edicl / hunchentoot Goto Github PK
View Code? Open in Web Editor NEWWeb server written in Common Lisp
Home Page: https://edicl.github.io/hunchentoot/
Web server written in Common Lisp
Home Page: https://edicl.github.io/hunchentoot/
My server simply stops responding after a while and I see the message in the log.
Does it mean that when an exception happens in a thread it keeps hanging there?
Is there a way to prevent this situation? (I have lots of exceptions at the socket level and I don't know how to fix it)
Hello,
After running hunchentoot within Caveman framework, after a while I get this error :
Can't handle a new request, too many request threads already
and the server stop responding. I have this problem with latest hunchentoot package available on quicklisp at this time, and tried differents versions of SBCL but the problem is still the same.
It seems that doing some request with curl crash the server sooner than loading it with firefox.
I don't know what informations I can add to h elp.
Would you please consider adding a :description option to your system definition of hunchentoot?
The default method for acceptor-remove-session is
defined as
(defmethod acceptor-remove-session ((acceptor acceptor) (session t))
"Default implementation for the session removal hook function. This
function is called whenever a session is destroyed."
)
And the string is the last form, so it's not in fact a docstring, but a string which will be returned.
And in the documentation the return value is described as
acceptor-remove-session acceptor session => generalized-boolean
even though it's not a predicate.
Andrey Moskvitin via common-lisp.net to General, Apr 4
Hi,
For ACCESS-LOG-DESIGNATION default value is ERROR-OUTPUT. It is the cause of
littering REPL for SLIME users. Maybe better use NIL as default and for suppress
logging use a keyword :suppress?
(defmethod acceptor-access-log-destination ((acceptor acceptor))
(let ((destination (slot-value acceptor 'access-log-destination)))
(case destination
((nil) error-output)
(:suppress nil)
(otherwise destination))))
In this case, the logging will be sent to inferior-lisp and will not
interfere with.
Andrey
tbnl-devel site list
[email protected]
http://common-lisp.net/mailman/listinfo/tbnl-devel
In the documentation for the acceptor readers, acceptor-ssl-certificate-file is listed twice. I think the second one is supposed to be acceptor-listen-backlog.
Also, the following description of the acceptor readers begins with a special description of acceptor-listen-backlog. This makes the structure of the document less clear (in all other cases, descriptions following a list of symbols describe the symbols as a group).
As the title says. The same example:
(with-input-from-string (*standard-input* "ababad123")
(read-until "abad" :skip nil))
The problem is the line
(svref offsets i)
which should be
(svref offsets mismatch)
If you are going to test the differences, remember to use
(clrhash *find-string-hash*)
to clear the cache. Make sure you didn't use the code for read-until
anywhere else.
Nuff said. Users want it.
I have a relatively small hunchentoot web application that worked on mac os x yosemite and linux, and that now does not work on linux any more, maybe due to recent update to all quicklisp packages. The application still works without any problem in mac os x. I use CCL both on mac and linux.
This is the backtrace obtained with slime (after disabling error reporting by hunchentoot, otherwise nothing is printed on the log):
The log is given in the following gist, since it not visible if I paste it: https://gist.github.com/renzo-orsini/2ce407b383c25566466f
Hope there are examples about create server supporting HTTPS.
While make-instance
of easy-ssl-acceptor
there are keywords like :ssl-privatekey-file
:ssl-certificate-file
, which file should pass? Here is how I generate files with OpenSSL:
./CA.sh -newca
openssl genrsa -des3 -out server.key 1024
openssl req -new -key server.key -out server.csr
cp server.csr newreq.pem
./CA.sh -sign
cp newcert.pem server.crt
After those commands, here is the tree of the directory:
.
├── CA.sh
├── demoCA
│ ├── cacert.pem
│ ├── careq.pem
│ ├── certs
│ ├── crl
│ ├── index.txt
│ ├── index.txt.attr
│ ├── index.txt.attr.old
│ ├── index.txt.old
│ ├── newcerts
│ │ ├── BECF060AA4079FB0.pem
│ │ └── BECF060AA4079FB1.pem
│ ├── private
│ │ └── cakey.pem
│ ├── serial
│ └── serial.old
├── newcert.pem
├── newreq.pem
├── server.crt
├── server.csr
└── server.key
which file should pass?
The release process should put the literal version number into the .asd file and into packages.lisp. Otherwise, reading an old .asd file (e.g. by quicklisp) causes version number confusion.
@hanshuebner: I wonder if this ABCL specific problem? Running on osx-10.10.1. If it is ABCL specific, lemme know and I'll triage on my side when I get a chance (I suspect usocket)…
Hunchentoot-1.2.29 from quicklisp 2015-01-03 bound to port 2001 is failing when resolving IP6 for localhost. This is from my EHR application in which I'm using many other libraries in addition to Hunchentoot, but other than RESTAS, they are all for rendering the content, so therefore should not be part of this problem (and RESTAS, although it manipulates some Hunchentoot constructs, is also more of a "rendering" library than anything else).
wget http://localhost:2001
--2015-01-21 16:12:38-- http://localhost:2001/
Resolving localhost (localhost)... ::1, fe80::1, 127.0.0.1
Connecting to localhost (localhost)|::1|:2001... connected.
HTTP request sent, awaiting response... C-c C-c
gives the
[2015-01-21 16:12:38 [ERROR]] Error while processing connection: The value 8 is not of type (MEMBER 4).
Setting HUNCHENTOOT:*CATCH-ERRORS-P*
to nil doesn't signal an error, which is why I'm suspecting USOCKET here
When I use wget with an explicit IP4 address
wget http://127.0.0.1:2001
the request suceeds.
The docs talk about LOG-MESSAGE*, but it's LOG-MESSAGE.
I found a bug in static file managment.
If I start hunchentoot with:
(setf acceptor (make-instance 'hunchentoot:easy-acceptor
:port port
:document-root (truename "./static/")))
(start acceptor)
then hunchentoot return all .html files from ./static/ with Content-Type: text/html; charset=utf-8,
but other text/ files, like .js it returns without charset=... , and there is no way to change this.
If such .js file contains utf-8 text, than browser display it incorrectly.
Hans, can you fix this or may be advice how to do it, and i will try myself?
Session cookie without #: causes server to respond 500 instead of discarding. This blocks visitor from receiving new valid cookie.
While uploading a file with name using non-ASCII character, hunchentoot lead to charset encoding error. Here is the solution:
;; file: request.lisp
(defun parse-rfc2388-form-data (stream content-type-header external-format)
"Creates an alist of POST parameters from the stream STREAM which is
supposed to be of content type 'multipart/form-data'."
(let* ((parsed-content-type-header (rfc2388:parse-header content-type-header :value))
(boundary (or (cdr (rfc2388:find-parameter
"BOUNDARY"
(rfc2388:header-parameters parsed-content-type-header)))
(return-from parse-rfc2388-form-data))))
(loop for part in (rfc2388:parse-mime stream boundary)
for headers = (rfc2388:mime-part-headers part)
for content-disposition-header = (rfc2388:find-content-disposition-header headers)
for name = (cdr (rfc2388:find-parameter
"NAME"
(rfc2388:header-parameters content-disposition-header)))
when name
collect (cons name
(let ((contents (rfc2388:mime-part-contents part)))
(if (pathnamep contents)
(list contents
; Edit by muyinliu 20140303
;(rfc2388:get-file-name headers)
(convert-hack (rfc2388:get-file-name headers) external-format)
(rfc2388:content-type part :as-string t))
(convert-hack contents external-format)))))))
For now it works fine.
Please fix this. Thanks.
Hunchentoot is meant to hide error details from web users unless *show-lisp-errors-p* is overridden to true. But it doesn't always hide them. Here is how hunchentoot renders errors: a) if there's an error template html file use it, otherwise b) cook up a message whose level of detail depends on *show-lisp-errors-p* and *show-lisp-backtraces-p* As distributed, hunchentoot contains a 500.html error template file, so that is used and there is no need to cook up a message in code. The provided 500.html error template prints out the error message and backtrace, regardless of *show-lisp-errors-p* and *show-lisp-backtraces-p*. Refs: acceptor.lisp -> defgeneric #'acceptor-status-message documentation acceptor.lisp -> #'make-cooked-message -> +http-internal-server-error+ clause www/errors/500.html Workaround: Set your acceptor's error-template-directory to nil, causing hunchentoot to bypass (a) above. (make-instance 'easy-acceptor :port 8000 :error-template-directory nil)
I have latest 1.2.7 version hunchentoot, here is how I'm reproducing bug
T
Hi,
To get the matching reason for an error, applications have to maintain a list of messages for each status code.
For example:
(defun foo ()
(setf (hunchentoot:return-code*) hunchentoot:+http-method-not-allowed+)
"Method Not Allowed"))
Which seems kind of redundant because it exists in hunchentoot. This could be just like this:
(defun foo ()
(setf (hunchentoot:return-code*) hunchentoot:+http-method-not-allowed+)
(gethash hunchentoot:+http-method-not-allowed+ hunchentoot:*http-reason-phrase-map*))
It's weird that this variable isn't exported. As of now, I can't use it because the API might break anytime.
Is it possible to export it? I can open a PR for the exporting + docs.
Cheers,
Florian
some browsers still don't know XSLT
debugger invoked on a SIMPLE-ERROR in thread #<THREAD
"hunchentoot-worker-127.0.0.1:43115" RUNNING
{C4F7F19}>:
Recursive lock attempt #S(SB-THREAD:MUTEX
:NAME "global-message-log-lock"
:%OWNER #<SB-THREAD:THREAD
"hunchentoot-worker-127.0.0.1:43115" RUNNING
{C4F7F19}>
:STATE 1).
Hi;
I cannot suspend session among page refreshes. When I login to the page and refresh two times the page that is to be loaded when session is not created is shown as before my login. How to handle this. I create all the page html with lisp dynamically. Is that the problem?
I have a very lon lines of code to be share here for inconvenience of readers. some portion of the page that decides whether login or not is drawer by the following portion of the compose-home-page function:
(div (list :id "toolbar" :style "height: 45px; border: 1px solid;")
(morph-name)
(morph-search)
(div (list :id "online-xor-offline"
:style "height: 45px; border: 1px solid; float:left;")
(if (signed-in-p);!!!t
(div (list :id "if-online")
(div (list :id "numbers-online" :style "border:1px solid; float:left;") "123 users online")
(div (list :id "username" :style "border:1px solid; float:left;") (session-value '*username));!!!"sess val"
(button (list :onclick "ajaxlogout()") "logout")
(a (list :onclick "writingdesk()") "writing desk")
(a (list :onclick "notepad()") "note pad")
(a (list :onclick "published()") "published")
(a (list :onclick "preferences()") "preferences"))
(div (list :id "if-offline")
(morph-sign-in-form)
(morph-signup-link)
))))
authentication functions that have role in above code:
(defun signed-in-p ()
(if (session-value '*signed-in)
t
nil))
;;test sign-up
(defun signed-up-p (x y)
(if (with-connection *conn1spec*
(query (:select 'username 'password :from 'users.users
:where (:and (:= 'username x)
(:= 'password y)))))
t
nil))
;;make sign in. ajax version. composes only specific morphs to place.
(defun sign-in ()
(let ((username (parameter "username"))
(password (parameter "password")))
(if (signed-up-p username password)
(progn
(start-session)
(setf (session-value '*username *session*) username)
(setf (session-value '*signed-in) t)
(div (list :id "if-online")
(div (list :id "numbers-online" :style "border:1px solid; float:left;") "123 users online")
(div (list :id "username" :style "border:1px solid; float:left;") (session-value '*username))
(button (list :onclick "ajaxlogout()") "logout")
(a (list :onclick "writingdesk()") "writing desk")
(a (list :onclick "notepad") "note pad")
(a (list :onclick "published") "published")
(a (list :onclick "preferences") "preferences")))
(with-output-to-string (s)
(princ (morph-sign-in-form) s)
(princ "No record found!" s)
(princ (morph-signup-link) s)
))))
On Linux:
setcap 'cap_net_bind_service=+ep' /path/to/program
Hi,
After some quick testing, I've found that, in my humble opinion, hunchentoot sessions are lacking some (from today's standards) necessary features.
remove-session
should send a Set-Cookie
header to remove the session cookie (e.g. Set-Cookie: hunchentoot-session=deleted; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT
)I understand that these are "breaking changes". I wonder if you'd still be interested in accepting these features. I think I could send you a pull request if you'd like so.
Cheers,
Florian
The HTTP standard has no way for a client to specify a character encoding for www-form-urlencoded POST data. So you have to guess. And if you guess utf-8 and you end up being wrong and generating a UTF-8 parse error, then there is no way to recover because maybe-read-post-parameters is hard-coded to call abort-request-handler if the parse fails.
There's a hacky workaround for this by always parsing first to latin-1 (which can't fail) and then converting to UTF-8 afterwards, but it seems like there really ought to be a better way to handle this.
Hunchentoot uses CHUNGA's as-keyword method to convert strings to keywords. In several cases, the strings are coming from external sources (e.g. method in incoming requests), and by interning arbitrary strings, memory can be leaking.
Hi,
PROCESS-CONNECTION in v1.2.0 uses FORCE-OUTPUT instead of FINISH-OUTPUT again.
Sequence
(FORCE-OUTPUT hunchentoot-stream)
(CLOSE hunchentoot-stream :abort t)
has a race condition, because FORCE-OUTPUT does not wait till all the buffered data is sent and CLOSE discards the buffered data.
See the mailing list archive for more details: http://lists.common-lisp.net/pipermail/tbnl-devel/2011-February/005411.html
Ilya
Hello,
I have noticed this error while running Hunchentoot with Clozure CL on a GNU/Linux box:
error Filename "[...]/hunchentoot-1.2.21/www/errors\\//404.html"
contains illegal character #\/ during error processing, sending cooked
message to client
I am not sure to understand the reason of this problem.
Is there anything I can do to help?
Thanks!
Camille
This is a documented function, but it does not appear to be exported.
1.2.5 also present in documentation so please regenerate it
maybe there should be a chapter "serving static files", too.
Invalid URLs with non-hex characters after the %
return an internal-server-error (500) instead of a proper 400 Bad Request
result.
The version of Hunchentoot in Quicklisp is currently 1.1.1, and the current version is 1.2.1 . Please ensure Quicklisp is updated with the new release. I would file the issue myself, but I'm not sure where the "official" Hunchentoot is located.
In addition, the download link at http://weitz.de/hunchentoot/ is broken and returns 404.
Thank you,
Krzysztof Drewniak
The Hunchentoot shipped with February 2012 Quicklisp (hunchentoot-1.2.2) fails to work when the :HUNCHENTOOT-NO-SSL keyword in present in FEATURES. For systems unable to load the SSL libraries via CFFI (which happens even with otherwise well supported implementations on outlier platforms, like SBCL on OpenSolaris), this renders a naked HTTP only Hunchentoot unusable.
Will followup with the (hopefully) trivial patch to fix this.
I'm probably doing it wrong. Here is the most minimal example I can think of:
(hunchentoot:start (make-instance 'hunchentoot:easy-acceptor :document-root "." :error-template-directory "error-templates" :port 8080))
I expect the error-templates/404.html file to display when I visit http://localhost:8080. Thoughts?
It would be nice if hunchentoot would help with multipart responses.
Hints from IRC discussion:
Proposed interface:
(defun my-handler ()
(hunchentoot:render-multipart "<h1>rendering in progress.</h1>")
(sleep 120)
(hunchentoot:render-multipart "<h1>rendering done.</h1>"))
The first call of this function (within a single REQUEST) would generate an ID, send all appropriate headers and the first part of the output. Further calls would just reuse the existing ID to push new data.
When browser request URI like this: /中文字符
(URI contains non-ASCII character), hunchentoot will throw an exception:
The value 20013 is not of type (UNSIGNED-BYTE 8).
[Condition of type TYPE-ERROR]
Restarts:
0: [ABORT] abort thread (#<THREAD "hunchentoot-worker-127.0.0.1:58011" RUNNING {1003920143}>)
Backtrace:
0: ((SB-IMPL::OPTIMIZED-DATA-VECTOR-SET (UNSIGNED-BYTE 8)) #<unavailable argument> #<unavailable argument> #<unavailable argument>)
1: (VECTOR-PUSH 20013 #(47))
2: ((LABELS HUNCHENTOOT::PUSH-INTEGER :IN HUNCHENTOOT:URL-DECODE) 20013)
3: (HUNCHENTOOT:URL-DECODE "/中文字符" #<FLEXI-STREAMS::FLEXI-UTF-8-FORMAT (:UTF-8 :EOL-STYLE :LF) {1008E2E813}>)
4: (HUNCHENTOOT:REQUEST-PATHNAME #<HUNCHENTOOT:REQUEST {1003931673}> NIL)
5: ((:METHOD HUNCHENTOOT:ACCEPTOR-DISPATCH-REQUEST (HUNCHENTOOT:ACCEPTOR T)) #<HUNCHENTOOT:EASY-ACCEPTOR (host *, port 9000)> #<HUNCHENTOOT:REQUEST {1003931673}>) [fast-method]
6: ((:METHOD HUNCHENTOOT:ACCEPTOR-DISPATCH-REQUEST (HUNCHENTOOT:EASY-ACCEPTOR T)) #<HUNCHENTOOT:EASY-ACCEPTOR (host *, port 9000)> #<HUNCHENTOOT:REQUEST {1003931673}>) [fast-method]
7: ((:METHOD HUNCHENTOOT:HANDLE-REQUEST (HUNCHENTOOT:ACCEPTOR HUNCHENTOOT:REQUEST)) #<HUNCHENTOOT:EASY-ACCEPTOR (host *, port 9000)> #<HUNCHENTOOT:REQUEST {1003931673}>) [fast-method]
8: ((:METHOD HUNCHENTOOT:PROCESS-REQUEST (T)) #<HUNCHENTOOT:REQUEST {1003931673}>) [fast-method]
9: (HUNCHENTOOT::DO-WITH-ACCEPTOR-REQUEST-COUNT-INCREMENTED #<HUNCHENTOOT:EASY-ACCEPTOR (host *, port 9000)> #<CLOSURE (LAMBDA NIL :IN HUNCHENTOOT:PROCESS-CONNECTION) {100393090B}>)
10: ((:METHOD HUNCHENTOOT:PROCESS-CONNECTION (HUNCHENTOOT:ACCEPTOR T)) #<HUNCHENTOOT:EASY-ACCEPTOR (host *, port 9000)> #<USOCKET:STREAM-USOCKET {100391F083}>) [fast-method]
11: ((:METHOD HUNCHENTOOT:PROCESS-CONNECTION :AROUND (HUNCHENTOOT:ACCEPTOR T)) #<HUNCHENTOOT:EASY-ACCEPTOR (host *, port 9000)> #<USOCKET:STREAM-USOCKET {100391F083}>) [fast-method]
12: ((FLET HUNCHENTOOT::PROCESS-CONNECTION% :IN HUNCHENTOOT::HANDLE-INCOMING-CONNECTION%) #<HUNCHENTOOT:EASY-ACCEPTOR (host *, port 9000)> #<USOCKET:STREAM-USOCKET {100391F083}>)
13: ((LAMBDA NIL :IN BORDEAUX-THREADS::BINDING-DEFAULT-SPECIALS))
14: ((FLET #:WITHOUT-INTERRUPTS-BODY-1156 :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE))
15: ((FLET SB-THREAD::WITH-MUTEX-THUNK :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE))
16: ((FLET #:WITHOUT-INTERRUPTS-BODY-359 :IN SB-THREAD::CALL-WITH-MUTEX))
17: (SB-THREAD::CALL-WITH-MUTEX #<CLOSURE (FLET SB-THREAD::WITH-MUTEX-THUNK :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE) {2AAAB541EEAB}> #<SB-THREAD:MUTEX "thread result lock" owner: #<SB-THREAD:THR..
18: (SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE #<SB-THREAD:THREAD "hunchentoot-worker-127.0.0.1:58011" RUNNING {1003920143}> NIL #<CLOSURE (LAMBDA NIL :IN BORDEAUX-THREADS::BINDING-DEFAULT-SPECIALS) {..
19: ("foreign function: call_into_lisp")
--more--
After compare file request.lisp between v1.2.31 and v1.2.34, I found a solution: change line 606 from (let ((path (url-decode (script-name request))))
to (let ((path (script-name request)))
. Call function url-decode
here is unnecessary after the script-name
has already be decoded in method initialize-instance
(line 185).
Such as:
(hunchentoot:define-easy-handler (say-yo :uri "/哈哈") ()
(setf (hunchentoot:content-type*) "text/plain")
(format nil "hello"))
I'm using brower requestng URL http://xxx/哈哈, Hunchentoot reported 404:
Not Found
The requested URL /%E5%93%88%E5%93%88 was not found on this server.
Hello everyone, I'm new here and am in the process of updating Hunchensocket to adhere to the Websocket protocol ver. 13 RFC 6455.
I've come with a problem and a proposed solution (not my own), and I'd like it verified for backwards-compatibility, before it gets committed. Here it is, in file 'headers.lisp' on line 113 (as of 21.12.2013), replace:
(t (setf (header-out :connection) "Close")) ))
with:
(t (unless (header-out-set-p :connection)
(setf (header-out :connection) "Close"))) ))
Best regards,
Andrej
Currently, the default-document-directory uses asdf:system-relative-pathname to determine the default document directory, which does not work if ASDF is not present or if :hunchentoot is not available as system, which makes loading FASL files fail. This should be changed.
I’ve been using Hunchentoot for a couple of years with no problem. Yesterday some code that had been working stopped working. An example of the problem is below.
Basically, it seems like with-output-to-string(standard-output) no longer results in Hunchentoot writing the result to the client. I’m using ccl version 1.10-r16196 and the latest Hunchentoot from Quicklisp. When I run the code below in Slime and then call "curl -G http://127.0.0.1:9876/echo/foo/bar/baz", I can connect to 127.0.0.1:9876, I see the entry in the access log, log-message gets called, but nothing is sent back.
Has something changed in Hunchentoot or have I hosed my environment in some other way?
Thanks,
Patrick
(in-package :common-lisp-user)
(ql:quickload :hunchentoot)
(defpackage :org.softwarematters.hunchentoot-issue
(:nicknames :hunchentoot-issue)
(:use :common-lisp
:hunchentoot))
(in-package :hunchentoot-issue)
;;; Define the web server acceptor
(defparameter *test-acceptor*
(make-instance 'easy-acceptor
:port 9876
:document-root #p"/Users/Patrick/src/lisp/web/"
:access-log-destination "/tmp/issue-access.log"
:message-log-destination "/tmp/issue-message.log"))
;;; Utilities
(defconstant +issue-log-file+ #p"/tmp/issue.log")
(defun log-message (message)
(with-open-file (log +issue-log-file+
:direction :output
:if-exists :append
:if-does-not-exist :create)
(format log "~A~%" message)))
;;; Define handler
(defun echo-handler ()
(log-message (request-uri*))
(with-output-to-string (*standard-output*)
(request-uri*)))
(setq *dispatch-table*
(list (create-regex-dispatcher "^/echo/.*" 'echo-handler)))
;;; Start the web server
(start *test-acceptor*)
;(hunchentoot:stop *test-acceptor*)
In quicklisp 2013-11-11, hunchentoot-1.2.21, loading hunchentoot on CLISP leads to error:
MAKE-PATHNAME: Illegal :DIRECTORY argument (:ABSOLUTE "home" "hijarian"
"projects" "others" "cl-test-grid" "work-dir" "agent" "quicklisp" "dists"
"quicklisp" "software" "hunchentoot-1.2.21" "www" "errors/")
signaled from the default-initargs in of the acceptor class:
:error-template-directory (load-time-value (default-document-directory "errors/")))
I guess it is introduced by commit 8d22bc7
An incoming request has
Content-Type: application/json; charset=UTF-8
but the server treats it as latin-1 (the default). It seems the code correctly parses the character set from the content type, but ignores it unless the type is "text". See parse-content-type.
This is documented as a way to call a function when a session is removed. It does not appear to be implemented anywhere in version 1.2.1.
Reading the doc here http://weitz.de/hunchentoot/#easy-handlers
If parameter-type is 'INTEGER and the parameter string consists solely
of decimal digits, var's value will be the corresponding integer, otherwise NIL.
But when I enter "50jj99" to the form, the parameter gets value 50.
The doc and implementation disagree.
Hi,
Such a method would just regenerate the session id without changing anything else in the data held by the session.
This method helps to prevent against session fixation attacks. It should be called when logging a user if a session already exists. This, of course, should be done by the application using hunchentoot.
Would you agree to add this method to hunchentoot?
If you need a patch, I'm willing to open a PR.
Cheers,
Florian
handle-static-files should call an acceptor hook to validate a file before it is served. The hook can verify that the file is under certain directories (document-root or some such). The default should be safe.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.