So... I'm trying to convert my hunchentoot-cgi over to the new hunchentoot and running into some problems. My old approach was to do:
(progn (let* ((return-code (tbnl::return-code)) (reason-phrase (reason-phrase return-code)) (first-line (format nil "HTTP/1.1 ~D ~A" return-code reason-phrase))) (write-sequence (map 'list #'char-code first-line) out) (write-sequence tbnl::+crlf+ out) (tbnl::maybe-write-to-header-stream first-line))
(setf tbnl::*headers-sent* t) (setf (tbnl::content-type) nil) (sb-ext::run-program path nil :output out :environment env) nil)
but this doesn't seem to work anymore. My new approach is to try to use send-headers, but with some hackery to make it optionally more cgi-friendly: Index: headers.lisp =================================================================== --- headers.lisp (revision 3423) +++ headers.lisp (working copy) @@ -70,6 +70,8 @@ (:method (key value) (write-header-line key (princ-to-string value))))
+(defparameter *cgi-hack* nil) + (defun start-output (&key (content nil content-provided-p) (request *request*)) "Sends all headers and maybe the content body to @@ -84,7 +86,8 @@ ;; Read post data to clear stream - Force binary mode to avoid OCTETS-TO-STRING overhead. (raw-post-data :force-binary t) (let* ((return-code (return-code)) - (chunkedp (and (server-output-chunking-p *server*) + (chunkedp (and (not *cgi-hack*) + (server-output-chunking-p *server*) (eq (server-protocol request) :http/1.1) ;; only turn chunking on if the content ;; length is unknown at this point... @@ -196,12 +199,14 @@ ;; write all headers from the REPLY object (loop for (key . value) in (headers-out) when value - do (write-header-line (as-capitalized-string key) value)) + do (unless (and *cgi-hack* (equal key :content-type)) + (write-header-line (as-capitalized-string key) value))) ;; now the cookies (loop for (nil . cookie) in (cookies-out) do (write-header-line "Set-Cookie" (stringify-cookie cookie))) ;; all headers sent - (write-sequence +crlf+ *hunchentoot-stream*) + (unless *cgi-hack* + (write-sequence +crlf+ *hunchentoot-stream*)) (maybe-write-to-header-stream "") ;; access log message (when-let (access-logger (server-access-logger *server*))
The motivation for this hack being that the CGI script wants to send the content-type header, so we can't finish the headers here when running a CGI script.
Then I can do:
(let* ((tbnl::*cgi-hack* t) (stream (flexi-streams:make-flexi-stream (tbnl:send-headers) :external-format tbnl::+latin-1+))) (sb-ext::run-program path nil :output stream :environment env))
and this sort of works, but, 1) it's kind of a hack and 2) it either exacerbates the timeout situation or there's some other problem where the first request is handled promptly, but subsequent requests to 10 seconds or so while something times out. Not sure why this would be.
any thoughts on a good way to handle this?
thanks,
Cyrus