Paste: fcgi
Author: | brennanc |
Mode: | factor |
Date: | Thu, 27 May 2010 22:41:46 |
Plain Text |
USING: accessors alien.enums alien.syntax assocs combinators
combinators.smart io io.binary io.directories io.encodings.binary
io.files io.servers.connection io.sockets io.streams.byte-array kernel
locals math namespaces pack prettyprint sequences sequences.deep
strings unix.users ;
IN: fastcgi
SYMBOL: fcgi-server
SYMBOL: fcgi-role
SYMBOL: fcgi-flags
SYMBOL: fcgi-params
SYMBOL: fcgi-request
CONSTANT: fcgi-version 1
CONSTANT: socket-path "/chroot/web/var/run/factor.sock"
TUPLE: fcgi-header version type request-id content-length
padding-length reserved ;
TUPLE: request params stdin data ;
: <request> ( params stdin data -- obj ) request boa ;
ENUM: fcgi-header-types
{ FCGI_BEGIN_REQUEST 1 }
FCGI_ABORT_REQUEST
FCGI_END_REQUEST
FCGI_PARAMS
FCGI_STDIN
FCGI_STDOUT
FCGI_STDERR
FCGI_DATA
FCGI_GET_VALUES
FCGI_GET_VALUES_RESULT
FCGI_UNKNOWN_TYPE
{ FCGI_MAXTYPE 11 } ;
ENUM: fcgi-roles
{ FCGI_RESPONDER 1 }
FCGI_AUTHORIZER
FCGI_FILTER ;
ENUM: fcgi-protocol-status
{ FCGI_REQUEST_COMPLETE 0 }
FCGI_CANT_MAX_CONN
FCGI_OVERLOADED
FCGI_UNKNOWN_ROLE ;
:: debug-print ( print-quot -- )
global [ print-quot call flush ] bind ; inline
: read-var-int ( -- n/f )
read1 [
dup 7 bit?
[ 127 bitand 3 read swap suffix be> ] when
] [ f ] if* ;
: store-key-value-param ( key value -- )
swap fcgi-params get set-at ;
: read-params ( -- )
[
read-var-int read-var-int 2dup and
[
[ read >string ] bi@
store-key-value-param
t
] [ 2drop f ] if
] loop
fcgi-request get fcgi-params get >>params fcgi-request set ;
: delete-if-exists ( file -- )
dup exists? [ delete-file ] [ drop ] if ;
: make-local-socket ( -- socket )
socket-path [ delete-if-exists ] keep
<local> ;
: get-header ( -- header )
"CCSSCC" read-packed-be
[ fcgi-header boa ] input<sequence
dup type>> fcgi-header-types number>enum >>type ;
: get-content-data ( header -- content )
dup
[ content-length>> ] [ padding-length>> ] bi or 0 >
[
[ content-length>> read ] [ padding-length>> read drop ] bi
] [ drop f ] if ;
: begin-request-body ( seq -- )
binary [ "SCCCCCC" read-packed-be ] with-byte-reader
first2 fcgi-flags set fcgi-roles number>enum fcgi-role set ;
: process-begin-request ( header -- )
get-content-data begin-request-body
H{ } clone dup fcgi-params set
"" "" <request> fcgi-request set ;
: process-params ( header -- )
get-content-data binary [ read-params ] with-byte-reader ;
:: make-response-packet ( content -- seq )
[
fcgi-version
FCGI_STDOUT enum>number
1
content length
0
0
] output>array
"CCSSCC" pack-be content append ;
:: make-end-request-body ( app-status protocol-status -- seq )
[ app-status protocol-status 0 0 0 ] output>array "ICCCC" pack-be ;
: make-end-request ( -- seq )
[
fcgi-version
FCGI_END_REQUEST enum>number
1
8
0
0
0 0 make-end-request-body
] output>array flatten ;
: write-response ( content -- )
make-response-packet write ;
: dispatch-by-header ( header -- ? )
dup type>>
{
{ FCGI_BEGIN_REQUEST [ process-begin-request t ] }
{ FCGI_PARAMS [ process-params t ] }
{ FCGI_STDIN [ get-content-data drop f ] }
[ drop [ . ] debug-print f ]
} case ;
: page-handler ( -- )
"Content-type: text/html\n\nThis is a test" write-response ;
: fcgi-handler ( -- )
[ get-header dispatch-by-header ] loop [ "stopped" print ] debug-print page-handler ;
: <fastcgi-server> ( addr -- server )
binary
<threaded-server>
swap >>insecure
"fastcgi-server" >>name
[ fcgi-handler ] >>handler ;
: do-it ( -- )
socket-path delete-if-exists
"nginx" [ make-local-socket <fastcgi-server> dup fcgi-server set start-server ] with-real-user ;
New Annotation