]> gitweb.factorcode.org Git - factor.git/blob - basis/http/server/requests/requests-tests.factor
factor: second stab at [ ] [ ] unit-test -> { } [ ] unit-test
[factor.git] / basis / http / server / requests / requests-tests.factor
1 USING: accessors assocs continuations http http.client http.client.private
2 http.server http.server.requests io.crlf io.streams.limited io.streams.string
3 kernel math math.parser multiline namespaces peg sequences splitting
4 tools.test urls ;
5 IN: http.server.requests.tests
6
7 : request>string ( request -- string )
8     [ write-request ] with-string-writer ;
9
10 : string>request ( str -- request )
11     [ request-limit get limited-input read-request ] with-string-reader ;
12
13 ! POST requests
14 { "foo=bar" "7" } [
15     "foo=bar" "localhost" <post-request> request>string string>request
16     [ post-data>> data>> ] [ header>> "content-length" of ] bi
17 ] unit-test
18
19 { f "0" } [
20     "" "localhost" <post-request> request>string string>request
21     [ post-data>> data>> ] [ header>> "content-length" of ] bi
22 ] unit-test
23
24 ! Incorrect content-length works fine
25 { H{ { "foo" "bar" } } } [
26     { { "foo" "bar" } } "localhost" <post-request> request>string
27     "7" "190" replace string>request post-data>> params>>
28 ] unit-test
29
30 { H{ { "name" "John Smith" } } } [
31     { { "name" "John Smith" } } "localhost" <post-request> request>string
32     string>request post-data>> params>>
33 ] unit-test
34
35 ! multipart/form-data
36 STRING: test-multipart/form-data
37 POST / HTTP/1.1
38 Accept: */*
39 Accept-Encoding: gzip, deflate
40 Connection: keep-alive
41 Content-Length: 151
42 Content-Type: multipart/form-data; boundary=768de80194d942619886d23f1337aa15
43 Host: localhost:8000
44 User-Agent: HTTPie/0.9.0-dev
45
46 --768de80194d942619886d23f1337aa15
47 Content-Disposition: form-data; name="text"; filename="upload.txt"
48
49 hello
50 --768de80194d942619886d23f1337aa15--
51
52 ;
53 {
54     "upload.txt"
55     H{
56         { "content-disposition"
57           "form-data; name=\"text\"; filename=\"upload.txt\"" }
58     }
59 } [
60     test-multipart/form-data lf>crlf string>request
61     post-data>> params>> "text" of [ filename>> ] [ headers>> ] bi
62 ] unit-test
63
64 ! Error handling
65 ! If the incoming request is not valid, read-request should throw an
66 ! appropriate error.
67 STRING: test-multipart/form-data-missing-boundary
68 POST / HTTP/1.1
69 Accept: */*
70 Accept-Encoding: gzip, deflate
71 Connection: keep-alive
72 Content-Length: 151
73 Content-Type: multipart/form-data; abcd
74 Host: localhost:8000
75 User-Agent: HTTPie/0.9.0-dev
76
77 --768de80194d942619886d23f1337aa15
78 Content-Disposition: form-data; name="text"; filename="upload.txt"
79
80 hello
81 --768de80194d942619886d23f1337aa15--
82
83 ;
84 [ test-multipart/form-data-missing-boundary string>request ]
85 [ no-boundary? ] must-fail-with
86
87 ! Relative urls are invalid.
88 [ "GET foo HTTP/1.1" string>request ] [ path>> "foo" = ] must-fail-with
89
90 ! Empty request lines
91 [ "" string>request ] [ parse-error>> parse-error? ] must-fail-with
92
93 ! Missing content-length is probably not ok. It's plausible
94 ! transfer-length could replace it, but we don't handle it atm anyway.
95 [
96     { { "foo" "bar" } } "localhost" <post-request> request>string
97     "content-length" "foo" replace string>request
98 ] [ content-length-missing? ] must-fail-with
99
100 ! Non-numeric content-length is ofc crap.
101 [
102     { { "foo" "bar" } } "localhost" <post-request> request>string
103     "7" "i am not a number!" replace string>request
104 ] [
105     [ invalid-content-length? ]
106     [ content-length>> "i am not a number!" = ] bi and
107 ] must-fail-with
108
109 ! Negative is it too.
110 [
111     { { "foo" "bar" } } "localhost" <post-request> request>string
112     "7" "-1234" replace string>request
113 ] [
114     [ invalid-content-length? ]
115     [ content-length>> -1234 = ] bi and
116 ] must-fail-with
117
118 ! And too big
119 [
120     { { "foo" "bar" } } "localhost" <post-request> request>string
121     "7" upload-limit get 1 + number>string replace string>request
122 ] [
123     [ invalid-content-length? ]
124     [ content-length>> upload-limit get 1 + = ] bi and
125 ] must-fail-with
126
127
128 ! RFC 2616: Section 4.1
129 ! In the interest of robustness, servers SHOULD ignore any empty
130 ! line(s) received where a Request-Line is expected. In other words, if
131 ! the server is reading the protocol stream at the beginning of a
132 ! message and receives a CRLF first, it should ignore the CRLF.
133 {
134     T{ request
135         { method "GET" }
136         { url URL" /" }
137         { version "1.0" }
138         { header H{ } }
139         { cookies V{ } }
140         { redirects 10 }
141     }
142 } [
143     "\r\n\r\n\r\nGET / HTTP/1.0\r\n\r\n" [ read-request ] with-string-reader
144 ] unit-test
145
146 ! RFC 2616: Section 19.3
147 ! The line terminator for message-header fields is the sequence CRLF.
148 ! However, we recommend that applications, when parsing such headers,
149 ! recognize a single LF as a line terminator and ignore the leading CR.
150 { t } [
151     {
152         "GET / HTTP/1.1"
153         "connection: close"
154         "host: 127.0.0.1:55532"
155         "user-agent: Factor http.client"
156     } [ "\n" join ] [ "\r\n" join ] bi
157     [ string>request ] same?
158 ] unit-test