factor/extra/http/server/sessions/sessions.factor

115 lines
3.1 KiB
Factor
Raw Normal View History

2008-02-29 01:57:38 -05:00
! Copyright (C) 2008 Doug Coleman, Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: assocs calendar kernel math.parser namespaces random
boxes alarms new-slots accessors http http.server
quotations hashtables sequences ;
IN: http.server.sessions
! ! ! ! ! !
! WARNING: this session manager is vulnerable to XSRF attacks
! ! ! ! ! !
2008-03-03 03:19:36 -05:00
GENERIC: init-session ( responder -- )
M: dispatcher init-session drop ;
2008-03-03 03:19:36 -05:00
TUPLE: session-manager responder sessions ;
2008-02-29 01:57:38 -05:00
: <session-manager> ( responder class -- responder' )
2008-03-03 03:19:36 -05:00
>r H{ } clone session-manager construct-boa r>
2008-02-29 01:57:38 -05:00
construct-delegate ; inline
TUPLE: session id manager namespace alarm ;
: <session> ( id manager -- session )
H{ } clone <box> \ session construct-boa ;
: timeout ( -- dt ) 20 minutes ;
: cancel-timeout ( session -- )
2008-02-29 11:37:39 -05:00
alarm>> [ cancel-alarm ] if-box? ;
2008-02-29 01:57:38 -05:00
: delete-session ( session -- )
dup cancel-timeout
dup manager>> sessions>> delete-at ;
: touch-session ( session -- )
dup cancel-timeout
dup [ delete-session ] curry timeout later
swap session-alarm >box ;
: session ( -- assoc ) \ session get namespace>> ;
: sget ( key -- value ) session at ;
: sset ( value key -- ) session set-at ;
: schange ( key quot -- ) session swap change-at ; inline
: new-session ( responder -- id )
[ sessions>> generate-key dup ] keep
[ <session> dup touch-session ] keep
2008-03-03 03:19:36 -05:00
[ swap \ session [ responder>> init-session ] with-variable ] 2keep
2008-02-29 01:57:38 -05:00
>r over r> sessions>> set-at ;
: get-session ( id responder -- session )
sessions>> tuck at* [
nip dup touch-session
] [
2drop f
] if ;
: call-responder/session ( request path responder session -- response )
2008-03-03 03:19:36 -05:00
\ session set responder>> call-responder ;
2008-02-29 01:57:38 -05:00
: sessions ( -- manager/f )
\ session get dup [ manager>> ] when ;
GENERIC: session-link* ( url query sessions -- string )
M: object session-link* 2drop url-encode ;
: session-link ( url query -- string ) sessions session-link* ;
TUPLE: url-sessions ;
: <url-sessions> ( responder -- responder' )
url-sessions <session-manager> ;
: sess-id "factorsessid" ;
M: url-sessions call-responder ( request path responder -- response )
pick sess-id query-param over get-session [
call-responder/session
] [
new-session nip sess-id set-query-param
2008-03-03 03:19:36 -05:00
dup request-url <temporary-redirect>
2008-02-29 01:57:38 -05:00
] if* ;
M: url-sessions session-link*
drop
\ session get id>> sess-id associate union assoc>query
>r url-encode r>
dup assoc-empty? [ drop ] [ "?" swap 3append ] if ;
TUPLE: cookie-sessions ;
: <cookie-sessions> ( responder -- responder' )
cookie-sessions <session-manager> ;
2008-03-03 03:19:36 -05:00
: get-session-cookie ( request responder -- cookie )
>r sess-id get-cookie dup
[ value>> r> get-session ] [ r> 2drop f ] if ;
2008-02-29 01:57:38 -05:00
: <session-cookie> ( id -- cookie )
sess-id <cookie> ;
M: cookie-sessions call-responder ( request path responder -- response )
2008-03-03 03:19:36 -05:00
3dup nip get-session-cookie [
2008-02-29 01:57:38 -05:00
call-responder/session
] [
dup new-session
[ over get-session call-responder/session ] keep
<session-cookie> put-cookie
] if* ;