]> gitweb.factorcode.org Git - factor.git/blob - basis/http/server/static/static.factor
Updating code for make and fry changes
[factor.git] / basis / http / server / static / static.factor
1 ! Copyright (C) 2004, 2008 Slava Pestov.\r
2 ! See http://factorcode.org/license.txt for BSD license.\r
3 USING: calendar io io.files kernel math math.order\r
4 math.parser namespaces parser sequences strings\r
5 assocs hashtables debugger mime-types sorting logging\r
6 calendar.format accessors\r
7 io.encodings.binary fry xml.entities destructors urls\r
8 html.elements html.templates.fhtml\r
9 http\r
10 http.server\r
11 http.server.responses\r
12 http.server.redirection ;\r
13 IN: http.server.static\r
14 \r
15 ! special maps mime types to quots with effect ( path -- )\r
16 TUPLE: file-responder root hook special allow-listings ;\r
17 \r
18 : modified-since? ( filename -- ? )\r
19     request get "if-modified-since" header dup [\r
20         [ file-info modified>> ] [ rfc822>timestamp ] bi* after?\r
21     ] [\r
22         2drop t\r
23     ] if ;\r
24 \r
25 : <file-responder> ( root hook -- responder )\r
26     file-responder new\r
27         swap >>hook\r
28         swap >>root\r
29         H{ } clone >>special ;\r
30 \r
31 : (serve-static) ( path mime-type -- response )\r
32     [\r
33         [ binary <file-reader> &dispose ] dip\r
34         <content> binary >>content-charset\r
35     ]\r
36     [ drop file-info [ size>> ] [ modified>> ] bi ] 2bi\r
37     [ "content-length" set-header ]\r
38     [ "last-modified" set-header ] bi* ;\r
39 \r
40 : <static> ( root -- responder )\r
41     [ (serve-static) ] <file-responder> ;\r
42 \r
43 : serve-static ( filename mime-type -- response )\r
44     over modified-since?\r
45     [ file-responder get hook>> call ] [ 2drop <304> ] if ;\r
46 \r
47 : serving-path ( filename -- filename )\r
48     file-responder get root>> trim-right-separators\r
49     "/"\r
50     rot "" or trim-left-separators 3append ;\r
51 \r
52 : serve-file ( filename -- response )\r
53     dup mime-type\r
54     dup file-responder get special>> at\r
55     [ call ] [ serve-static ] ?if ;\r
56 \r
57 \ serve-file NOTICE add-input-logging\r
58 \r
59 : file. ( name dirp -- )\r
60     [ "/" append ] when\r
61     dup <a =href a> escape-string write </a> ;\r
62 \r
63 : directory. ( path -- )\r
64     dup file-name [\r
65         [ <h1> file-name escape-string write </h1> ]\r
66         [\r
67             <ul>\r
68                 directory sort-keys\r
69                 [ <li> file. </li> ] assoc-each\r
70             </ul>\r
71         ] bi\r
72     ] simple-page ;\r
73 \r
74 : list-directory ( directory -- response )\r
75     file-responder get allow-listings>> [\r
76         '[ _ directory. ] "text/html" <content>\r
77     ] [\r
78         drop <403>\r
79     ] if ;\r
80 \r
81 : find-index ( filename -- path )\r
82     "index.html" append-path dup exists? [ drop f ] unless ;\r
83 \r
84 : serve-directory ( filename -- response )\r
85     url get path>> "/" tail? [\r
86         dup\r
87         find-index [ serve-file ] [ list-directory ] ?if\r
88     ] [\r
89         drop\r
90         url get clone [ "/" append ] change-path <permanent-redirect>\r
91     ] if ;\r
92 \r
93 : serve-object ( filename -- response )\r
94     serving-path dup exists?\r
95     [ dup file-info directory? [ serve-directory ] [ serve-file ] if ]\r
96     [ drop <404> ]\r
97     if ;\r
98 \r
99 M: file-responder call-responder* ( path responder -- response )\r
100     file-responder set\r
101     ".." over member?\r
102     [ drop <400> ] [ "/" join serve-object ] if ;\r
103 \r
104 ! file responder integration\r
105 : enable-fhtml ( responder -- responder )\r
106     [ <fhtml> "text/html" <content> ]\r
107     "application/x-factor-server-page"\r
108     pick special>> set-at ;\r