Revision: 4639
Author: hans
URL: http://bknr.net/trac/changeset/4639
Rework logging API, log to *error-output* by default.
U trunk/thirdparty/hunchentoot/acceptor.lisp
U trunk/thirdparty/hunchentoot/doc/index.xml
U trunk/thirdparty/hunchentoot/headers.lisp
U trunk/thirdparty/hunchentoot/log.lisp
U trunk/thirdparty/hunchentoot/misc.lisp
U trunk/thirdparty/hunchentoot/packages.lisp
U trunk/thirdparty/hunchentoot/request.lisp
U trunk/thirdparty/hunchentoot/session.lisp
U trunk/thirdparty/hunchentoot/specials.lisp
U trunk/thirdparty/hunchentoot/taskmaster.lisp
Change set too large, please see URL above
Revision: 4637
Author: hans
URL: http://bknr.net/trac/changeset/4637
Improve error handling. Move code around in START-OUTPUT so that
if content has been supplied, it is first converted to binary if
necessary before anything is written to the client. Move error
logging up to process-request. If START-OUTPUT fails, try logging
and sending error information back to the client.
U trunk/thirdparty/hunchentoot/acceptor.lisp
U trunk/thirdparty/hunchentoot/headers.lisp
U trunk/thirdparty/hunchentoot/request.lisp
Modified: trunk/thirdparty/hunchentoot/acceptor.lisp
===================================================================
--- trunk/thirdparty/hunchentoot/acceptor.lisp 2011-01-21 22:13:30 UTC (rev 4636)
+++ trunk/thirdparty/hunchentoot/acceptor.lisp 2011-01-21 22:31:40 UTC (rev 4637)
@@ -437,11 +437,6 @@
handler."
(handler-bind ((error
(lambda (cond)
- (when *log-lisp-errors-p*
- (log-message *lisp-errors-log-level*
- "~A~@[~%~A~]"
- cond
- (and *log-lisp-backtraces-p* (get-backtrace))))
;; if the headers were already sent, the error
;; happened within the body and we have to close
;; the stream
Modified: trunk/thirdparty/hunchentoot/headers.lisp
===================================================================
--- trunk/thirdparty/hunchentoot/headers.lisp 2011-01-21 22:13:30 UTC (rev 4636)
+++ trunk/thirdparty/hunchentoot/headers.lisp 2011-01-21 22:31:40 UTC (rev 4637)
@@ -70,22 +70,15 @@
(:method (key value)
(write-header-line key (princ-to-string value))))
-(defun start-output (&key (content nil content-provided-p)
- (request *request*))
+(defun start-output (&optional (content nil content-provided-p))
"Sends all headers and maybe the content body to
*HUNCHENTOOT-STREAM*. Returns immediately and does nothing if called
more than once per request. Handles the supported return codes
accordingly. Called by PROCESS-REQUEST and/or SEND-HEADERS. Returns
the stream to write to."
- ;; send headers only once
- (when *headers-sent*
- (return-from start-output))
- (setq *headers-sent* t)
- ;; 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 (acceptor-output-chunking-p *acceptor*)
- (eq (server-protocol request) :http/1.1)
+ (eq (server-protocol *request*) :http/1.1)
;; only turn chunking on if the content
;; length is unknown at this point...
(null (or (content-length*) content-provided-p))
@@ -94,11 +87,11 @@
;; own content
(member return-code *approved-return-codes*)))
(reason-phrase (reason-phrase return-code))
- (request-method (request-method request))
+ (request-method (request-method *request*))
(head-request-p (eq request-method :head))
content-modified-p)
(multiple-value-bind (keep-alive-p keep-alive-requested-p)
- (keep-alive-p request)
+ (keep-alive-p *request*)
(when keep-alive-p
(setq keep-alive-p
;; use keep-alive if there's a way for the client to
@@ -115,7 +108,7 @@
(cond (keep-alive-p
(setf *close-hunchentoot-stream* nil)
(when (and (acceptor-read-timeout *acceptor*)
- (or (not (eq (server-protocol request) :http/1.1))
+ (or (not (eq (server-protocol *request*) :http/1.1))
keep-alive-requested-p))
;; persistent connections are implicitly assumed for
;; HTTP/1.1, but we return a 'Keep-Alive' header if the
@@ -162,20 +155,14 @@
"The server could not verify that you are authorized to access the document requested. Either you supplied the wrong credentials \(e.g., bad password), or your browser doesn't understand how to supply the credentials required.")
((#.+http-forbidden+)
(format nil "You don't have permission to access ~A on this server."
- (escape-for-html (script-name request))))
+ (escape-for-html (script-name *request*))))
((#.+http-not-found+)
(format nil "The requested URL ~A was not found on this server."
- (escape-for-html (script-name request))))
+ (escape-for-html (script-name *request*))))
((#.+http-bad-request+)
"Your browser sent a request that this server could not understand.")
(otherwise ""))
(address-string))))))
- ;; start with status line
- (let ((first-line
- (format nil "HTTP/1.1 ~D ~A" return-code reason-phrase)))
- (write-sequence (map 'list #'char-code first-line) *hunchentoot-stream*)
- (write-sequence +crlf+ *hunchentoot-stream*)
- (maybe-write-to-header-stream first-line))
(when (and (stringp content)
(not content-modified-p)
(starts-with-one-of-p (or (content-type*) "")
@@ -192,6 +179,18 @@
;; the Content-Length header properly; maybe the user specified
;; a different content length, but that will wrong anyway
(setf (header-out :content-length) (length content)))
+ ;; send headers only once
+ (when *headers-sent*
+ (return-from start-output))
+ (setq *headers-sent* t)
+ ;; Read post data to clear stream - Force binary mode to avoid OCTETS-TO-STRING overhead.
+ (raw-post-data :force-binary t)
+ ;; start with status line
+ (let ((first-line
+ (format nil "HTTP/1.1 ~D ~A" return-code reason-phrase)))
+ (write-sequence (map 'list #'char-code first-line) *hunchentoot-stream*)
+ (write-sequence +crlf+ *hunchentoot-stream*)
+ (maybe-write-to-header-stream first-line))
;; write all headers from the REPLY object
(loop for (key . value) in (headers-out*)
when value
Modified: trunk/thirdparty/hunchentoot/request.lisp
===================================================================
--- trunk/thirdparty/hunchentoot/request.lisp 2011-01-21 22:13:30 UTC (rev 4636)
+++ trunk/thirdparty/hunchentoot/request.lisp 2011-01-21 22:31:40 UTC (rev 4637)
@@ -212,26 +212,32 @@
"Standard implementation for processing a request. You should not
change or replace this functionality unless you know what you're
doing."
- (let (*tmp-files* *headers-sent*)
+ (let (*tmp-files*
+ *headers-sent*
+ (*request* request))
(unwind-protect
- (with-mapped-conditions ()
- (let* ((*request* request))
- (multiple-value-bind (body error backtrace)
- ;; skip dispatch if bad request
- (when (eql (return-code *reply*) +http-ok+)
- (catch 'handler-done
- (handle-request *acceptor* *request*)))
- (when error
- (setf (return-code *reply*)
- +http-internal-server-error+))
- (start-output :content (cond ((and error *show-lisp-errors-p*)
- (format nil "<pre>~A~@[~%~%Backtrace:~A~]</pre>"
- (escape-for-html (format nil "~A" error))
- (when *show-lisp-backtraces-p*
- (escape-for-html (format nil "~A" backtrace)))))
- (error
- "An error has occured.")
- (t body))))))
+ (with-mapped-conditions ()
+ (labels
+ ((report-error-to-client (error &optional backtrace)
+ (setf (return-code *reply*) +http-internal-server-error+)
+ (when *log-lisp-errors-p*
+ (log-message *lisp-errors-log-level* "~A~@[~%~A~]" error backtrace))
+ (start-output (if *show-lisp-errors-p*
+ (format nil "<pre>~A</pre>" (escape-for-html (format nil "~A" error)))
+ "An error has occured") )))
+ (multiple-value-bind (body error backtrace)
+ ;; skip dispatch if bad request
+ (when (eql (return-code *reply*) +http-ok+)
+ (catch 'handler-done
+ (handle-request *acceptor* *request*)))
+ (when error
+ ;; error occured in request handler
+ (report-error-to-client error backtrace))
+ (handler-case
+ (start-output body)
+ (error (e)
+ ;; error occured while writing to the client. attempt to report.
+ (report-error-to-client e))))))
(dolist (path *tmp-files*)
(when (and (pathnamep path) (probe-file path))
;; the handler may have chosen to (re)move the uploaded
Revision: 4631
Author: edi
URL: http://bknr.net/trac/changeset/4631
ECL fix
U trunk/thirdparty/hunchentoot/CHANGELOG
U trunk/thirdparty/hunchentoot/specials.lisp
Modified: trunk/thirdparty/hunchentoot/CHANGELOG
===================================================================
--- trunk/thirdparty/hunchentoot/CHANGELOG 2011-01-21 18:58:17 UTC (rev 4630)
+++ trunk/thirdparty/hunchentoot/CHANGELOG 2011-01-21 19:01:44 UTC (rev 4631)
@@ -1,3 +1,4 @@
+Patch for compilation with ECL (Sohail Somani)
Fix DEFINE-EASY-HANDLER for multiple acceptors (Nicolas Neuss)
Revived *SHOW-LISP-BACKTRACES-P*
Made sure "100 Continue" is returned even if the client sends "Expect: 100-continue" twice (reported by Gordon Sims)
Modified: trunk/thirdparty/hunchentoot/specials.lisp
===================================================================
--- trunk/thirdparty/hunchentoot/specials.lisp 2011-01-21 18:58:17 UTC (rev 4630)
+++ trunk/thirdparty/hunchentoot/specials.lisp 2011-01-21 19:01:44 UTC (rev 4631)
@@ -315,9 +315,10 @@
"The default connection timeout used when an acceptor is reading
from and writing to a socket stream.")
-(define-symbol-macro *supports-threads-p*
- #+:lispworks t
- #-:lispworks bt:*supports-threads-p*)
+(eval-when (:compile-toplevel :load-toplevel :execute)
+ (define-symbol-macro *supports-threads-p*
+ #+:lispworks t
+ #-:lispworks bt:*supports-threads-p*))
(defvar *global-session-db-lock*
(load-time-value (and *supports-threads-p* (make-lock "global-session-db-lock")))