Skip to content

Commit 10b11df

Browse files
committed
got symbols instead response body (fixes #14746)
1 parent cb9feb6 commit 10b11df

2 files changed

Lines changed: 86 additions & 1 deletion

File tree

vlib/net/http/response.v

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
// that can be found in the LICENSE file.
44
module http
55

6+
import compress.gzip
7+
import compress.zlib
68
import net.http.chunked
79
import strconv
810

@@ -40,9 +42,10 @@ pub fn parse_response(resp string) !Response {
4042
start_idx, end_idx := find_headers_range(resp)!
4143
header := parse_headers(resp.substr(start_idx, end_idx))!
4244
mut body := resp.substr(end_idx, resp.len)
43-
if header.get(.transfer_encoding) or { '' } == 'chunked' {
45+
if has_header_token(header.get(.transfer_encoding) or { '' }, 'chunked') {
4446
body = chunked.decode(body)!
4547
}
48+
body = decode_response_body(body, header.get(.content_encoding) or { '' })
4649
return Response{
4750
http_version: version
4851
status_code: status_code
@@ -52,6 +55,55 @@ pub fn parse_response(resp string) !Response {
5255
}
5356
}
5457

58+
fn has_header_token(header_value string, expected_token string) bool {
59+
for token in parse_header_tokens(header_value) {
60+
if token == expected_token.to_lower() {
61+
return true
62+
}
63+
}
64+
return false
65+
}
66+
67+
fn parse_header_tokens(header_value string) []string {
68+
mut tokens := []string{}
69+
for part in header_value.split(',') {
70+
token := part.all_before(';').trim_space().to_lower()
71+
if token != '' {
72+
tokens << token
73+
}
74+
}
75+
return tokens
76+
}
77+
78+
fn decode_response_body(body string, content_encoding string) string {
79+
if body.len == 0 {
80+
return body
81+
}
82+
encodings := parse_header_tokens(content_encoding)
83+
if encodings.len == 0 {
84+
return body
85+
}
86+
mut decoded := body.bytes()
87+
for i := encodings.len - 1; i >= 0; i-- {
88+
encoding := encodings[i]
89+
decoded = match encoding {
90+
'gzip', 'x-gzip' {
91+
gzip.decompress(decoded) or { return body }
92+
}
93+
'deflate' {
94+
zlib.decompress(decoded) or { return body }
95+
}
96+
'identity' {
97+
decoded
98+
}
99+
else {
100+
return body
101+
}
102+
}
103+
}
104+
return decoded.bytestr()
105+
}
106+
55107
// parse_status_line parses the first HTTP response line into the HTTP
56108
// version, status code, and reason phrase
57109
fn parse_status_line(line string) !(string, int, string) {

vlib/net/http/response_test.v

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
module http
22

3+
import compress.gzip
4+
import compress.zlib
5+
36
fn test_response_bytestr_1() {
47
resp := new_response(
58
status: .ok
@@ -79,3 +82,33 @@ fn test_parse_response_with_weird_cookie() {
7982
weird_cookie := xx.cookies()
8083
assert weird_cookie[0].str() == 'a=b'
8184
}
85+
86+
fn 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+
96+
fn 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+
106+
fn 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+
}

0 commit comments

Comments
 (0)