2008-02-07 02:05:10 -05:00
|
|
|
! Copyright (C) 2003, 2008 Slava Pestov.
|
2007-09-20 18:09:08 -04:00
|
|
|
! See http://factorcode.org/license.txt for BSD license.
|
2008-02-09 22:34:42 -05:00
|
|
|
USING: assocs kernel namespaces io io.timeouts strings splitting
|
2008-02-25 15:53:18 -05:00
|
|
|
threads http sequences prettyprint io.server logging calendar
|
2008-02-29 01:57:38 -05:00
|
|
|
new-slots html.elements accessors math.parser combinators.lib
|
|
|
|
vocabs.loader debugger html continuations random ;
|
2007-09-20 18:09:08 -04:00
|
|
|
IN: http.server
|
|
|
|
|
2008-02-29 01:57:38 -05:00
|
|
|
GENERIC: call-responder ( request path responder -- response )
|
2008-02-25 15:53:18 -05:00
|
|
|
|
2008-02-29 01:57:38 -05:00
|
|
|
TUPLE: trivial-responder response ;
|
2008-02-25 15:53:18 -05:00
|
|
|
|
2008-02-29 01:57:38 -05:00
|
|
|
C: <trivial-responder> trivial-responder
|
2008-02-25 15:53:18 -05:00
|
|
|
|
2008-02-29 01:57:38 -05:00
|
|
|
M: trivial-responder call-responder 2nip response>> call ;
|
2008-02-25 15:53:18 -05:00
|
|
|
|
|
|
|
: trivial-response-body ( code message -- )
|
|
|
|
<html>
|
|
|
|
<body>
|
|
|
|
<h1> swap number>string write bl write </h1>
|
|
|
|
</body>
|
|
|
|
</html> ;
|
|
|
|
|
2008-02-29 01:57:38 -05:00
|
|
|
: <trivial-response> ( code message -- response )
|
|
|
|
<response>
|
|
|
|
2over [ trivial-response-body ] 2curry >>body
|
2008-02-25 15:53:18 -05:00
|
|
|
"text/html" set-content-type
|
|
|
|
swap >>message
|
|
|
|
swap >>code ;
|
|
|
|
|
2008-02-29 01:57:38 -05:00
|
|
|
: <404> ( -- response )
|
2008-02-25 15:53:18 -05:00
|
|
|
404 "Not Found" <trivial-response> ;
|
|
|
|
|
2008-02-29 01:57:38 -05:00
|
|
|
SYMBOL: 404-responder
|
|
|
|
|
|
|
|
[ <404> ] <trivial-responder> 404-responder set-global
|
|
|
|
|
|
|
|
: <redirect> ( to code message -- response )
|
2008-02-25 15:53:18 -05:00
|
|
|
<trivial-response>
|
2008-02-29 01:57:38 -05:00
|
|
|
swap "location" set-header ;
|
2008-02-25 15:53:18 -05:00
|
|
|
|
2008-02-29 01:57:38 -05:00
|
|
|
\ <redirect> DEBUG add-input-logging
|
|
|
|
|
|
|
|
: <permanent-redirect> ( to -- response )
|
2008-02-25 15:53:18 -05:00
|
|
|
301 "Moved Permanently" <redirect> ;
|
|
|
|
|
2008-02-29 01:57:38 -05:00
|
|
|
: <temporary-redirect> ( to -- response )
|
2008-02-25 15:53:18 -05:00
|
|
|
307 "Temporary Redirect" <redirect> ;
|
|
|
|
|
|
|
|
: <content> ( content-type -- response )
|
|
|
|
<response>
|
|
|
|
200 >>code
|
|
|
|
swap set-content-type ;
|
|
|
|
|
2008-02-29 01:57:38 -05:00
|
|
|
TUPLE: dispatcher default responders ;
|
2008-02-25 15:53:18 -05:00
|
|
|
|
2008-02-29 01:57:38 -05:00
|
|
|
: get-responder ( name dispatcher -- responder )
|
|
|
|
tuck responders>> at [ ] [ default>> ] ?if ;
|
2008-02-25 15:53:18 -05:00
|
|
|
|
2008-02-29 01:57:38 -05:00
|
|
|
: find-responder ( path dispatcher -- path responder )
|
|
|
|
>r [ CHAR: / = ] left-trim "/" split1
|
|
|
|
swap [ CHAR: / = ] right-trim r> get-responder ;
|
2008-02-25 15:53:18 -05:00
|
|
|
|
2008-02-29 01:57:38 -05:00
|
|
|
: redirect-with-/ ( request -- response )
|
2008-02-25 15:53:18 -05:00
|
|
|
dup path>> "/" append >>path
|
|
|
|
request-url <permanent-redirect> ;
|
|
|
|
|
2008-02-29 01:57:38 -05:00
|
|
|
M: dispatcher call-responder
|
|
|
|
over [
|
|
|
|
find-responder call-responder
|
|
|
|
] [
|
|
|
|
2drop redirect-with-/
|
|
|
|
] if ;
|
2008-02-25 15:53:18 -05:00
|
|
|
|
2008-02-29 01:57:38 -05:00
|
|
|
: <dispatcher> ( -- dispatcher )
|
|
|
|
404-responder get-global H{ } clone
|
|
|
|
dispatcher construct-boa ;
|
2008-02-25 15:53:18 -05:00
|
|
|
|
2008-02-29 01:57:38 -05:00
|
|
|
: add-responder ( dispatcher responder path -- dispatcher )
|
|
|
|
pick responders>> set-at ;
|
2008-02-25 15:53:18 -05:00
|
|
|
|
|
|
|
SYMBOL: virtual-hosts
|
|
|
|
SYMBOL: default-host
|
|
|
|
|
|
|
|
virtual-hosts global [ drop H{ } clone ] cache drop
|
2008-02-29 01:57:38 -05:00
|
|
|
default-host global [ drop 404-responder get-global ] cache drop
|
2008-02-25 15:53:18 -05:00
|
|
|
|
|
|
|
: find-virtual-host ( host -- responder )
|
|
|
|
virtual-hosts get at [ default-host get ] unless* ;
|
|
|
|
|
2008-02-29 01:57:38 -05:00
|
|
|
: <500> ( error -- response )
|
|
|
|
500 "Internal server error" <trivial-response>
|
|
|
|
swap [
|
|
|
|
"Internal server error" [
|
|
|
|
[ print-error nl :c ] with-html-stream
|
|
|
|
] simple-page
|
|
|
|
] curry >>body ;
|
|
|
|
|
2008-02-25 15:53:18 -05:00
|
|
|
: handle-request ( request -- )
|
|
|
|
[
|
2008-02-29 01:57:38 -05:00
|
|
|
dup dup path>> over host>>
|
|
|
|
find-virtual-host call-responder
|
|
|
|
] [ <500> ] recover
|
|
|
|
dup write-response
|
|
|
|
swap method>> "HEAD" =
|
|
|
|
[ drop ] [ write-response-body ] if ;
|
2008-02-25 15:53:18 -05:00
|
|
|
|
|
|
|
: default-timeout 1 minutes stdio get set-timeout ;
|
|
|
|
|
|
|
|
LOG: httpd-hit NOTICE
|
|
|
|
|
|
|
|
: log-request ( request -- )
|
|
|
|
{ method>> host>> path>> } map-exec-with httpd-hit ;
|
2008-02-07 18:07:43 -05:00
|
|
|
|
2008-02-29 01:57:38 -05:00
|
|
|
SYMBOL: development-mode
|
|
|
|
|
|
|
|
: (httpd) ( -- )
|
|
|
|
default-timeout
|
|
|
|
development-mode get-global
|
|
|
|
[ global [ refresh-all ] bind ] when
|
|
|
|
read-request dup log-request handle-request ;
|
|
|
|
|
2007-09-20 18:09:08 -04:00
|
|
|
: httpd ( port -- )
|
2008-02-29 01:57:38 -05:00
|
|
|
internet-server "http.server" [ (httpd) ] with-server ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
|
|
|
: httpd-main ( -- ) 8888 httpd ;
|
|
|
|
|
|
|
|
MAIN: httpd-main
|
2008-02-29 01:57:38 -05:00
|
|
|
|
|
|
|
: generate-key ( assoc -- str )
|
|
|
|
4 big-random >hex dup pick key?
|
|
|
|
[ drop generate-key ] [ nip ] if ;
|