Merge pull request #27 from mtstickney/delayed_session_control

Delayed-response session expiration
This commit is contained in:
Eitaro Fukamachi 2018-09-05 10:56:11 +09:00 committed by GitHub
commit 17756b63fd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 7 deletions

View file

@ -35,12 +35,18 @@
(if new-session-p (if new-session-p
(list :id sid :new-session t :change-id nil :expire nil) (list :id sid :new-session t :change-id nil :expire nil)
(list :id sid :new-session nil :change-id nil :expire nil))) (list :id sid :new-session nil :change-id nil :expire nil)))
(let ((res (funcall app env))) (let ((res (funcall app env))
(if (and (not keep-empty) (process-session (lambda (result)
new-session-p (if (and (not keep-empty)
(zerop (hash-table-count session))) new-session-p
res (zerop (hash-table-count session)))
(finalize store state env res)))))) 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") "Middleware for session management")
(defun finalize (store state env res) (defun finalize (store state env res)

View file

@ -6,7 +6,7 @@
:lack.test)) :lack.test))
(in-package :t.lack.middleware.session) (in-package :t.lack.middleware.session)
(plan 6) (plan 7)
(ok (lack.session.state:make-state) (ok (lack.session.state:make-state)
"Base class of session state") "Base class of session state")
@ -126,6 +126,36 @@
"new session is not expired")) "new session is not expired"))
(is body '("hi") "body")))) (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" (subtest ":keep-empty nil"
(let ((app (builder (let ((app (builder
(:session :keep-empty nil) (:session :keep-empty nil)