diff --git a/src/middleware/session.lisp b/src/middleware/session.lisp index 5b9dbfe..d572f91 100644 --- a/src/middleware/session.lisp +++ b/src/middleware/session.lisp @@ -35,12 +35,18 @@ (if new-session-p (list :id sid :new-session t :change-id nil :expire nil) (list :id sid :new-session nil :change-id nil :expire nil))) - (let ((res (funcall app env))) - (if (and (not keep-empty) - new-session-p - (zerop (hash-table-count session))) - res - (finalize store state env res)))))) + (let ((res (funcall app env)) + (process-session (lambda (result) + (if (and (not keep-empty) + new-session-p + (zerop (hash-table-count session))) + result + (finalize store state env result))))) + (typecase res + (function (lambda (responder) + (funcall res (lambda (result) + (funcall responder (funcall process-session result)))))) + (t (funcall process-session res))))))) "Middleware for session management") (defun finalize (store state env res) diff --git a/t/middleware/session.lisp b/t/middleware/session.lisp index 2c3082c..cdffc8e 100644 --- a/t/middleware/session.lisp +++ b/t/middleware/session.lisp @@ -6,7 +6,7 @@ :lack.test)) (in-package :t.lack.middleware.session) -(plan 6) +(plan 7) (ok (lack.session.state:make-state) "Base class of session state") @@ -126,6 +126,36 @@ "new session is not expired")) (is body '("hi") "body")))) +(subtest "session expiration with delayed response" + (let ((app (builder + :session + (lambda (env) + (if (equal (getf env :path-info) "/delayed-expire") + (lambda (responder) + (setf (getf (getf env :lack.session.options) :expire) t) + (funcall responder '(200 () ("hi")))) + (lambda (responder) + (funcall responder '(200 () "hi"))))))) + session) + ;; Get a session. + (funcall (funcall app (generate-env "/")) + (lambda (result) + (destructuring-bind (status headers body) result + (declare (ignore status body)) + (setf session + (ppcre:scan-to-strings "(?<=lack.session=)[^;]+" + (getf headers :set-cookie "")))))) + ;; Make sure it expires when expiration is set in a delayed response. + (funcall (funcall app (generate-env "/delayed-expire" :cookies `(("lack.session" . ,session)))) + (lambda (result) + (destructuring-bind (status headers body) result + (declare (ignore status body)) + (let ((cookie (cookie:parse-set-cookie-header (getf headers :set-cookie) "" ""))) + (is (cookie:cookie-value cookie) session + "Set-Cookie header is for existing session") + (ok (<= (cookie:cookie-expires cookie) (get-universal-time)) + "Session expired"))))))) + (subtest ":keep-empty nil" (let ((app (builder (:session :keep-empty nil)