Merge branch 'master' of git://factorcode.org/git/factor
commit
ddd5d544e2
|
@ -29,7 +29,9 @@ $nl
|
||||||
{ $subsection ignore-errors }
|
{ $subsection ignore-errors }
|
||||||
"Unhandled errors are reported in the listener and can be debugged using various tools. See " { $link "debugger" } "."
|
"Unhandled errors are reported in the listener and can be debugged using various tools. See " { $link "debugger" } "."
|
||||||
{ $subsection "errors-restartable" }
|
{ $subsection "errors-restartable" }
|
||||||
{ $subsection "errors-post-mortem" } ;
|
{ $subsection "errors-post-mortem" }
|
||||||
|
"When Factor encouters a critical error, it calls the following word:"
|
||||||
|
{ $subsection die } ;
|
||||||
|
|
||||||
ARTICLE: "continuations.private" "Continuation implementation details"
|
ARTICLE: "continuations.private" "Continuation implementation details"
|
||||||
"A continuation is simply a tuple holding the contents of the five stacks:"
|
"A continuation is simply a tuple holding the contents of the five stacks:"
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
IN: io.files.tests
|
IN: io.files.tests
|
||||||
USING: tools.test io.files io threads kernel continuations io.encodings.ascii ;
|
USING: tools.test io.files io threads kernel continuations io.encodings.ascii ;
|
||||||
|
|
||||||
|
[ ] [ "blahblah" temp-file dup exists? [ delete-directory ] [ drop ] if ] unit-test
|
||||||
|
[ ] [ "blahblah" temp-file make-directory ] unit-test
|
||||||
|
[ t ] [ "blahblah" temp-file directory? ] unit-test
|
||||||
|
|
||||||
[ "passwd" ] [ "/etc/passwd" file-name ] unit-test
|
[ "passwd" ] [ "/etc/passwd" file-name ] unit-test
|
||||||
[ "awk" ] [ "/usr/libexec/awk/" file-name ] unit-test
|
[ "awk" ] [ "/usr/libexec/awk/" file-name ] unit-test
|
||||||
[ "awk" ] [ "/usr/libexec/awk///" file-name ] unit-test
|
[ "awk" ] [ "/usr/libexec/awk///" file-name ] unit-test
|
||||||
|
@ -123,3 +127,7 @@ USING: tools.test io.files io threads kernel continuations io.encodings.ascii ;
|
||||||
[ ] [ "copy-tree-test" temp-file delete-tree ] unit-test
|
[ ] [ "copy-tree-test" temp-file delete-tree ] unit-test
|
||||||
|
|
||||||
[ t ] [ cwd "misc" resource-path [ ] with-directory cwd = ] unit-test
|
[ t ] [ cwd "misc" resource-path [ ] with-directory cwd = ] unit-test
|
||||||
|
|
||||||
|
[ ] [ "append-test" temp-file dup exists? [ delete-file ] [ drop ] if ] unit-test
|
||||||
|
|
||||||
|
[ ] [ "append-test" ascii <file-appender> dispose ] unit-test
|
||||||
|
|
|
@ -429,7 +429,14 @@ $nl
|
||||||
{ $code "[ X ] [ Y ] ?if" "dup [ nip X ] [ drop Y ] if" } } ;
|
{ $code "[ X ] [ Y ] ?if" "dup [ nip X ] [ drop Y ] if" } } ;
|
||||||
|
|
||||||
HELP: die
|
HELP: die
|
||||||
{ $description "Starts the front-end processor (FEP), which is a low-level debugger which can inspect memory addresses and the like. The FEP is also entered when a critical error occurs." } ;
|
{ $description "Starts the front-end processor (FEP), which is a low-level debugger which can inspect memory addresses and the like. The FEP is also entered when a critical error occurs." }
|
||||||
|
{ $notes
|
||||||
|
"The term FEP originates from the Lisp machines of old. According to the Jargon File,"
|
||||||
|
$nl
|
||||||
|
{ $strong "fepped out" } " /fept owt/ " { $emphasis "adj." } " The Symbolics 3600 LISP Machine has a Front-End Processor called a `FEP' (compare sense 2 of box). When the main processor gets wedged, the FEP takes control of the keyboard and screen. Such a machine is said to have `fepped out' or `dropped into the fep'."
|
||||||
|
$nl
|
||||||
|
{ $url "http://www.jargon.net/jargonfile/f/feppedout.html" }
|
||||||
|
} ;
|
||||||
|
|
||||||
HELP: (clone) ( obj -- newobj )
|
HELP: (clone) ( obj -- newobj )
|
||||||
{ $values { "obj" object } { "newobj" "a shallow copy" } }
|
{ $values { "obj" object } { "newobj" "a shallow copy" } }
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
USING: arrays assocs kernel vectors sequences namespaces ;
|
USING: arrays assocs kernel vectors sequences namespaces
|
||||||
|
random math.parser ;
|
||||||
IN: assocs.lib
|
IN: assocs.lib
|
||||||
|
|
||||||
: >set ( seq -- hash )
|
: >set ( seq -- hash )
|
||||||
|
@ -38,3 +39,10 @@ IN: assocs.lib
|
||||||
|
|
||||||
: 2seq>assoc ( keys values exemplar -- assoc )
|
: 2seq>assoc ( keys values exemplar -- assoc )
|
||||||
>r 2array flip r> assoc-like ;
|
>r 2array flip r> assoc-like ;
|
||||||
|
|
||||||
|
: generate-key ( assoc -- str )
|
||||||
|
>r random-256 >hex r>
|
||||||
|
2dup key? [ nip generate-key ] [ drop ] if ;
|
||||||
|
|
||||||
|
: set-at-unique ( value assoc -- key )
|
||||||
|
dup generate-key [ swap set-at ] keep ;
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
IN: db.tests
|
||||||
|
USING: tools.test db kernel ;
|
||||||
|
|
||||||
|
{ 1 0 } [ [ drop ] query-each ] must-infer-as
|
||||||
|
{ 1 1 } [ [ ] query-map ] must-infer-as
|
|
@ -119,8 +119,8 @@ M: postgresql-db bind% ( spec -- )
|
||||||
|
|
||||||
: postgresql-make ( class quot -- )
|
: postgresql-make ( class quot -- )
|
||||||
>r sql-props r>
|
>r sql-props r>
|
||||||
[ postgresql-counter off ] swap compose
|
[ postgresql-counter off call ] { "" { } { } } nmake
|
||||||
{ "" { } { } } nmake <postgresql-statement> ;
|
<postgresql-statement> ; inline
|
||||||
|
|
||||||
: create-table-sql ( class -- statement )
|
: create-table-sql ( class -- statement )
|
||||||
[
|
[
|
||||||
|
|
|
@ -127,6 +127,6 @@ FUNCTION: char* sqlite3_column_decltype ( sqlite3_stmt* pStmt, int col ) ;
|
||||||
FUNCTION: int sqlite3_column_int ( sqlite3_stmt* pStmt, int col ) ;
|
FUNCTION: int sqlite3_column_int ( sqlite3_stmt* pStmt, int col ) ;
|
||||||
FUNCTION: sqlite3_int64 sqlite3_column_int64 ( sqlite3_stmt* pStmt, int col ) ;
|
FUNCTION: sqlite3_int64 sqlite3_column_int64 ( sqlite3_stmt* pStmt, int col ) ;
|
||||||
FUNCTION: double sqlite3_column_double ( sqlite3_stmt* pStmt, int col ) ;
|
FUNCTION: double sqlite3_column_double ( sqlite3_stmt* pStmt, int col ) ;
|
||||||
FUNCTION: int sqlite3_column_name ( sqlite3_stmt* pStmt, int col ) ;
|
FUNCTION: char* sqlite3_column_name ( sqlite3_stmt* pStmt, int col ) ;
|
||||||
FUNCTION: char* sqlite3_column_text ( sqlite3_stmt* pStmt, int col ) ;
|
FUNCTION: char* sqlite3_column_text ( sqlite3_stmt* pStmt, int col ) ;
|
||||||
FUNCTION: int sqlite3_column_type ( sqlite3_stmt* pStmt, int col ) ;
|
FUNCTION: int sqlite3_column_type ( sqlite3_stmt* pStmt, int col ) ;
|
||||||
|
|
|
@ -98,7 +98,7 @@ M: sqlite-db rollback-transaction ( -- ) "ROLLBACK" sql-command ;
|
||||||
|
|
||||||
: sqlite-make ( class quot -- )
|
: sqlite-make ( class quot -- )
|
||||||
>r sql-props r>
|
>r sql-props r>
|
||||||
{ "" { } { } } nmake <simple-statement> ;
|
{ "" { } { } } nmake <simple-statement> ; inline
|
||||||
|
|
||||||
M: sqlite-db create-sql-statement ( class -- statement )
|
M: sqlite-db create-sql-statement ( class -- statement )
|
||||||
[
|
[
|
||||||
|
|
|
@ -239,3 +239,9 @@ TUPLE: exam id name score ;
|
||||||
;
|
;
|
||||||
|
|
||||||
! [ test-ranges ] test-sqlite
|
! [ test-ranges ] test-sqlite
|
||||||
|
|
||||||
|
\ insert-tuple must-infer
|
||||||
|
\ update-tuple must-infer
|
||||||
|
\ delete-tuple must-infer
|
||||||
|
\ select-tuple must-infer
|
||||||
|
\ define-persistent must-infer
|
||||||
|
|
|
@ -36,7 +36,7 @@ HOOK: <update-tuples-statement> db ( class -- obj )
|
||||||
HOOK: <delete-tuple-statement> db ( class -- obj )
|
HOOK: <delete-tuple-statement> db ( class -- obj )
|
||||||
HOOK: <delete-tuples-statement> db ( class -- obj )
|
HOOK: <delete-tuples-statement> db ( class -- obj )
|
||||||
|
|
||||||
HOOK: <select-by-slots-statement> db ( tuple -- tuple )
|
HOOK: <select-by-slots-statement> db ( tuple class -- tuple )
|
||||||
|
|
||||||
HOOK: insert-tuple* db ( tuple statement -- )
|
HOOK: insert-tuple* db ( tuple statement -- )
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ tuple-syntax namespaces ;
|
||||||
port: 80
|
port: 80
|
||||||
version: "1.1"
|
version: "1.1"
|
||||||
cookies: V{ }
|
cookies: V{ }
|
||||||
|
header: H{ }
|
||||||
}
|
}
|
||||||
] [
|
] [
|
||||||
[
|
[
|
||||||
|
|
|
@ -180,6 +180,7 @@ cookies ;
|
||||||
request construct-empty
|
request construct-empty
|
||||||
"1.1" >>version
|
"1.1" >>version
|
||||||
http-port >>port
|
http-port >>port
|
||||||
|
H{ } clone >>header
|
||||||
H{ } clone >>query
|
H{ } clone >>query
|
||||||
V{ } clone >>cookies ;
|
V{ } clone >>cookies ;
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
IN: http.server.actions.tests
|
IN: http.server.actions.tests
|
||||||
USING: http.server.actions tools.test math math.parser
|
USING: http.server.actions http.server.validators
|
||||||
multiline namespaces http io.streams.string http.server
|
tools.test math math.parser multiline namespaces http
|
||||||
sequences accessors ;
|
io.streams.string http.server sequences accessors ;
|
||||||
|
|
||||||
|
[
|
||||||
|
"a" [ v-number ] { { "a" "123" } } validate-param
|
||||||
|
[ 123 ] [ "a" get ] unit-test
|
||||||
|
] with-scope
|
||||||
|
|
||||||
<action>
|
<action>
|
||||||
[ "a" get "b" get + ] >>display
|
[ "a" get "b" get + ] >>display
|
||||||
{ { "a" [ string>number ] } { "b" [ string>number ] } } >>get-params
|
{ { "a" [ v-number ] } { "b" [ v-number ] } } >>get-params
|
||||||
"action-1" set
|
"action-1" set
|
||||||
|
|
||||||
STRING: action-request-test-1
|
STRING: action-request-test-1
|
||||||
|
@ -23,7 +28,7 @@ blah
|
||||||
|
|
||||||
<action>
|
<action>
|
||||||
[ +path+ get "xxx" get "X" <repetition> concat append ] >>submit
|
[ +path+ get "xxx" get "X" <repetition> concat append ] >>submit
|
||||||
{ { +path+ [ ] } { "xxx" [ string>number ] } } >>post-params
|
{ { +path+ [ ] } { "xxx" [ v-number ] } } >>post-params
|
||||||
"action-2" set
|
"action-2" set
|
||||||
|
|
||||||
STRING: action-request-test-2
|
STRING: action-request-test-2
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: accessors new-slots sequences kernel assocs combinators
|
USING: accessors new-slots sequences kernel assocs combinators
|
||||||
http.server http.server.validators http hashtables namespaces
|
http.server http.server.validators http hashtables namespaces
|
||||||
combinators.cleave fry continuations ;
|
combinators.cleave fry continuations locals ;
|
||||||
IN: http.server.actions
|
IN: http.server.actions
|
||||||
|
|
||||||
SYMBOL: +path+
|
SYMBOL: +path+
|
||||||
|
@ -17,12 +17,13 @@ TUPLE: action init display submit get-params post-params ;
|
||||||
[ <400> ] >>display
|
[ <400> ] >>display
|
||||||
[ <400> ] >>submit ;
|
[ <400> ] >>submit ;
|
||||||
|
|
||||||
: validate-param ( name validator assoc -- error? )
|
:: validate-param ( name validator assoc -- )
|
||||||
swap pick
|
name assoc at validator with-validator name set ; inline
|
||||||
>r >r at r> with-validator swap r> set ;
|
|
||||||
|
|
||||||
: action-params ( validators -- error? )
|
: action-params ( validators -- error? )
|
||||||
[ params get validate-param ] { } assoc>map [ ] contains? ;
|
validation-failed? off
|
||||||
|
params get '[ , validate-param ] assoc-each
|
||||||
|
validation-failed? get ;
|
||||||
|
|
||||||
: handle-get ( -- response )
|
: handle-get ( -- response )
|
||||||
action get get-params>> action-params [ <400> ] [
|
action get get-params>> action-params [ <400> ] [
|
||||||
|
|
|
@ -173,7 +173,7 @@ SYMBOL: previous-page
|
||||||
dup users update-user
|
dup users update-user
|
||||||
logged-in-user sset
|
logged-in-user sset
|
||||||
|
|
||||||
previous-page sget dup [ f <permanent-redirect> ] when
|
previous-page sget f <permanent-redirect>
|
||||||
] >>submit
|
] >>submit
|
||||||
] ;
|
] ;
|
||||||
|
|
||||||
|
@ -347,7 +347,7 @@ M: login call-responder ( path responder -- response )
|
||||||
swap <protected> >>default
|
swap <protected> >>default
|
||||||
<login-action> "login" add-responder
|
<login-action> "login" add-responder
|
||||||
<logout-action> "logout" add-responder
|
<logout-action> "logout" add-responder
|
||||||
no >>users ;
|
no-users >>users ;
|
||||||
|
|
||||||
! ! ! Configuration
|
! ! ! Configuration
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ USING: http.server.auth.providers
|
||||||
http.server.auth.providers.assoc tools.test
|
http.server.auth.providers.assoc tools.test
|
||||||
namespaces accessors kernel ;
|
namespaces accessors kernel ;
|
||||||
|
|
||||||
<in-memory> "provider" set
|
<users-in-memory> "provider" set
|
||||||
|
|
||||||
[ t ] [
|
[ t ] [
|
||||||
<user>
|
<user>
|
||||||
|
@ -26,7 +26,7 @@ namespaces accessors kernel ;
|
||||||
|
|
||||||
[ f ] [ "xx" "blah" "provider" get set-password ] unit-test
|
[ f ] [ "xx" "blah" "provider" get set-password ] unit-test
|
||||||
|
|
||||||
[ t ] [ "fdasf" "slava" "provider" get set-password ] unit-test
|
[ t ] [ "fdasf" "slava" "provider" get set-password >boolean ] unit-test
|
||||||
|
|
||||||
[ t ] [ "fdasf" "slava" "provider" get check-login >boolean ] unit-test
|
[ t ] [ "fdasf" "slava" "provider" get check-login >boolean ] unit-test
|
||||||
|
|
||||||
|
|
|
@ -4,16 +4,16 @@ IN: http.server.auth.providers.assoc
|
||||||
USING: new-slots accessors assocs kernel
|
USING: new-slots accessors assocs kernel
|
||||||
http.server.auth.providers ;
|
http.server.auth.providers ;
|
||||||
|
|
||||||
TUPLE: in-memory assoc ;
|
TUPLE: users-in-memory assoc ;
|
||||||
|
|
||||||
: <in-memory> ( -- provider )
|
: <users-in-memory> ( -- provider )
|
||||||
H{ } clone in-memory construct-boa ;
|
H{ } clone users-in-memory construct-boa ;
|
||||||
|
|
||||||
M: in-memory get-user ( username provider -- user/f )
|
M: users-in-memory get-user ( username provider -- user/f )
|
||||||
assoc>> at ;
|
assoc>> at ;
|
||||||
|
|
||||||
M: in-memory update-user ( user provider -- ) 2drop ;
|
M: users-in-memory update-user ( user provider -- ) 2drop ;
|
||||||
|
|
||||||
M: in-memory new-user ( user provider -- user/f )
|
M: users-in-memory new-user ( user provider -- user/f )
|
||||||
>r dup username>> r> assoc>>
|
>r dup username>> r> assoc>>
|
||||||
2dup key? [ 3drop f ] [ pick >r set-at r> ] if ;
|
2dup key? [ 3drop f ] [ pick >r set-at r> ] if ;
|
||||||
|
|
|
@ -4,12 +4,11 @@ http.server.auth.providers.db tools.test
|
||||||
namespaces db db.sqlite db.tuples continuations
|
namespaces db db.sqlite db.tuples continuations
|
||||||
io.files accessors kernel ;
|
io.files accessors kernel ;
|
||||||
|
|
||||||
from-db "provider" set
|
users-in-db "provider" set
|
||||||
|
|
||||||
"auth-test.db" temp-file sqlite-db [
|
"auth-test.db" temp-file sqlite-db [
|
||||||
|
|
||||||
[ user drop-table ] ignore-errors
|
init-users-table
|
||||||
[ user create-table ] ignore-errors
|
|
||||||
|
|
||||||
[ t ] [
|
[ t ] [
|
||||||
<user>
|
<user>
|
||||||
|
@ -32,7 +31,7 @@ from-db "provider" set
|
||||||
|
|
||||||
[ f ] [ "xx" "blah" "provider" get set-password ] unit-test
|
[ f ] [ "xx" "blah" "provider" get set-password ] unit-test
|
||||||
|
|
||||||
[ t ] [ "fdasf" "slava" "provider" get set-password ] unit-test
|
[ t ] [ "fdasf" "slava" "provider" get set-password >boolean ] unit-test
|
||||||
|
|
||||||
[ t ] [ "fdasf" "slava" "provider" get check-login >boolean ] unit-test
|
[ t ] [ "fdasf" "slava" "provider" get check-login >boolean ] unit-test
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
! Copyright (C) 2008 Slava Pestov.
|
! Copyright (C) 2008 Slava Pestov.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: db db.tuples db.types new-slots accessors
|
USING: db db.tuples db.types new-slots accessors
|
||||||
http.server.auth.providers kernel continuations ;
|
http.server.auth.providers kernel continuations
|
||||||
|
singleton ;
|
||||||
IN: http.server.auth.providers.db
|
IN: http.server.auth.providers.db
|
||||||
|
|
||||||
user "USERS"
|
user "USERS"
|
||||||
|
@ -16,20 +17,18 @@ user "USERS"
|
||||||
|
|
||||||
: init-users-table user ensure-table ;
|
: init-users-table user ensure-table ;
|
||||||
|
|
||||||
TUPLE: from-db ;
|
SINGLETON: users-in-db
|
||||||
|
|
||||||
: from-db T{ from-db } ;
|
|
||||||
|
|
||||||
: find-user ( username -- user )
|
: find-user ( username -- user )
|
||||||
<user>
|
<user>
|
||||||
swap >>username
|
swap >>username
|
||||||
select-tuple ;
|
select-tuple ;
|
||||||
|
|
||||||
M: from-db get-user
|
M: users-in-db get-user
|
||||||
drop
|
drop
|
||||||
find-user ;
|
find-user ;
|
||||||
|
|
||||||
M: from-db new-user
|
M: users-in-db new-user
|
||||||
drop
|
drop
|
||||||
[
|
[
|
||||||
dup username>> find-user [
|
dup username>> find-user [
|
||||||
|
@ -39,5 +38,5 @@ M: from-db new-user
|
||||||
] if
|
] if
|
||||||
] with-transaction ;
|
] with-transaction ;
|
||||||
|
|
||||||
M: from-db update-user
|
M: users-in-db update-user
|
||||||
drop update-tuple ;
|
drop update-tuple ;
|
||||||
|
|
|
@ -3,14 +3,12 @@
|
||||||
USING: http.server.auth.providers kernel ;
|
USING: http.server.auth.providers kernel ;
|
||||||
IN: http.server.auth.providers.null
|
IN: http.server.auth.providers.null
|
||||||
|
|
||||||
! Named "no" because we can say no >>users
|
TUPLE: no-users ;
|
||||||
|
|
||||||
TUPLE: no ;
|
: no-users T{ no-users } ;
|
||||||
|
|
||||||
: no T{ no } ;
|
M: no-users get-user 2drop f ;
|
||||||
|
|
||||||
M: no get-user 2drop f ;
|
M: no-users new-user 2drop f ;
|
||||||
|
|
||||||
M: no new-user 2drop f ;
|
M: no-users update-user 2drop ;
|
||||||
|
|
||||||
M: no update-user 2drop ;
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ GENERIC: new-user ( user provider -- user/f )
|
||||||
user [
|
user [
|
||||||
user
|
user
|
||||||
password >>password
|
password >>password
|
||||||
provider dup update-user
|
dup provider update-user
|
||||||
] [ f ] if
|
] [ f ] if
|
||||||
] ;
|
] ;
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
USING: html http http.server io kernel math namespaces
|
USING: html http http.server io kernel math namespaces
|
||||||
continuations calendar sequences assocs new-slots hashtables
|
continuations calendar sequences assocs new-slots hashtables
|
||||||
accessors arrays alarms quotations combinators
|
accessors arrays alarms quotations combinators
|
||||||
combinators.cleave fry ;
|
combinators.cleave fry assocs.lib ;
|
||||||
IN: http.server.callbacks
|
IN: http.server.callbacks
|
||||||
|
|
||||||
SYMBOL: responder
|
SYMBOL: responder
|
||||||
|
|
|
@ -98,4 +98,12 @@ TUPLE: test-tuple text number more-text ;
|
||||||
[ "123" ] [
|
[ "123" ] [
|
||||||
"123" "n" get validate value>>
|
"123" "n" get validate value>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
|
[ ] [ "n" get t >>integer drop ] unit-test
|
||||||
|
|
||||||
|
[ 3 ] [
|
||||||
|
"3" "n" get validate
|
||||||
|
] unit-test
|
||||||
] with-scope
|
] with-scope
|
||||||
|
|
||||||
|
[ t ] [ "wake up sheeple" dup "n" <text> validate = ] unit-test
|
||||||
|
|
|
@ -187,15 +187,16 @@ M: password render-error*
|
||||||
render-edit* render-error ;
|
render-edit* render-error ;
|
||||||
|
|
||||||
! Number fields
|
! Number fields
|
||||||
TUPLE: number min-value max-value ;
|
TUPLE: number min-value max-value integer ;
|
||||||
|
|
||||||
: <number> ( id -- component ) number <component> ;
|
: <number> ( id -- component ) number <component> ;
|
||||||
|
|
||||||
M: number validate*
|
M: number validate*
|
||||||
[ v-number ] [
|
[ v-number ] [
|
||||||
|
[ integer>> [ v-integer ] when ]
|
||||||
[ min-value>> [ v-min-value ] when* ]
|
[ min-value>> [ v-min-value ] when* ]
|
||||||
[ max-value>> [ v-max-value ] when* ]
|
[ max-value>> [ v-max-value ] when* ]
|
||||||
bi
|
tri
|
||||||
] bi* ;
|
] bi* ;
|
||||||
|
|
||||||
M: number render-view*
|
M: number render-view*
|
||||||
|
@ -212,7 +213,7 @@ TUPLE: text ;
|
||||||
|
|
||||||
: <text> ( id -- component ) text <component> ;
|
: <text> ( id -- component ) text <component> ;
|
||||||
|
|
||||||
M: text validate* 2drop ;
|
M: text validate* drop ;
|
||||||
|
|
||||||
M: text render-view*
|
M: text render-view*
|
||||||
drop write ;
|
drop write ;
|
||||||
|
|
|
@ -108,10 +108,6 @@ TUPLE: dispatcher default responders ;
|
||||||
: <dispatcher> ( -- dispatcher )
|
: <dispatcher> ( -- dispatcher )
|
||||||
404-responder get H{ } clone dispatcher construct-boa ;
|
404-responder get H{ } clone dispatcher construct-boa ;
|
||||||
|
|
||||||
: set-main ( dispatcher name -- dispatcher )
|
|
||||||
'[ , f <permanent-redirect> ] <trivial-responder>
|
|
||||||
>>default ;
|
|
||||||
|
|
||||||
: split-path ( path -- rest first )
|
: split-path ( path -- rest first )
|
||||||
[ CHAR: / = ] left-trim "/" split1 swap ;
|
[ CHAR: / = ] left-trim "/" split1 swap ;
|
||||||
|
|
||||||
|
@ -124,28 +120,36 @@ TUPLE: dispatcher default responders ;
|
||||||
|
|
||||||
M: dispatcher call-responder ( path dispatcher -- response )
|
M: dispatcher call-responder ( path dispatcher -- response )
|
||||||
over [
|
over [
|
||||||
2dup find-responder call-responder [
|
find-responder call-responder
|
||||||
2nip
|
|
||||||
] [
|
|
||||||
default>> [
|
|
||||||
call-responder
|
|
||||||
] [
|
|
||||||
drop f
|
|
||||||
] if*
|
|
||||||
] if*
|
|
||||||
] [
|
] [
|
||||||
2drop redirect-with-/
|
2drop redirect-with-/
|
||||||
] if ;
|
] if ;
|
||||||
|
|
||||||
|
: <webapp> ( class -- dispatcher )
|
||||||
|
<dispatcher> swap construct-delegate ; inline
|
||||||
|
|
||||||
|
TUPLE: vhost-dispatcher default responders ;
|
||||||
|
|
||||||
|
: <vhost-dispatcher> ( -- dispatcher )
|
||||||
|
404-responder get H{ } clone vhost-dispatcher construct-boa ;
|
||||||
|
|
||||||
|
: find-vhost ( dispatcher -- responder )
|
||||||
|
request get host>> over responders>> at*
|
||||||
|
[ nip ] [ drop default>> ] if ;
|
||||||
|
|
||||||
|
M: vhost-dispatcher call-responder ( path dispatcher -- response )
|
||||||
|
find-vhost call-responder ;
|
||||||
|
|
||||||
|
: set-main ( dispatcher name -- dispatcher )
|
||||||
|
'[ , f <permanent-redirect> ] <trivial-responder>
|
||||||
|
>>default ;
|
||||||
|
|
||||||
: add-responder ( dispatcher responder path -- dispatcher )
|
: add-responder ( dispatcher responder path -- dispatcher )
|
||||||
pick responders>> set-at ;
|
pick responders>> set-at ;
|
||||||
|
|
||||||
: add-main-responder ( dispatcher responder path -- dispatcher )
|
: add-main-responder ( dispatcher responder path -- dispatcher )
|
||||||
[ add-responder ] keep set-main ;
|
[ add-responder ] keep set-main ;
|
||||||
|
|
||||||
: <webapp> ( class -- dispatcher )
|
|
||||||
<dispatcher> swap construct-delegate ; inline
|
|
||||||
|
|
||||||
SYMBOL: main-responder
|
SYMBOL: main-responder
|
||||||
|
|
||||||
main-responder global
|
main-responder global
|
||||||
|
@ -219,11 +223,3 @@ SYMBOL: exit-continuation
|
||||||
: httpd-main ( -- ) 8888 httpd ;
|
: httpd-main ( -- ) 8888 httpd ;
|
||||||
|
|
||||||
MAIN: httpd-main
|
MAIN: httpd-main
|
||||||
|
|
||||||
! Utility
|
|
||||||
: generate-key ( assoc -- str )
|
|
||||||
>r random-256 >hex r>
|
|
||||||
2dup key? [ nip generate-key ] [ drop ] if ;
|
|
||||||
|
|
||||||
: set-at-unique ( value assoc -- key )
|
|
||||||
dup generate-key [ swap set-at ] keep ;
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
IN: http.server.sessions.tests
|
IN: http.server.sessions.tests
|
||||||
USING: tools.test http.server.sessions math namespaces
|
USING: tools.test http http.server.sessions
|
||||||
kernel accessors ;
|
http.server.sessions.storage http.server.sessions.storage.assoc
|
||||||
|
http.server math namespaces kernel accessors prettyprint
|
||||||
|
io.streams.string splitting destructors ;
|
||||||
|
|
||||||
[ H{ } ] [ H{ } add-session-id ] unit-test
|
[ H{ } ] [ H{ } add-session-id ] unit-test
|
||||||
|
|
||||||
|
@ -12,7 +14,16 @@ C: <foo> foo
|
||||||
|
|
||||||
M: foo init-session* drop 0 "x" sset ;
|
M: foo init-session* drop 0 "x" sset ;
|
||||||
|
|
||||||
f <session> "123" >>id [
|
M: foo call-responder
|
||||||
|
2drop
|
||||||
|
"x" [ 1+ ] schange
|
||||||
|
"text/html" <content> [ "x" sget pprint ] >>body ;
|
||||||
|
|
||||||
|
[
|
||||||
|
"123" session-id set
|
||||||
|
H{ } clone session set
|
||||||
|
session-changed? off
|
||||||
|
|
||||||
[ H{ { "factorsessid" "123" } } ] [ H{ } add-session-id ] unit-test
|
[ H{ { "factorsessid" "123" } } ] [ H{ } add-session-id ] unit-test
|
||||||
|
|
||||||
[ ] [ 3 "x" sset ] unit-test
|
[ ] [ 3 "x" sset ] unit-test
|
||||||
|
@ -22,22 +33,88 @@ f <session> "123" >>id [
|
||||||
[ ] [ "x" [ 1- ] schange ] unit-test
|
[ ] [ "x" [ 1- ] schange ] unit-test
|
||||||
|
|
||||||
[ 4 ] [ "x" sget sq ] unit-test
|
[ 4 ] [ "x" sget sq ] unit-test
|
||||||
] with-session
|
|
||||||
|
[ t ] [ session-changed? get ] unit-test
|
||||||
|
] with-scope
|
||||||
|
|
||||||
[ t ] [ f <url-sessions> url-sessions? ] unit-test
|
[ t ] [ f <url-sessions> url-sessions? ] unit-test
|
||||||
[ t ] [ f <cookie-sessions> cookie-sessions? ] unit-test
|
[ t ] [ f <cookie-sessions> cookie-sessions? ] unit-test
|
||||||
|
|
||||||
[ ] [
|
[ ] [
|
||||||
<foo> <url-sessions>
|
<foo> <url-sessions>
|
||||||
|
<sessions-in-memory> >>sessions
|
||||||
"manager" set
|
"manager" set
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
[ { 5 0 } ] [
|
[ { 5 0 } ] [
|
||||||
[
|
[
|
||||||
"manager" get new-session
|
"manager" get begin-session drop
|
||||||
dup "manager" get get-session [ 5 "a" sset ] with-session
|
dup "manager" get sessions>> get-session [ 5 "a" sset ] with-session
|
||||||
dup "manager" get get-session [ "a" sget , ] with-session
|
dup "manager" get sessions>> get-session [ "a" sget , ] with-session
|
||||||
dup "manager" get get-session [ "x" sget , ] with-session
|
dup "manager" get sessions>> get-session [ "x" sget , ] with-session
|
||||||
"manager" get get-session delete-session
|
"manager" get sessions>> get-session
|
||||||
|
"manager" get sessions>> delete-session
|
||||||
] { } make
|
] { } make
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
|
[ ] [
|
||||||
|
<request>
|
||||||
|
"GET" >>method
|
||||||
|
request set
|
||||||
|
"/etc" "manager" get call-responder
|
||||||
|
response set
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
[ 307 ] [ response get code>> ] unit-test
|
||||||
|
|
||||||
|
[ ] [ response get "location" header "=" split1 nip "id" set ] unit-test
|
||||||
|
|
||||||
|
: url-responder-mock-test
|
||||||
|
[
|
||||||
|
<request>
|
||||||
|
"GET" >>method
|
||||||
|
"id" get session-id-key set-query-param
|
||||||
|
"/" >>path
|
||||||
|
request set
|
||||||
|
"/" "manager" get call-responder
|
||||||
|
[ write-response-body drop ] with-string-writer
|
||||||
|
] with-destructors ;
|
||||||
|
|
||||||
|
[ "1" ] [ url-responder-mock-test ] unit-test
|
||||||
|
[ "2" ] [ url-responder-mock-test ] unit-test
|
||||||
|
[ "3" ] [ url-responder-mock-test ] unit-test
|
||||||
|
[ "4" ] [ url-responder-mock-test ] unit-test
|
||||||
|
|
||||||
|
[ ] [
|
||||||
|
<foo> <cookie-sessions>
|
||||||
|
<sessions-in-memory> >>sessions
|
||||||
|
"manager" set
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
[
|
||||||
|
<request>
|
||||||
|
"GET" >>method
|
||||||
|
"/" >>path
|
||||||
|
request set
|
||||||
|
"/etc" "manager" get call-responder response set
|
||||||
|
[ "1" ] [ [ response get write-response-body drop ] with-string-writer ] unit-test
|
||||||
|
response get
|
||||||
|
] with-destructors
|
||||||
|
response set
|
||||||
|
|
||||||
|
[ ] [ response get cookies>> "cookies" set ] unit-test
|
||||||
|
|
||||||
|
: cookie-responder-mock-test
|
||||||
|
[
|
||||||
|
<request>
|
||||||
|
"GET" >>method
|
||||||
|
"cookies" get >>cookies
|
||||||
|
"/" >>path
|
||||||
|
request set
|
||||||
|
"/" "manager" get call-responder
|
||||||
|
[ write-response-body drop ] with-string-writer
|
||||||
|
] with-destructors ;
|
||||||
|
|
||||||
|
[ "2" ] [ cookie-responder-mock-test ] unit-test
|
||||||
|
[ "3" ] [ cookie-responder-mock-test ] unit-test
|
||||||
|
[ "4" ] [ cookie-responder-mock-test ] unit-test
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
! Copyright (C) 2008 Doug Coleman, Slava Pestov.
|
! Copyright (C) 2008 Doug Coleman, Slava Pestov.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: assocs calendar kernel math.parser namespaces random
|
USING: assocs calendar kernel math.parser namespaces random
|
||||||
boxes alarms new-slots accessors http http.server
|
new-slots accessors http http.server
|
||||||
|
http.server.sessions.storage http.server.sessions.storage.assoc
|
||||||
quotations hashtables sequences fry combinators.cleave
|
quotations hashtables sequences fry combinators.cleave
|
||||||
html.elements ;
|
html.elements symbols continuations destructors ;
|
||||||
IN: http.server.sessions
|
IN: http.server.sessions
|
||||||
|
|
||||||
! ! ! ! ! !
|
! ! ! ! ! !
|
||||||
|
@ -17,56 +18,48 @@ M: dispatcher init-session* drop ;
|
||||||
TUPLE: session-manager responder sessions ;
|
TUPLE: session-manager responder sessions ;
|
||||||
|
|
||||||
: <session-manager> ( responder class -- responder' )
|
: <session-manager> ( responder class -- responder' )
|
||||||
>r H{ } clone session-manager construct-boa r>
|
>r <sessions-in-memory> session-manager construct-boa
|
||||||
construct-delegate ; inline
|
r> construct-delegate ; inline
|
||||||
|
|
||||||
TUPLE: session manager id namespace alarm ;
|
SYMBOLS: session session-id session-changed? ;
|
||||||
|
|
||||||
: <session> ( manager -- session )
|
: sget ( key -- value )
|
||||||
f H{ } clone <box> \ session construct-boa ;
|
session get at ;
|
||||||
|
|
||||||
: timeout ( -- dt ) 20 minutes ;
|
: sset ( value key -- )
|
||||||
|
session get set-at
|
||||||
|
session-changed? on ;
|
||||||
|
|
||||||
: cancel-timeout ( session -- )
|
: schange ( key quot -- )
|
||||||
alarm>> [ cancel-alarm ] if-box? ;
|
session get swap change-at
|
||||||
|
session-changed? on ; inline
|
||||||
|
|
||||||
: delete-session ( session -- )
|
: sessions session-manager get sessions>> ;
|
||||||
[ cancel-timeout ]
|
|
||||||
[ dup manager>> sessions>> delete-at ]
|
|
||||||
bi ;
|
|
||||||
|
|
||||||
: touch-session ( session -- session )
|
: managed-responder session-manager get responder>> ;
|
||||||
[ cancel-timeout ]
|
|
||||||
[ [ '[ , delete-session ] timeout later ] keep alarm>> >box ]
|
|
||||||
[ ]
|
|
||||||
tri ;
|
|
||||||
|
|
||||||
: session ( -- assoc ) \ session get namespace>> ;
|
: init-session ( managed -- session )
|
||||||
|
H{ } clone [ session [ init-session* ] with-variable ] keep ;
|
||||||
|
|
||||||
: sget ( key -- value ) session at ;
|
: begin-session ( responder -- id session )
|
||||||
|
[ responder>> init-session ] [ sessions>> ] bi
|
||||||
|
[ new-session ] [ drop ] 2bi ;
|
||||||
|
|
||||||
: sset ( value key -- ) session set-at ;
|
! Destructor
|
||||||
|
TUPLE: session-saver id session ;
|
||||||
|
|
||||||
: schange ( key quot -- ) session swap change-at ; inline
|
C: <session-saver> session-saver
|
||||||
|
|
||||||
: init-session ( session -- session )
|
M: session-saver dispose
|
||||||
dup dup \ session [
|
session-changed? get [
|
||||||
manager>> responder>> init-session*
|
[ session>> ] [ id>> ] bi
|
||||||
] with-variable ;
|
sessions update-session
|
||||||
|
] [ drop ] if ;
|
||||||
|
|
||||||
: new-session ( responder -- id )
|
: call-responder/session ( path responder id session -- response )
|
||||||
[ <session> init-session touch-session ]
|
[ <session-saver> add-always-destructor ]
|
||||||
[ [ sessions>> set-at-unique ] [ drop swap >>id ] 2bi ]
|
[ [ session-id set ] [ session set ] bi* ] 2bi
|
||||||
bi id>> ;
|
[ session-manager set ] [ responder>> call-responder ] bi ;
|
||||||
|
|
||||||
: get-session ( id responder -- session/f )
|
|
||||||
sessions>> at* [ touch-session ] when ;
|
|
||||||
|
|
||||||
: call-responder/session ( path responder session -- response )
|
|
||||||
\ session set responder>> call-responder ;
|
|
||||||
|
|
||||||
: sessions ( -- manager/f )
|
|
||||||
\ session get dup [ manager>> ] when ;
|
|
||||||
|
|
||||||
TUPLE: null-sessions ;
|
TUPLE: null-sessions ;
|
||||||
|
|
||||||
|
@ -74,56 +67,64 @@ TUPLE: null-sessions ;
|
||||||
null-sessions <session-manager> ;
|
null-sessions <session-manager> ;
|
||||||
|
|
||||||
M: null-sessions call-responder ( path responder -- response )
|
M: null-sessions call-responder ( path responder -- response )
|
||||||
dup <session> call-responder/session ;
|
H{ } clone f call-responder/session ;
|
||||||
|
|
||||||
TUPLE: url-sessions ;
|
TUPLE: url-sessions ;
|
||||||
|
|
||||||
: <url-sessions> ( responder -- responder' )
|
: <url-sessions> ( responder -- responder' )
|
||||||
url-sessions <session-manager> ;
|
url-sessions <session-manager> ;
|
||||||
|
|
||||||
: sess-id "factorsessid" ;
|
: session-id-key "factorsessid" ;
|
||||||
|
|
||||||
: current-session ( responder -- session )
|
: current-url-session ( responder -- id/f session/f )
|
||||||
>r request-params sess-id swap at r> get-session ;
|
[ request-params session-id-key swap at ] [ sessions>> ] bi*
|
||||||
|
[ drop ] [ get-session ] 2bi ;
|
||||||
|
|
||||||
: add-session-id ( query -- query' )
|
: add-session-id ( query -- query' )
|
||||||
\ session get [ id>> sess-id associate union ] when* ;
|
session-id get [ session-id-key associate union ] when* ;
|
||||||
|
|
||||||
: session-form-field ( -- )
|
: session-form-field ( -- )
|
||||||
<input
|
<input
|
||||||
"hidden" =type
|
"hidden" =type
|
||||||
sess-id =id
|
session-id-key =id
|
||||||
sess-id =name
|
session-id-key =name
|
||||||
\ session get id>> =value
|
session-id get =value
|
||||||
input/> ;
|
input/> ;
|
||||||
|
|
||||||
|
: new-url-session ( responder -- response )
|
||||||
|
[ f ] [ begin-session drop session-id-key associate ] bi*
|
||||||
|
<temporary-redirect> ;
|
||||||
|
|
||||||
M: url-sessions call-responder ( path responder -- response )
|
M: url-sessions call-responder ( path responder -- response )
|
||||||
[ add-session-id ] link-hook set
|
[ add-session-id ] link-hook set
|
||||||
[ session-form-field ] form-hook set
|
[ session-form-field ] form-hook set
|
||||||
dup current-session [
|
dup current-url-session dup [
|
||||||
call-responder/session
|
call-responder/session
|
||||||
] [
|
] [
|
||||||
nip
|
2drop nip new-url-session
|
||||||
f swap new-session sess-id associate <temporary-redirect>
|
] if ;
|
||||||
] if* ;
|
|
||||||
|
|
||||||
TUPLE: cookie-sessions ;
|
TUPLE: cookie-sessions ;
|
||||||
|
|
||||||
: <cookie-sessions> ( responder -- responder' )
|
: <cookie-sessions> ( responder -- responder' )
|
||||||
cookie-sessions <session-manager> ;
|
cookie-sessions <session-manager> ;
|
||||||
|
|
||||||
: get-session-cookie ( responder -- cookie )
|
: current-cookie-session ( responder -- id namespace/f )
|
||||||
request get sess-id get-cookie
|
request get session-id-key get-cookie dup
|
||||||
[ value>> swap get-session ] [ drop f ] if* ;
|
[ value>> dup rot sessions>> get-session ] [ 2drop f f ] if ;
|
||||||
|
|
||||||
: <session-cookie> ( id -- cookie )
|
: <session-cookie> ( id -- cookie )
|
||||||
sess-id <cookie> ;
|
session-id-key <cookie> ;
|
||||||
|
|
||||||
|
: call-responder/new-session ( path responder -- response )
|
||||||
|
dup begin-session
|
||||||
|
[ call-responder/session ]
|
||||||
|
[ drop <session-cookie> ] 2bi
|
||||||
|
put-cookie ;
|
||||||
|
|
||||||
M: cookie-sessions call-responder ( path responder -- response )
|
M: cookie-sessions call-responder ( path responder -- response )
|
||||||
dup get-session-cookie [
|
dup current-cookie-session dup [
|
||||||
call-responder/session
|
call-responder/session
|
||||||
] [
|
] [
|
||||||
dup new-session
|
2drop call-responder/new-session
|
||||||
[ over get-session call-responder/session ] keep
|
] if ;
|
||||||
<session-cookie> put-cookie
|
|
||||||
] if* ;
|
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
! Copyright (C) 2008 Slava Pestov.
|
||||||
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
|
USING: assocs assocs.lib new-slots accessors
|
||||||
|
http.server.sessions.storage combinators.cleave alarms kernel
|
||||||
|
fry http.server ;
|
||||||
|
IN: http.server.sessions.storage.assoc
|
||||||
|
|
||||||
|
TUPLE: sessions-in-memory sessions alarms ;
|
||||||
|
|
||||||
|
: <sessions-in-memory> ( -- storage )
|
||||||
|
H{ } clone H{ } clone sessions-in-memory construct-boa ;
|
||||||
|
|
||||||
|
: cancel-session-timeout ( id storage -- )
|
||||||
|
alarms>> at [ cancel-alarm ] when* ;
|
||||||
|
|
||||||
|
: touch-session ( id storage -- )
|
||||||
|
[ cancel-session-timeout ]
|
||||||
|
[ '[ , , delete-session ] timeout later ]
|
||||||
|
[ alarms>> set-at ]
|
||||||
|
2tri ;
|
||||||
|
|
||||||
|
M: sessions-in-memory get-session ( id storage -- namespace )
|
||||||
|
[ sessions>> at ] [ touch-session ] 2bi ;
|
||||||
|
|
||||||
|
M: sessions-in-memory update-session ( namespace id storage -- )
|
||||||
|
[ sessions>> set-at ]
|
||||||
|
[ touch-session ]
|
||||||
|
2bi ;
|
||||||
|
|
||||||
|
M: sessions-in-memory delete-session ( id storage -- )
|
||||||
|
[ sessions>> delete-at ]
|
||||||
|
[ cancel-session-timeout ]
|
||||||
|
2bi ;
|
||||||
|
|
||||||
|
M: sessions-in-memory new-session ( namespace storage -- id )
|
||||||
|
[ sessions>> set-at-unique ]
|
||||||
|
[ [ touch-session ] [ drop ] 2bi ]
|
||||||
|
bi ;
|
|
@ -0,0 +1,24 @@
|
||||||
|
IN: http.server.sessions.storage.db
|
||||||
|
USING: http.server.sessions.storage
|
||||||
|
http.server.sessions.storage.db namespaces io.files
|
||||||
|
db.sqlite db accessors math tools.test kernel assocs
|
||||||
|
sequences ;
|
||||||
|
|
||||||
|
sessions-in-db "storage" set
|
||||||
|
|
||||||
|
"auth-test.db" temp-file sqlite-db [
|
||||||
|
[ ] [ init-sessions-table ] unit-test
|
||||||
|
|
||||||
|
[ f ] [ H{ } "storage" get new-session empty? ] unit-test
|
||||||
|
|
||||||
|
H{ } "storage" get new-session "id" set
|
||||||
|
|
||||||
|
"id" get "storage" get get-session "session" set
|
||||||
|
"a" "b" "session" get set-at
|
||||||
|
|
||||||
|
"session" get "id" get "storage" get update-session
|
||||||
|
|
||||||
|
[ H{ { "b" "a" } } ] [
|
||||||
|
"id" get "storage" get get-session
|
||||||
|
] unit-test
|
||||||
|
] with-db
|
|
@ -0,0 +1,52 @@
|
||||||
|
! Copyright (C) 2008 Slava Pestov.
|
||||||
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
|
USING: assocs new-slots accessors http.server.sessions.storage
|
||||||
|
alarms kernel http.server db.tuples db.types singleton
|
||||||
|
combinators.cleave math.parser ;
|
||||||
|
IN: http.server.sessions.storage.db
|
||||||
|
|
||||||
|
SINGLETON: sessions-in-db
|
||||||
|
|
||||||
|
TUPLE: session id namespace ;
|
||||||
|
|
||||||
|
session "SESSIONS"
|
||||||
|
{
|
||||||
|
{ "id" "ID" INTEGER +native-id+ }
|
||||||
|
{ "namespace" "NAMESPACE" FACTOR-BLOB }
|
||||||
|
} define-persistent
|
||||||
|
|
||||||
|
: init-sessions-table session ensure-table ;
|
||||||
|
|
||||||
|
: <session> ( id -- session )
|
||||||
|
session construct-empty
|
||||||
|
swap dup [ string>number ] when >>id ;
|
||||||
|
|
||||||
|
USING: namespaces io prettyprint ;
|
||||||
|
M: sessions-in-db get-session ( id storage -- namespace/f )
|
||||||
|
global [ "get " write over print flush ] bind
|
||||||
|
drop
|
||||||
|
dup [
|
||||||
|
<session>
|
||||||
|
select-tuple dup [ namespace>> ] when global [ dup . ] bind
|
||||||
|
] when ;
|
||||||
|
|
||||||
|
M: sessions-in-db update-session ( namespace id storage -- )
|
||||||
|
global [ "update " write over print flush ] bind
|
||||||
|
drop
|
||||||
|
<session>
|
||||||
|
swap global [ dup . ] bind >>namespace
|
||||||
|
dup update-tuple
|
||||||
|
id>> <session> select-tuple global [ . flush ] bind
|
||||||
|
;
|
||||||
|
|
||||||
|
M: sessions-in-db delete-session ( id storage -- )
|
||||||
|
drop
|
||||||
|
<session>
|
||||||
|
delete-tuple ;
|
||||||
|
|
||||||
|
M: sessions-in-db new-session ( namespace storage -- id )
|
||||||
|
global [ "new " print flush ] bind
|
||||||
|
drop
|
||||||
|
f <session>
|
||||||
|
swap global [ dup . ] bind >>namespace
|
||||||
|
[ insert-tuple ] [ id>> number>string ] bi ;
|
|
@ -0,0 +1,14 @@
|
||||||
|
! Copyright (C) 2008 Slava Pestov.
|
||||||
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
|
USING: calendar ;
|
||||||
|
IN: http.server.sessions.storage
|
||||||
|
|
||||||
|
: timeout 20 minutes ;
|
||||||
|
|
||||||
|
GENERIC: get-session ( id storage -- namespace )
|
||||||
|
|
||||||
|
GENERIC: update-session ( namespace id storage -- )
|
||||||
|
|
||||||
|
GENERIC: delete-session ( id storage -- )
|
||||||
|
|
||||||
|
GENERIC: new-session ( namespace storage -- id )
|
|
@ -2,7 +2,8 @@ IN: http.server.validators.tests
|
||||||
USING: kernel sequences tools.test http.server.validators
|
USING: kernel sequences tools.test http.server.validators
|
||||||
accessors ;
|
accessors ;
|
||||||
|
|
||||||
[ "foo" v-number ] [ validation-error? ] must-fail-with
|
[ "foo" v-number ] must-fail
|
||||||
|
[ 123 ] [ "123" v-number ] unit-test
|
||||||
|
|
||||||
[ "slava@factorcode.org" ] [
|
[ "slava@factorcode.org" ] [
|
||||||
"slava@factorcode.org" v-email
|
"slava@factorcode.org" v-email
|
||||||
|
|
|
@ -40,6 +40,9 @@ C: <validation-error> validation-error
|
||||||
: v-number ( str -- n )
|
: v-number ( str -- n )
|
||||||
dup string>number [ ] [ "must be a number" throw ] ?if ;
|
dup string>number [ ] [ "must be a number" throw ] ?if ;
|
||||||
|
|
||||||
|
: v-integer ( n -- n )
|
||||||
|
dup integer? [ "must be an integer" throw ] unless ;
|
||||||
|
|
||||||
: v-min-value ( x n -- x )
|
: v-min-value ( x n -- x )
|
||||||
2dup < [
|
2dup < [
|
||||||
[ "must be at least " % # ] "" make throw
|
[ "must be at least " % # ] "" make throw
|
||||||
|
|
|
@ -7,7 +7,7 @@ sequences namespaces words symbols ;
|
||||||
IN: io.windows.files
|
IN: io.windows.files
|
||||||
|
|
||||||
SYMBOLS: +read-only+ +hidden+ +system+
|
SYMBOLS: +read-only+ +hidden+ +system+
|
||||||
+directory+ +archive+ +device+ +normal+ +temporary+
|
+archive+ +device+ +normal+ +temporary+
|
||||||
+sparse-file+ +reparse-point+ +compressed+ +offline+
|
+sparse-file+ +reparse-point+ +compressed+ +offline+
|
||||||
+not-content-indexed+ +encrypted+ ;
|
+not-content-indexed+ +encrypted+ ;
|
||||||
|
|
||||||
|
|
|
@ -76,11 +76,8 @@ M: win32-file close-handle ( handle -- )
|
||||||
] when drop ;
|
] when drop ;
|
||||||
|
|
||||||
: open-append ( path -- handle length )
|
: open-append ( path -- handle length )
|
||||||
dup file-info file-info-size dup [
|
[ dup file-info file-info-size ] [ drop 0 ] recover
|
||||||
>r (open-append) r> 2dup set-file-pointer
|
>r (open-append) r> 2dup set-file-pointer ;
|
||||||
] [
|
|
||||||
drop open-write
|
|
||||||
] if ;
|
|
||||||
|
|
||||||
TUPLE: FileArgs
|
TUPLE: FileArgs
|
||||||
hFile lpBuffer nNumberOfBytesToRead lpNumberOfBytesRet lpOverlapped ;
|
hFile lpBuffer nNumberOfBytesToRead lpNumberOfBytesRet lpOverlapped ;
|
||||||
|
|
|
@ -4,7 +4,7 @@ USING: namespaces kernel io calendar sequences io.files
|
||||||
io.sockets continuations prettyprint assocs math.parser
|
io.sockets continuations prettyprint assocs math.parser
|
||||||
words debugger math combinators concurrency.messaging
|
words debugger math combinators concurrency.messaging
|
||||||
threads arrays init math.ranges strings calendar.format
|
threads arrays init math.ranges strings calendar.format
|
||||||
io.encodings.ascii ;
|
io.encodings.utf8 ;
|
||||||
IN: logging.server
|
IN: logging.server
|
||||||
|
|
||||||
: log-root ( -- string )
|
: log-root ( -- string )
|
||||||
|
@ -21,7 +21,7 @@ SYMBOL: log-files
|
||||||
: open-log-stream ( service -- stream )
|
: open-log-stream ( service -- stream )
|
||||||
log-path
|
log-path
|
||||||
dup make-directories
|
dup make-directories
|
||||||
1 log# ascii <file-appender> ;
|
1 log# utf8 <file-appender> ;
|
||||||
|
|
||||||
: log-stream ( service -- stream )
|
: log-stream ( service -- stream )
|
||||||
log-files get [ open-log-stream ] cache ;
|
log-files get [ open-log-stream ] cache ;
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
IN: namespaces.lib.tests
|
||||||
|
USING: namespaces.lib tools.test ;
|
||||||
|
|
||||||
|
[ ] [ [ ] { } nmake ] unit-test
|
||||||
|
|
||||||
|
[ { 1 } { 2 } ] [ [ 1 0, 2 1, ] { { } { } } nmake ] unit-test
|
|
@ -2,7 +2,7 @@
|
||||||
! USING: kernel quotations namespaces sequences assocs.lib ;
|
! USING: kernel quotations namespaces sequences assocs.lib ;
|
||||||
|
|
||||||
USING: kernel namespaces namespaces.private quotations sequences
|
USING: kernel namespaces namespaces.private quotations sequences
|
||||||
assocs.lib math.parser math sequences.lib ;
|
assocs.lib math.parser math sequences.lib locals ;
|
||||||
|
|
||||||
IN: namespaces.lib
|
IN: namespaces.lib
|
||||||
|
|
||||||
|
@ -42,11 +42,19 @@ SYMBOL: building-seq
|
||||||
: 4% 4 n% ;
|
: 4% 4 n% ;
|
||||||
: 4# 4 n# ;
|
: 4# 4 n# ;
|
||||||
|
|
||||||
: nmake ( quot exemplars -- seqs )
|
MACRO:: nmake ( quot exemplars -- )
|
||||||
dup length dup zero? [ 1+ ] when
|
[let | n [ exemplars length ] |
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
[ drop 1024 swap new-resizable ] 2map
|
exemplars
|
||||||
[ building-seq set call ] keep
|
[ 0 swap new-resizable ] map
|
||||||
] 2keep >r [ like ] 2map r> firstn
|
building-seq set
|
||||||
] with-scope ;
|
|
||||||
|
quot call
|
||||||
|
|
||||||
|
building-seq get
|
||||||
|
exemplars [ like ] 2map
|
||||||
|
n firstn
|
||||||
|
] with-scope
|
||||||
|
]
|
||||||
|
] ;
|
||||||
|
|
|
@ -79,3 +79,6 @@ IN: sequences.lib.tests
|
||||||
[ { 910 911 912 } ] [ 10 900 3 [ + + ] map-with2 ] unit-test
|
[ { 910 911 912 } ] [ 10 900 3 [ + + ] map-with2 ] unit-test
|
||||||
|
|
||||||
[ 1 2 3 4 ] [ { 1 2 3 4 } 4 firstn ] unit-test
|
[ 1 2 3 4 ] [ { 1 2 3 4 } 4 firstn ] unit-test
|
||||||
|
|
||||||
|
[ ] [ { } 0 firstn ] unit-test
|
||||||
|
[ "a" ] [ { "a" } 1 firstn ] unit-test
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
USING: combinators.lib kernel sequences math namespaces assocs
|
USING: combinators.lib kernel sequences math namespaces assocs
|
||||||
random sequences.private shuffle math.functions mirrors
|
random sequences.private shuffle math.functions mirrors
|
||||||
arrays math.parser math.private sorting strings ascii macros
|
arrays math.parser math.private sorting strings ascii macros
|
||||||
assocs.lib ;
|
assocs.lib quotations ;
|
||||||
IN: sequences.lib
|
IN: sequences.lib
|
||||||
|
|
||||||
: each-withn ( seq quot n -- ) nwith each ; inline
|
: each-withn ( seq quot n -- ) nwith each ; inline
|
||||||
|
@ -20,8 +20,9 @@ IN: sequences.lib
|
||||||
: map-with2 ( obj obj list quot -- newseq ) 2 map-withn ; inline
|
: map-with2 ( obj obj list quot -- newseq ) 2 map-withn ; inline
|
||||||
|
|
||||||
MACRO: firstn ( n -- )
|
MACRO: firstn ( n -- )
|
||||||
[ [ swap nth ] curry
|
[ [ swap nth ] curry [ keep ] curry ] map
|
||||||
[ keep ] curry ] map concat [ drop ] compose ;
|
concat >quotation
|
||||||
|
[ drop ] compose ;
|
||||||
|
|
||||||
: prepare-index ( seq quot -- seq n quot )
|
: prepare-index ( seq quot -- seq n quot )
|
||||||
>r dup length r> ; inline
|
>r dup length r> ; inline
|
||||||
|
@ -193,7 +194,7 @@ USE: continuations
|
||||||
: ?tail* ( seq n -- seq/f ) (tail) ?subseq ;
|
: ?tail* ( seq n -- seq/f ) (tail) ?subseq ;
|
||||||
|
|
||||||
: accumulator ( quot -- quot vec )
|
: accumulator ( quot -- quot vec )
|
||||||
V{ } clone [ [ push ] curry compose ] keep ;
|
V{ } clone [ [ push ] curry compose ] keep ; inline
|
||||||
|
|
||||||
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,15 @@
|
||||||
USING: kernel symbols tools.test ;
|
USING: kernel symbols tools.test parser generic words ;
|
||||||
IN: symbols.tests
|
IN: symbols.tests
|
||||||
|
|
||||||
[ ] [ SYMBOLS: a b c ; ] unit-test
|
[ ] [ SYMBOLS: a b c ; ] unit-test
|
||||||
[ a ] [ a ] unit-test
|
[ a ] [ a ] unit-test
|
||||||
[ b ] [ b ] unit-test
|
[ b ] [ b ] unit-test
|
||||||
[ c ] [ c ] unit-test
|
[ c ] [ c ] unit-test
|
||||||
|
|
||||||
|
DEFER: blah
|
||||||
|
|
||||||
|
[ ] [ "IN: symbols.tests GENERIC: blah" eval ] unit-test
|
||||||
|
[ ] [ "IN: symbols.tests USE: symbols SYMBOLS: blah ;" eval ] unit-test
|
||||||
|
|
||||||
|
[ f ] [ \ blah generic? ] unit-test
|
||||||
|
[ t ] [ \ blah symbol? ] unit-test
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
! Copyright (C) 2008 Slava Pestov.
|
! Copyright (C) 2008 Doug Coleman.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: parser sequences words ;
|
USING: parser sequences words kernel ;
|
||||||
IN: symbols
|
IN: symbols
|
||||||
|
|
||||||
: SYMBOLS:
|
: SYMBOLS:
|
||||||
";" parse-tokens [ create-in define-symbol ] each ;
|
";" parse-tokens
|
||||||
|
[ create-in dup reset-generic define-symbol ] each ;
|
||||||
parsing
|
parsing
|
||||||
|
|
Loading…
Reference in New Issue