#lang scheme/base
(require "web-export.ss"
"web-support.scm"
(file "util.scm")
(file "time.scm")
(file "record.scm")
(file "repository.scm")
(lib "time.ss" "srfi" "19"))
(provide session-put-val!
session-get-val
session-id
session-get-hash
session-replace-hash!
get-session-object
session-remove-entry!
sessioned-response
make-fresh-session
remove-session
cookied-response
cookie-val
flash-create!
flash-get!
)
(define SESSION_KEY_LENGTH 20)
(define (make-fresh-session)
(let ((rec (fresh-rec-from-data '((type . session))
#:stamp-time #t
#:id-length SESSION_KEY_LENGTH)))
(store-rec! rec)
(values (rec-id rec) rec)))
(define (remove-session sesh)
(delete-rec! sesh))
(define (get-session-object session-key)
(and (record-id-stored? session-key)
(load-rec session-key)))
(define (session-put-val! sesh key val)
(rec-set-prop! sesh key val)
(store-rec! sesh)
sesh)
(define (session-get-hash sesh)
(rec-data sesh))
(define (session-replace-hash! sesh hash)
(rec-set-data! sesh hash)
(store-rec! sesh)
sesh)
(define (session-get-val sesh key (missing-val #f))
(rec-prop sesh key missing-val))
(define (session-id sesh)
(rec-id sesh))
(define (session-remove-entry! sesh key)
(rec-remove-prop! sesh key)
(store-rec! sesh)
sesh)
(define-syntax sessioned-response
(syntax-rules ()
((_ req (sesh-iden) body ...)
(let* ((sesh-id (cookie-val req "sesh"))
(sesh-iden (and sesh-id (get-session-object sesh-id))))
(if (not sesh-iden)
(receive (fresh-sesh-id sesh-iden) (make-fresh-session)
(cookied-response "sesh" fresh-sesh-id
body ...))
(let ((body-lst (list body ...)))
(or (single-response-promise-in-list body-lst)
(single-response/full-in-list body-lst)
(list-response body-lst))))))))
(define (cookied-response cookie-key-str cookie-val-str
#:expire-in (expire-in THIRTY_DAYS)
. content-lst)
(let ((headers (list (make-header #"Set-Cookie"
(string->bytes/utf-8
(format "~A=~A; expires=~A; path=~A"
cookie-key-str cookie-val-str
(cookie-expiry-time expire-in)
"/"))))))
(aif (single-response-promise-in-list content-lst)
(response-from-promise it #:headers headers)
(list-response content-lst #:extras headers))))
(define (cookie-expiry-time secs-from-now)
(date->string (time-utc->date (make-time 'time-utc 0
(+ (current-seconds) secs-from-now))
0)
"~a, ~d-~b-~Y ~T GMT"))
(define (cookie-val req key-str)
(and-let* ((header-binds (request-headers req))
((exists-binding? 'cookie header-binds))
(cookie-strs (pregexp-split "; "
(extract-binding/single 'cookie
(request-headers req)))))
(any (lambda (kv-str)
(match (pregexp-split "=" kv-str)
((list key val)
(and (string=? key-str key) val))
(else #f)))
cookie-strs)))
(define (flash-create! sesh key val)
(session-put-val! sesh key val))
(define (flash-get! sesh key)
(let ((val (session-get-val sesh key)))
(session-remove-entry! sesh key)
val))