159 lines
4.6 KiB
Factor
159 lines
4.6 KiB
Factor
USING: accessors assocs continuations http http.client http.client.private
|
|
http.server http.server.requests io.crlf io.streams.limited io.streams.string
|
|
kernel math math.parser multiline namespaces peg sequences splitting
|
|
tools.test urls ;
|
|
IN: http.server.requests.tests
|
|
|
|
: request>string ( request -- string )
|
|
[ write-request ] with-string-writer ;
|
|
|
|
: string>request ( str -- request )
|
|
[ request-limit get limited-input read-request ] with-string-reader ;
|
|
|
|
! POST requests
|
|
{ "foo=bar" "7" } [
|
|
"foo=bar" "localhost" <post-request> request>string string>request
|
|
[ post-data>> data>> ] [ header>> "content-length" of ] bi
|
|
] unit-test
|
|
|
|
{ f "0" } [
|
|
"" "localhost" <post-request> request>string string>request
|
|
[ post-data>> data>> ] [ header>> "content-length" of ] bi
|
|
] unit-test
|
|
|
|
! Incorrect content-length works fine
|
|
{ H{ { "foo" "bar" } } } [
|
|
{ { "foo" "bar" } } "localhost" <post-request> request>string
|
|
"7" "190" replace string>request post-data>> params>>
|
|
] unit-test
|
|
|
|
{ H{ { "name" "John Smith" } } } [
|
|
{ { "name" "John Smith" } } "localhost" <post-request> request>string
|
|
string>request post-data>> params>>
|
|
] unit-test
|
|
|
|
! multipart/form-data
|
|
STRING: test-multipart/form-data
|
|
POST / HTTP/1.1
|
|
Accept: */*
|
|
Accept-Encoding: gzip, deflate
|
|
Connection: keep-alive
|
|
Content-Length: 151
|
|
Content-Type: multipart/form-data; boundary=768de80194d942619886d23f1337aa15
|
|
Host: localhost:8000
|
|
User-Agent: HTTPie/0.9.0-dev
|
|
|
|
--768de80194d942619886d23f1337aa15
|
|
Content-Disposition: form-data; name="text"; filename="upload.txt"
|
|
|
|
hello
|
|
--768de80194d942619886d23f1337aa15--
|
|
|
|
;
|
|
{
|
|
"upload.txt"
|
|
H{
|
|
{ "content-disposition"
|
|
"form-data; name=\"text\"; filename=\"upload.txt\"" }
|
|
}
|
|
} [
|
|
test-multipart/form-data lf>crlf string>request
|
|
post-data>> params>> "text" of [ filename>> ] [ headers>> ] bi
|
|
] unit-test
|
|
|
|
! Error handling
|
|
! If the incoming request is not valid, read-request should throw an
|
|
! appropriate error.
|
|
STRING: test-multipart/form-data-missing-boundary
|
|
POST / HTTP/1.1
|
|
Accept: */*
|
|
Accept-Encoding: gzip, deflate
|
|
Connection: keep-alive
|
|
Content-Length: 151
|
|
Content-Type: multipart/form-data; abcd
|
|
Host: localhost:8000
|
|
User-Agent: HTTPie/0.9.0-dev
|
|
|
|
--768de80194d942619886d23f1337aa15
|
|
Content-Disposition: form-data; name="text"; filename="upload.txt"
|
|
|
|
hello
|
|
--768de80194d942619886d23f1337aa15--
|
|
|
|
;
|
|
[ test-multipart/form-data-missing-boundary string>request ]
|
|
[ no-boundary? ] must-fail-with
|
|
|
|
! Relative urls are invalid.
|
|
[ "GET foo HTTP/1.1" string>request ] [ path>> "foo" = ] must-fail-with
|
|
|
|
! Empty request lines
|
|
[ "" string>request ] [ parse-error>> parse-error? ] must-fail-with
|
|
|
|
! Missing content-length is probably not ok. It's plausible
|
|
! transfer-length could replace it, but we don't handle it atm anyway.
|
|
[
|
|
{ { "foo" "bar" } } "localhost" <post-request> request>string
|
|
"content-length" "foo" replace string>request
|
|
] [ content-length-missing? ] must-fail-with
|
|
|
|
! Non-numeric content-length is ofc crap.
|
|
[
|
|
{ { "foo" "bar" } } "localhost" <post-request> request>string
|
|
"7" "i am not a number!" replace string>request
|
|
] [
|
|
[ invalid-content-length? ]
|
|
[ content-length>> "i am not a number!" = ] bi and
|
|
] must-fail-with
|
|
|
|
! Negative is it too.
|
|
[
|
|
{ { "foo" "bar" } } "localhost" <post-request> request>string
|
|
"7" "-1234" replace string>request
|
|
] [
|
|
[ invalid-content-length? ]
|
|
[ content-length>> -1234 = ] bi and
|
|
] must-fail-with
|
|
|
|
! And too big
|
|
[
|
|
{ { "foo" "bar" } } "localhost" <post-request> request>string
|
|
"7" upload-limit get 1 + number>string replace string>request
|
|
] [
|
|
[ invalid-content-length? ]
|
|
[ content-length>> upload-limit get 1 + = ] bi and
|
|
] must-fail-with
|
|
|
|
|
|
! RFC 2616: Section 4.1
|
|
! In the interest of robustness, servers SHOULD ignore any empty
|
|
! line(s) received where a Request-Line is expected. In other words, if
|
|
! the server is reading the protocol stream at the beginning of a
|
|
! message and receives a CRLF first, it should ignore the CRLF.
|
|
[
|
|
T{ request
|
|
{ method "GET" }
|
|
{ url URL" /" }
|
|
{ version "1.0" }
|
|
{ header H{ } }
|
|
{ cookies V{ } }
|
|
{ redirects 10 }
|
|
}
|
|
] [
|
|
"\r\n\r\n\r\nGET / HTTP/1.0\r\n\r\n" [ read-request ] with-string-reader
|
|
] unit-test
|
|
|
|
! RFC 2616: Section 19.3
|
|
! The line terminator for message-header fields is the sequence CRLF.
|
|
! However, we recommend that applications, when parsing such headers,
|
|
! recognize a single LF as a line terminator and ignore the leading CR.
|
|
[ t ] [
|
|
{
|
|
"GET / HTTP/1.1"
|
|
"connection: close"
|
|
"host: 127.0.0.1:55532"
|
|
"user-agent: Factor http.client"
|
|
} [ "\n" join ] [ "\r\n" join ] bi
|
|
[ string>request ] same?
|
|
] unit-test
|