1 USING: accessors combinators.short-circuit continuations db
2 db.sqlite db.tuples destructors furnace furnace.actions
3 furnace.alloy furnace.auth furnace.auth.login
4 furnace.conversations furnace.db furnace.redirection
5 furnace.sessions html.components html.forms http http.client
6 http.client.private http.download http.server
7 http.server.dispatchers http.server.redirection
8 http.server.requests http.server.responses http.server.static io
9 io.crlf io.directories io.encodings.ascii io.encodings.binary
10 io.encodings.utf8 io.files io.files.temp io.servers io.sockets
11 io.streams.string kernel literals locals make multiline
12 namespaces random sequences splitting threads tools.test urls
13 validators xml xml.data xml.traversal ;
16 { "text/plain" "UTF-8" } [ "text/plain" parse-content-type ] unit-test
18 { "text/html" "ASCII" } [ "text/html; charset=ASCII" parse-content-type ] unit-test
20 { "text/html" "utf-8" } [ "text/html; charset=\"utf-8\"" parse-content-type ] unit-test
22 { "application/octet-stream" f } [ "application/octet-stream" parse-content-type ] unit-test
24 { "localhost" f } [ "localhost" parse-host ] unit-test
25 { "localhost" 8888 } [ "localhost:8888" parse-host ] unit-test
26 { "::1" 8888 } [ "::1:8888" parse-host ] unit-test
27 { "127.0.0.1" 8888 } [ "127.0.0.1:8888" parse-host ] unit-test
29 { "localhost" } [ T{ url { protocol "http" } { host "localhost" } } unparse-host ] unit-test
30 { "localhost" } [ T{ url { protocol "http" } { host "localhost" } { port 80 } } unparse-host ] unit-test
31 { "localhost" } [ T{ url { protocol "https" } { host "localhost" } { port 443 } } unparse-host ] unit-test
32 { "localhost:8080" } [ T{ url { protocol "http" } { host "localhost" } { port 8080 } } unparse-host ] unit-test
33 { "localhost:8443" } [ T{ url { protocol "https" } { host "localhost" } { port 8443 } } unparse-host ] unit-test
35 STRING: read-request-test-1
40 Content-type: application/octet-stream
47 { url T{ url { path "/bar" } } }
48 { proxy-url T{ url } }
51 { header H{ { "some-header" "1; 2" } { "content-length" "4" } { "content-type" "application/octet-stream" } } }
52 { post-data T{ post-data { data "blah" } { content-type "application/octet-stream" } } }
57 read-request-test-1 lf>crlf [
62 STRING: read-request-test-1'
65 content-type: application/octet-stream
71 ${ read-request-test-1' } [
72 read-request-test-1 lf>crlf
73 [ read-request ] with-string-reader
74 [ write-request ] with-string-writer
76 split-lines join-lines
79 STRING: read-request-test-2
87 { url T{ url { host "www.sex.com" } { path "/bar" } } }
88 { proxy-url T{ url } }
91 { header H{ { "host" "www.sex.com" } } }
96 read-request-test-2 lf>crlf [
101 STRING: read-request-test-2'
103 Host: www.sex.com:101
109 { url T{ url { host "www.sex.com" } { port 101 } { path "/bar" } } }
110 { proxy-url T{ url } }
113 { header H{ { "host" "www.sex.com:101" } } }
118 read-request-test-2' lf>crlf [
123 STRING: read-request-test-3
128 STRING: read-request-test-4
130 Host: "www.amazon.com"
135 read-request-test-4 lf>crlf [ read-request ] with-string-reader
139 STRING: read-response-test-1
140 HTTP/1.1 404 not found
141 Content-Type: text/html; charset=UTF-8
150 { message "not found" }
151 { header H{ { "content-type" "text/html; charset=UTF-8" } } }
153 { content-type "text/html" }
154 { content-charset "UTF-8" }
155 { content-encoding utf8 }
158 read-response-test-1 lf>crlf
159 [ read-response ] with-string-reader
163 STRING: read-response-test-1'
164 HTTP/1.1 404 not found
165 content-type: text/html; charset=UTF-8
169 ${ read-response-test-1' } [
170 URL" http://localhost/" url set
171 read-response-test-1 lf>crlf
172 [ read-response ] with-string-reader
173 [ write-response ] with-string-writer
175 split-lines join-lines
179 "rmid=732423sdfs73242; path=/; domain=.example.net; expires=Fri, 31-Dec-2010 23:59:59 GMT"
180 dup parse-set-cookie first unparse-set-cookie =
189 { domain "example.com" }
192 } [ "lang=en-US; Path=/; Domain=example.com" parse-set-cookie ] unit-test
196 dup parse-set-cookie first unparse-set-cookie =
199 STRING: read-response-test-2
200 HTTP/1.1 200 Content follows
201 Set-Cookie: oo="bar; a=b"; httponly=yes; sid=123456
207 read-response-test-2 lf>crlf
208 [ read-response ] with-string-reader
212 STRING: read-response-test-3
213 HTTP/1.1 200 Content follows
214 Set-Cookie: oo="bar; a=b"; comment="your mom"; httponly=yes
220 read-response-test-3 lf>crlf
221 [ read-response ] with-string-reader
227 : add-quit-action ( responder -- responder )
229 [ stop-this-server "Goodbye" "text/html" <content> ] >>display
230 "quit" add-responder ;
232 : test-db-file ( -- path ) "test.db" temp-file ;
234 : test-db ( -- db ) test-db-file <sqlite-db> ;
236 : add-addr ( url -- url' )
237 >url clone "addr" get set-url-addr ;
239 : stop-test-httpd ( -- )
240 "http://localhost/quit" add-addr http-get nip
244 test-db-file ?delete-file
251 : test-with-dispatcher ( dispatcher quot -- )
252 [ main-responder ] dip '[
253 <http-server> 0 >>insecure f >>secure
255 server-addrs random "addr" set @
256 ] with-threaded-server
257 ] with-variable ; inline
259 :: test-with-db-persistence ( db-persistence quot -- )
261 quot test-with-dispatcher
262 ] with-disposal ; inline
267 "vocab:http/test" <static> >>default
268 "nested" add-responder
270 [ URL" redirect-loop" <temporary-redirect> ] >>display
271 "redirect-loop" add-responder [
274 "vocab:http/test/foo.html" ascii file-contents
275 "http://localhost/nested/foo.html" add-addr http-get nip =
278 [ "http://localhost/redirect-loop" add-addr http-get nip ]
279 [ too-many-redirects? ] must-fail-with
282 "http://localhost/quit" add-addr http-get nip
285 ] test-with-dispatcher
287 ! HTTP client redirect bug
290 <action> [ "quit" <temporary-redirect> ] >>display
291 "redirect" add-responder [
294 "http://localhost/redirect" add-addr http-get nip
298 [ stop-test-httpd ] ignore-errors
301 ] test-with-dispatcher
304 : 404? ( response -- ? )
307 [ response>> response? ]
308 [ response>> code>> 404 = ]
318 <action> "" add-responder
320 test-db <db-persistence> [
322 ! This should give a 404 not an infinite redirect loop
323 [ "http://localhost/d/blah" add-addr http-get nip ] [ 404? ] must-fail-with
325 ! This should give a 404 not an infinite redirect loop
326 [ "http://localhost/blah/" add-addr http-get nip ] [ 404? ] must-fail-with
328 [ "Goodbye" ] [ "http://localhost/quit" add-addr http-get nip ] unit-test
330 ] test-with-db-persistence
333 <action> [ [ "Hi" write ] "text/plain" <content> ] >>display
338 test-db <db-persistence> [
340 [ "Hi" ] [ "http://localhost/" add-addr http-get nip ] unit-test
342 [ "Goodbye" ] [ "http://localhost/quit" add-addr http-get nip ] unit-test
344 ] test-with-db-persistence
348 : test-a ( xml -- value )
349 string>xml body>> "input" deep-tag-named "value" attr ;
353 [ a get-global "a" set-value ] >>init
354 [ [ "<!DOCTYPE html><html>" write "a" <field> render "</html>" write ] "text/html" <content> ] >>display
355 [ { { "a" [ v-integer ] } } validate-params ] >>validate
356 [ "a" value a set-global URL" " <redirect> ] >>submit
361 test-db <db-persistence> [
366 "http://localhost/" add-addr http-get
367 swap dup cookies>> "cookies" set session-id-key get-cookie
368 value>> "session-id" set test-a
374 "http://localhost" add-addr "__u" ,,
375 "session-id" get session-id-key ,,
377 "http://localhost/" add-addr <post-request> "cookies" get >>cookies
378 http-request nip test-a
381 [ 4 ] [ a get-global ] unit-test
387 "http://localhost" add-addr "__u" ,,
388 "session-id" get session-id-key ,,
390 "http://localhost/" add-addr <post-request> "cookies" get >>cookies
391 http-request nip test-a
394 [ 4 ] [ a get-global ] unit-test
396 [ "Goodbye" ] [ "http://localhost/quit" add-addr http-get nip ] unit-test
398 ] test-with-db-persistence
401 { f } [ <404> dup clone "b" "a" set-header drop "a" header ] unit-test
402 { f } [ <404> dup clone "b" "a" <cookie> put-cookie drop "a" get-cookie ] unit-test
405 { "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" } [
406 <request> "Aladdin" "open sesame" set-basic-auth "Authorization" header
409 ! Test a corner case with static responder
412 "vocab:http/test/foo.html" <static> >>default [
414 "http://localhost/" add-addr http-get nip
415 "vocab:http/test/foo.html" ascii file-contents =
418 [ ] [ stop-test-httpd ] unit-test
420 ] test-with-dispatcher
422 ! Check behavior of 307 redirect (reported by Chris Double)
426 [ "b" <temporary-redirect> ] >>submit
430 request get post-data>> data>> "data" =
431 [ "OK" "text/plain" <content> ] [ "OOPS" throw ] if
435 [ "OK" ] [ "data" "http://localhost/a" add-addr http-post nip ] unit-test
437 ! Check that download throws errors (reported by Chris Double)
440 "http://localhost/tweet_my_twat" add-addr download drop
441 ] with-temp-directory
444 [ ] [ stop-test-httpd ] unit-test
446 ] test-with-dispatcher
448 ! Check that index.fhtml works
450 "resource:basis/http/test/" <static> enable-fhtml >>default
453 [ "OK\n" ] [ "http://localhost/" add-addr http-get nip ] unit-test
455 [ ] [ stop-test-httpd ] unit-test
457 ] test-with-dispatcher
459 ! Check that just closing the socket without sending anything works
462 [ ] [ "addr" get binary [ ] with-client ] unit-test
464 [ ] [ stop-test-httpd ] unit-test
466 ] test-with-dispatcher