v2 / vlib / fasthttp / request_parser_test.v
127 lines · 102 sloc · 4.33 KB · b7113f8425b17fc689a617834a7e6083e3193572
Raw
1module fasthttp
2
3fn test_parse_http1_request_line_valid_request() {
4 buffer := 'GET /path/to/resource HTTP/1.1\r\n'.bytes()
5 mut req := HttpRequest{
6 buffer: buffer
7 }
8
9 parse_http1_request_line(mut req) or { panic(err) }
10
11 assert req.method.to_string(req.buffer) == 'GET'
12 assert req.path.to_string(req.buffer) == '/path/to/resource'
13 assert req.version.to_string(req.buffer) == 'HTTP/1.1'
14}
15
16fn test_parse_http1_request_line_invalid_request() {
17 buffer := 'INVALID REQUEST LINE'.bytes()
18 mut req := HttpRequest{
19 buffer: buffer
20 }
21
22 mut has_error := false
23 parse_http1_request_line(mut req) or {
24 has_error = true
25 assert err.msg() == 'Invalid HTTP request line: Missing CR'
26 }
27 assert has_error, 'Expected error for invalid request line'
28}
29
30fn test_decode_http_request_valid_request() {
31 buffer := 'POST /api/resource HTTP/1.0\r\n'.bytes()
32 req := decode_http_request(buffer) or { panic(err) }
33
34 assert req.method.to_string(req.buffer) == 'POST'
35 assert req.path.to_string(req.buffer) == '/api/resource'
36 assert req.version.to_string(req.buffer) == 'HTTP/1.0'
37}
38
39fn test_decode_http_request_invalid_request() {
40 buffer := 'INVALID REQUEST LINE'.bytes()
41
42 mut has_error := false
43 decode_http_request(buffer) or {
44 has_error = true
45 assert err.msg() == 'Invalid HTTP request line: Missing CR'
46 }
47 assert has_error, 'Expected error for invalid request'
48}
49
50fn test_decode_http_request_with_headers_and_body() {
51 raw := 'POST /submit HTTP/1.1\r\n' + 'Host: localhost\r\n' +
52 'Content-Type: application/json\r\n' + 'Content-Length: 18\r\n' + '\r\n' +
53 '{"status": "ok"}'
54
55 buffer := raw.bytes()
56 req := decode_http_request(buffer) or { panic(err) }
57
58 assert req.method.to_string(req.buffer) == 'POST'
59 assert req.path.to_string(req.buffer) == '/submit'
60
61 // Verify Header Fields block
62 // Should contain everything between the first \r\n and the \r\n\r\n
63 header_str := req.header_fields.to_string(req.buffer)
64 assert header_str == 'Host: localhost\r\nContent-Type: application/json\r\nContent-Length: 18'
65
66 // Verify Body
67 assert req.body.to_string(req.buffer) == '{"status": "ok"}'
68}
69
70fn test_decode_http_request_no_body() {
71 // A GET request usually ends with \r\n\r\n and no body
72 buffer := 'GET /index.html HTTP/1.1\r\nUser-Agent: V\r\n\r\n'.bytes()
73 req := decode_http_request(buffer) or { panic(err) }
74
75 assert req.header_fields.to_string(req.buffer) == 'User-Agent: V'
76 assert req.body.len == 0
77}
78
79fn test_decode_http_request_malformed_no_double_crlf() {
80 // Request that never finishes headers
81 buffer := 'GET / HTTP/1.1\r\nHost: example.com\r\n'.bytes()
82 req := decode_http_request(buffer) or { panic(err) }
83
84 // Based on our implementation, if no \r\n\r\n is found,
85 // body should be empty and headers go to the end.
86 assert req.body.len == 0
87 assert req.header_fields.to_string(req.buffer) == 'Host: example.com'
88}
89
90fn test_has_complete_body_without_body() {
91 buffer := 'GET / HTTP/1.1\r\nHost: example.com\r\n\r\n'.bytes()
92 assert has_complete_body(buffer.data, buffer.len)
93}
94
95fn test_has_complete_body_with_incomplete_content_length() {
96 buffer := 'POST /upload HTTP/1.1\r\nHost: example.com\r\nContent-Length: 5\r\n\r\n123'.bytes()
97 assert !has_complete_body(buffer.data, buffer.len)
98}
99
100fn test_has_complete_body_with_complete_content_length() {
101 buffer := 'POST /upload HTTP/1.1\r\nHost: example.com\r\nContent-Length: 5\r\n\r\n12345'.bytes()
102 assert has_complete_body(buffer.data, buffer.len)
103}
104
105fn test_has_complete_body_with_incomplete_chunked_body() {
106 buffer :=
107 'POST /upload HTTP/1.1\r\nHost: example.com\r\nTransfer-Encoding: chunked\r\n\r\n5\r\nhello\r\n'.bytes()
108 assert !has_complete_body(buffer.data, buffer.len)
109}
110
111fn test_has_complete_body_with_complete_chunked_body() {
112 buffer :=
113 'POST /upload HTTP/1.1\r\nHost: example.com\r\nTransfer-Encoding: chunked\r\n\r\n5\r\nhello\r\n0\r\n\r\n'.bytes()
114 assert has_complete_body(buffer.data, buffer.len)
115}
116
117fn test_has_complete_body_with_incomplete_chunk_data_containing_terminator_bytes() {
118 buffer :=
119 'POST /upload HTTP/1.1\r\nHost: example.com\r\nTransfer-Encoding: chunked\r\n\r\n20\r\nabc\r\n0\r\n\r\n'.bytes()
120 assert !has_complete_body(buffer.data, buffer.len)
121}
122
123fn test_has_complete_body_with_complete_chunk_data_containing_terminator_bytes() {
124 buffer :=
125 'POST /upload HTTP/1.1\r\nHost: example.com\r\nTransfer-Encoding: chunked\r\n\r\nd\r\nabc\r\n0\r\n\r\ndef\r\n0\r\n\r\n'.bytes()
126 assert has_complete_body(buffer.data, buffer.len)
127}
128