1 ! Copyright (C) 2008 Doug Coleman, Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors combinators.short-circuit db.tuples db.types
4 furnace.cache furnace.scopes furnace.utilities http http.server
5 http.server.dispatchers http.server.filters io.sockets kernel
6 math.parser namespaces strings ;
9 TUPLE: session < scope user-agent client ;
11 : <session> ( id -- session )
12 session new-server-state ;
16 { "user-agent" "USER_AGENT" TEXT +not-null+ }
17 { "client" "CLIENT" TEXT +not-null+ }
20 : get-session ( id -- session )
21 dup [ session get-state ] when ;
23 GENERIC: init-session* ( responder -- )
25 M: object init-session* drop ;
27 M: dispatcher init-session* default>> init-session* ;
29 M: filter-responder init-session* responder>> init-session* ;
31 TUPLE: sessions < server-state-manager domain verify? ;
33 : <sessions> ( responder -- responder' )
34 sessions new-server-state-manager
37 : session-changed ( -- )
38 session get scope-changed ;
40 : sget ( key -- value ) session get scope-get ;
42 : sset ( value key -- ) session get scope-set ;
44 : schange ( key quot -- ) session get scope-change ; inline
46 : init-session ( session -- )
47 session [ sessions get init-session* ] with-variable ;
49 : touch-session ( session -- )
50 sessions get touch-state ;
52 : remote-host ( -- string )
54 [ request get "x-forwarded-for" header ]
55 [ remote-address get host>> ]
58 : empty-session ( -- session )
61 user-agent >>user-agent
64 : begin-session ( -- session )
65 empty-session [ init-session ] [ insert-tuple ] [ ] tri ;
67 : save-session-after ( session -- )
68 sessions get save-scope-after ;
70 : existing-session ( path session -- response )
71 [ session set ] [ save-session-after ] bi
72 sessions get responder>> call-responder ;
74 CONSTANT: session-id-key "__s"
76 : verify-session ( session -- session )
77 sessions get verify?>> [
80 [ client>> remote-host = ]
81 [ user-agent>> user-agent = ]
82 bi and [ drop f ] unless
86 : request-session ( -- session/f )
88 client-state dup string? [ string>number ] when
89 get-session verify-session ;
91 : <session-cookie> ( -- cookie )
92 session get id>> session-id-key <cookie>
93 "$sessions" resolve-base-path >>path
94 sessions get domain>> >>domain ;
96 : put-session-cookie ( response -- response' )
97 <session-cookie> put-cookie ;
99 M: sessions modify-form
100 drop session get id>> session-id-key hidden-form-field ;
102 M: sessions call-responder*
104 request-session [ begin-session ] unless*
105 existing-session put-session-cookie ;
109 : check-session ( state/f -- state/f )
110 dup [ dup session>> session get id>> = [ drop f ] unless ] when ;