Skip to content

Commit 4eec757

Browse files
authored
veb: fix gzip middleware decode/encode (fix #20865) (fix #25753) (#25754)
1 parent 76b752c commit 4eec757

File tree

3 files changed

+44
-7
lines changed

3 files changed

+44
-7
lines changed

vlib/veb/context.v

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,7 @@ mut:
3131
done bool
3232
// if true the response should not be sent and the connection should be closed
3333
// manually.
34-
takeover bool
35-
// how the http response should be handled by veb's backend
36-
return_type ContextReturnType = .normal
34+
takeover bool
3735
return_file string
3836
// If the `Connection: close` header is present the connection should always be closed
3937
client_wants_to_close bool
@@ -43,6 +41,8 @@ pub:
4341
// You can use it to determine how much time is spent on your request.
4442
page_gen_start i64
4543
pub mut:
44+
// how the http response should be handled by veb's backend
45+
return_type ContextReturnType = .normal
4646
req http.Request
4747
custom_mime_types map[string]string
4848
// TCP connection to client. Only for advanced usage!

vlib/veb/middleware.v

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,15 +159,16 @@ pub fn encode_gzip[T]() MiddlewareOptions[T] {
159159
pub fn decode_gzip[T]() MiddlewareOptions[T] {
160160
return MiddlewareOptions[T]{
161161
handler: fn [T](mut ctx T) bool {
162-
if encoding := ctx.res.header.get(.content_encoding) {
162+
if encoding := ctx.req.header.get(.content_encoding) {
163163
if encoding == 'gzip' {
164-
decompressed := gzip.decompress(ctx.req.body.bytes()) or {
164+
decompressed := gzip.decompress(ctx.req.data.bytes()) or {
165165
ctx.request_error('invalid gzip encoding')
166166
return false
167167
}
168-
ctx.req.body = decompressed.bytestr()
168+
ctx.req.data = decompressed.bytestr()
169169
}
170170
}
171+
return true
171172
}
172173
}
173174
}

vlib/veb/tests/middleware_test.v

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import veb
22
import net.http
33
import os
44
import time
5+
import compress.gzip
56

67
const port = 13001
78

@@ -48,6 +49,16 @@ pub fn (app &App) after(mut ctx Context) veb.Result {
4849
return ctx.text('from after, ${ctx.counter}')
4950
}
5051

52+
@['/gzip']
53+
pub fn (app &App) gzip_test(mut ctx Context) veb.Result {
54+
return ctx.text('gzip response, ${ctx.counter}')
55+
}
56+
57+
@['/decode_gzip'; post]
58+
pub fn (app &App) decode_gzip_test(mut ctx Context) veb.Result {
59+
return ctx.text('received: ${ctx.req.data}')
60+
}
61+
5162
pub fn (app &App) app_middleware(mut ctx Context) bool {
5263
ctx.counter++
5364
return true
@@ -87,6 +98,10 @@ fn testsuite_begin() {
8798

8899
app.Middleware.route_use('/after', handler: after_middleware, after: true)
89100

101+
// Gzip middleware tests
102+
app.Middleware.use(veb.decode_gzip[Context]())
103+
app.Middleware.route_use('/gzip', veb.encode_gzip[Context]())
104+
90105
spawn veb.run_at[App, Context](mut app, port: port, timeout_in_seconds: 2, family: .ip)
91106
// app startup time
92107
_ := <-app.started
@@ -126,4 +141,25 @@ fn test_after_middleware() {
126141
assert custom_header == '3'
127142
}
128143

129-
// TODO: add test for encode and decode gzip
144+
// Verifies that encode_gzip compresses responses
145+
fn test_encode_gzip_middleware() {
146+
x := http.get('${localserver}/gzip')!
147+
148+
encoding := x.header.get(.content_encoding) or { '' }
149+
assert encoding == 'gzip', 'Expected gzip encoding, got: ${encoding}'
150+
151+
decompressed := gzip.decompress(x.body.bytes())!
152+
assert decompressed.bytestr() == 'gzip response, 2'
153+
}
154+
155+
// Verifies that decode_gzip middleware decompresses request bodies
156+
fn test_decode_gzip_middleware() {
157+
original_text := 'Hello from gzip compressed body!'
158+
compressed := gzip.compress(original_text.bytes())!
159+
160+
mut req := http.new_request(.post, '${localserver}/decode_gzip', compressed.bytestr())
161+
req.header.add(.content_encoding, 'gzip')
162+
x := req.do()!
163+
164+
assert x.body == 'received: ${original_text}'
165+
}

0 commit comments

Comments
 (0)