[hunchentoot-devel] hunchentoot-cgi and the new hunchentoot regime

Cyrus Harmon ch-tbnl at bobobeach.com
Sat Jul 19 20:40:20 UTC 2008


So... any input/suggestions on how to hack start-output to deal with  
CGI-style content?

thanks,

Cyrus

On Jul 11, 2008, at 12:20 AM, Cyrus Harmon wrote:

> 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
>
> _______________________________________________
> tbnl-devel site list
> tbnl-devel at common-lisp.net
> http://common-lisp.net/mailman/listinfo/tbnl-devel




More information about the Tbnl-devel mailing list