1 USING: accessors assocs continuations http http.client
2 http.client.private http.server http.server.requests io.crlf
3 io.streams.limited io.streams.string linked-assocs kernel math
4 math.parser multiline namespaces peg sequences splitting
6 IN: http.server.requests.tests
8 : request>string ( request -- string )
9 [ write-request ] with-string-writer ;
11 : string>request ( str -- request )
12 [ request-limit get limited-input read-request ] with-string-reader ;
16 "foo=bar" "localhost" <post-request> request>string string>request
17 [ post-data>> data>> ] [ header>> "content-length" of ] bi
21 "" "localhost" <post-request> request>string string>request
22 [ post-data>> data>> ] [ header>> "content-length" of ] bi
25 ! Incorrect content-length works fine
26 { LH{ { "foo" "bar" } } } [
27 { { "foo" "bar" } } "localhost" <post-request> request>string
28 "7" "190" replace string>request post-data>> params>>
31 { LH{ { "name" "John Smith" } } } [
32 { { "name" "John Smith" } } "localhost" <post-request> request>string
33 string>request post-data>> params>>
37 STRING: test-multipart/form-data
40 Accept-Encoding: gzip, deflate
41 Connection: keep-alive
43 Content-Type: multipart/form-data; boundary=768de80194d942619886d23f1337aa15
45 User-Agent: HTTPie/0.9.0-dev
47 --768de80194d942619886d23f1337aa15
48 Content-Disposition: form-data; name="text"; filename="upload.txt"
51 --768de80194d942619886d23f1337aa15--
57 { "content-disposition"
58 "form-data; name=\"text\"; filename=\"upload.txt\"" }
61 test-multipart/form-data lf>crlf string>request
62 post-data>> params>> "text" of [ filename>> ] [ headers>> ] bi
66 ! If the incoming request is not valid, read-request should throw an
68 STRING: test-multipart/form-data-missing-boundary
71 Accept-Encoding: gzip, deflate
72 Connection: keep-alive
74 Content-Type: multipart/form-data; abcd
76 User-Agent: HTTPie/0.9.0-dev
78 --768de80194d942619886d23f1337aa15
79 Content-Disposition: form-data; name="text"; filename="upload.txt"
82 --768de80194d942619886d23f1337aa15--
85 [ test-multipart/form-data-missing-boundary string>request ]
86 [ no-boundary? ] must-fail-with
88 ! Relative urls are invalid.
89 [ "GET foo HTTP/1.1" string>request ] [ path>> "foo" = ] must-fail-with
92 [ "" string>request ] [ parse-error>> parse-error? ] must-fail-with
94 ! Missing content-length is probably not ok. It's plausible
95 ! transfer-length could replace it, but we don't handle it atm anyway.
97 { { "foo" "bar" } } "localhost" <post-request> request>string
98 "content-length" "foo" replace string>request
99 ] [ content-length-missing? ] must-fail-with
101 ! Non-numeric content-length is ofc crap.
103 { { "foo" "bar" } } "localhost" <post-request> request>string
104 "7" "i am not a number!" replace string>request
106 [ invalid-content-length? ]
107 [ content-length>> "i am not a number!" = ] bi and
110 ! Negative is it too.
112 { { "foo" "bar" } } "localhost" <post-request> request>string
113 "7" "-1234" replace string>request
115 [ invalid-content-length? ]
116 [ content-length>> -1234 = ] bi and
121 { { "foo" "bar" } } "localhost" <post-request> request>string
122 "7" upload-limit get 1 + number>string replace string>request
124 [ invalid-content-length? ]
125 [ content-length>> upload-limit get 1 + = ] bi and
129 ! RFC 2616: Section 4.1
130 ! In the interest of robustness, servers SHOULD ignore any empty
131 ! line(s) received where a Request-Line is expected. In other words, if
132 ! the server is reading the protocol stream at the beginning of a
133 ! message and receives a CRLF first, it should ignore the CRLF.
145 "\r\n\r\n\r\nGET / HTTP/1.0\r\n\r\n" [ read-request ] with-string-reader
148 ! RFC 2616: Section 19.3
149 ! The line terminator for message-header fields is the sequence CRLF.
150 ! However, we recommend that applications, when parsing such headers,
151 ! recognize a single LF as a line terminator and ignore the leading CR.
156 "host: 127.0.0.1:55532"
157 "user-agent: Factor http.client"
158 } [ join-lines ] [ "\r\n" join ] bi
159 [ string>request ] same?