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
5 IN: http.server.requests.tests
7 : request>string ( request -- string )
8 [ write-request ] with-string-writer ;
10 : string>request ( str -- request )
11 [ request-limit get limited-input read-request ] with-string-reader ;
15 "foo=bar" "localhost" <post-request> request>string string>request
16 [ post-data>> data>> ] [ header>> "content-length" of ] bi
20 "" "localhost" <post-request> request>string string>request
21 [ post-data>> data>> ] [ header>> "content-length" of ] bi
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>>
30 { H{ { "name" "John Smith" } } } [
31 { { "name" "John Smith" } } "localhost" <post-request> request>string
32 string>request post-data>> params>>
36 STRING: test-multipart/form-data
39 Accept-Encoding: gzip, deflate
40 Connection: keep-alive
42 Content-Type: multipart/form-data; boundary=768de80194d942619886d23f1337aa15
44 User-Agent: HTTPie/0.9.0-dev
46 --768de80194d942619886d23f1337aa15
47 Content-Disposition: form-data; name="text"; filename="upload.txt"
50 --768de80194d942619886d23f1337aa15--
56 { "content-disposition"
57 "form-data; name=\"text\"; filename=\"upload.txt\"" }
60 test-multipart/form-data lf>crlf string>request
61 post-data>> params>> "text" of [ filename>> ] [ headers>> ] bi
65 ! If the incoming request is not valid, read-request should throw an
67 STRING: test-multipart/form-data-missing-boundary
70 Accept-Encoding: gzip, deflate
71 Connection: keep-alive
73 Content-Type: multipart/form-data; abcd
75 User-Agent: HTTPie/0.9.0-dev
77 --768de80194d942619886d23f1337aa15
78 Content-Disposition: form-data; name="text"; filename="upload.txt"
81 --768de80194d942619886d23f1337aa15--
84 [ test-multipart/form-data-missing-boundary string>request ]
85 [ no-boundary? ] must-fail-with
87 ! Relative urls are invalid.
88 [ "GET foo HTTP/1.1" string>request ] [ path>> "foo" = ] must-fail-with
91 [ "" string>request ] [ parse-error>> parse-error? ] must-fail-with
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.
96 { { "foo" "bar" } } "localhost" <post-request> request>string
97 "content-length" "foo" replace string>request
98 ] [ content-length-missing? ] must-fail-with
100 ! Non-numeric content-length is ofc crap.
102 { { "foo" "bar" } } "localhost" <post-request> request>string
103 "7" "i am not a number!" replace string>request
105 [ invalid-content-length? ]
106 [ content-length>> "i am not a number!" = ] bi and
109 ! Negative is it too.
111 { { "foo" "bar" } } "localhost" <post-request> request>string
112 "7" "-1234" replace string>request
114 [ invalid-content-length? ]
115 [ content-length>> -1234 = ] bi and
120 { { "foo" "bar" } } "localhost" <post-request> request>string
121 "7" upload-limit get 1 + number>string replace string>request
123 [ invalid-content-length? ]
124 [ content-length>> upload-limit get 1 + = ] bi and
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.
143 "\r\n\r\n\r\nGET / HTTP/1.0\r\n\r\n" [ read-request ] with-string-reader
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.
154 "host: 127.0.0.1:55532"
155 "user-agent: Factor http.client"
156 } [ "\n" join ] [ "\r\n" join ] bi
157 [ string>request ] same?