v2 / vlib / net / http / response_test.v
147 lines · 131 sloc · 4.88 KB · fe02feffa68b9cce558cae5cf57b3e7b5af32689
Raw
1module http
2
3import compress.gzip
4import compress.zlib
5
6fn test_response_bytestr_1() {
7 resp := new_response(
8 status: .ok
9 body: 'Foo'
10 )
11 assert resp.bytestr() == 'HTTP/1.1 200 OK\r\n' + 'Content-Length: 3\r\n' + '\r\n' + 'Foo'
12}
13
14fn test_response_bytestr_2() {
15 resp := new_response(
16 status: .found
17 body: 'Foo'
18 header: new_header(key: .location, value: '/')
19 )
20 lines := resp.bytestr().split_into_lines()
21 assert lines[0] == 'HTTP/1.1 302 Found'
22 // header order is not guaranteed
23 check_headers(['Location: /', 'Content-Length: 3'], lines[1..3])!
24 assert lines[3] == ''
25 assert lines[4] == 'Foo'
26}
27
28// check_headers is a helper function for asserting all expected headers
29// are found because rendered header order is not guaranteed. The check
30// is O(n^2) which is fine for small lists.
31fn check_headers(expected []string, found []string) ! {
32 assert expected.len == found.len
33 for header in expected {
34 if !found.contains(header) {
35 return error('expected header "${header}" not in ${found}')
36 }
37 }
38}
39
40fn test_parse_response() {
41 content := 'HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nFoo'
42 x := parse_response(content)!
43 assert x.http_version == '1.1'
44 assert x.status_code == 200
45 assert x.status_msg == 'OK'
46 assert x.header.contains(.content_length)
47 assert x.header.get(.content_length)! == '3'
48 assert x.body == 'Foo'
49}
50
51fn test_parse_response_with_cookies() {
52 cookie_id := 'v_is_best'
53 content := 'HTTP/1.1 200 OK\r\nSet-Cookie: id=${cookie_id}\r\nContent-Length: 3\r\n\r\nFoo'
54 mut x := parse_response(content)!
55 assert x.http_version == '1.1'
56 assert x.status_code == 200
57 assert x.status_msg == 'OK'
58 assert x.header.contains(.content_length)
59 assert x.header.get(.content_length)! == '3'
60 assert x.body == 'Foo'
61 response_cookie := x.cookies()
62 assert response_cookie[0].str() == 'id=${cookie_id}'
63
64 // cookie has Base64 encoding info, ending with '=='
65 cookie_base64 := 'Ln0kBnAaAyYFQ8lH7d5J8Y5w1/iyDRpj6d0nBLTbBUMbtEyPD32rPvpApsvxhLJWlkHuHT3KYL0g/xNBxC9od5tMFAgurLxKdRd5lZ6Pd7W+SllkbsXmUA=='
66 content_cookie_base64 := 'HTTP/1.1 200 OK\r\nSet-Cookie: enctoken=${cookie_base64}; path=/; secure; SameSite=None\r\nContent-Length: 3\r\n\r\nFoo'
67 x = parse_response(content_cookie_base64)!
68 assert x.http_version == '1.1'
69 assert x.status_code == 200
70 assert x.status_msg == 'OK'
71 assert x.header.contains(.content_length)
72 assert x.header.get(.content_length)! == '3'
73 assert x.body == 'Foo'
74 response_cookie_base64 := x.cookies()
75 assert response_cookie_base64[0].str().split(';')[0] == 'enctoken=${cookie_base64}'
76}
77
78fn test_parse_response_with_weird_cookie() {
79 // weird cookies test
80 content_weird := 'HTTP/1.1 200 OK\r\nSet-Cookie: a=b; ; =; aa=; =bb; cc; ==\r\nContent-Length: 3\r\n\r\nFoo'
81 mut xx := parse_response(content_weird)!
82 weird_cookie := xx.cookies()
83 assert weird_cookie[0].str() == 'a=b'
84}
85
86fn test_parse_response_with_gzip_content_encoding() {
87 expected_body := '{"a": 1}'
88 compressed_body := gzip.compress(expected_body.bytes())!
89 content :=
90 'HTTP/1.1 200 OK\r\nContent-Encoding: gzip\r\nContent-Length: ${compressed_body.len}\r\n\r\n' +
91 compressed_body.bytestr()
92 resp := parse_response(content)!
93 assert resp.body == expected_body
94}
95
96fn test_parse_response_with_deflate_content_encoding() {
97 expected_body := '{"a": 1}'
98 compressed_body := zlib.compress(expected_body.bytes())!
99 content :=
100 'HTTP/1.1 200 OK\r\nContent-Encoding: deflate\r\nContent-Length: ${compressed_body.len}\r\n\r\n' +
101 compressed_body.bytestr()
102 resp := parse_response(content)!
103 assert resp.body == expected_body
104}
105
106fn test_parse_response_with_chunked_and_gzip_content_encoding() {
107 expected_body := '{"a": 1}'
108 compressed_body := gzip.compress(expected_body.bytes())!
109 chunked_body := '${compressed_body.len:x}\r\n' + compressed_body.bytestr() + '\r\n0\r\n\r\n'
110 content := 'HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\nContent-Encoding: gzip\r\n\r\n' +
111 chunked_body
112 resp := parse_response(content)!
113 assert resp.body == expected_body
114}
115
116fn test_vschannel_error_message_formats_non_wsa_errors() {
117 assert vschannel_error_message(-2146893052) == '0x80090304'
118 assert vschannel_error_message(42) == '42'
119}
120
121fn test_vschannel_error_message_formats_windows_wsa_errors() {
122 $if windows {
123 assert vschannel_error_message(11001) == '(11001) wsahost_not_found'
124 }
125}
126
127fn test_vschannel_request_error_normalizes_connect_failures() {
128 err := vschannel_request_error(vschannel_sec_e_internal_error)
129 assert err.msg() == vschannel_connect_failed_msg
130 assert err.code() == vschannel_sec_e_internal_error
131}
132
133fn test_vschannel_request_error_keeps_other_codes() {
134 err := vschannel_request_error(42)
135 assert err.msg() == 'http: vschannel request failed: 42'
136 assert err.code() == 42
137}
138
139fn test_vschannel_parse_response_normalizes_connect_failure_output() {
140 vschannel_parse_response('Error 10057 sending data to server (1)\nError performing handshake',
141 0) or {
142 assert err.msg() == vschannel_connect_failed_msg
143 assert err.code() == 0
144 return
145 }
146 assert false
147}
148