Skip to content

Commit 04a9b0c

Browse files
committed
Refactor to leverage client-body-reader instead of implementing our own chunked reader
1 parent c1cae29 commit 04a9b0c

File tree

3 files changed

+37
-99
lines changed

3 files changed

+37
-99
lines changed

gateway/src/apicast/http_proxy.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ local round_robin = require 'resty.balancer.round_robin'
66
local http_proxy = require 'resty.http.proxy'
77
local file_reader = require("resty.file").file_reader
88
local chunked_reader = require('resty.http.chunked').chunked_reader
9-
local chunked_writer = require('resty.http.chunked').chunked_writer
9+
local write_response = require('resty.http.chunked').write_response
1010
local req_headers = ngx.req.get_headers
1111
local http_ver = ngx.req.http_version
1212
local ngx_send_headers = ngx.send_headers
@@ -189,7 +189,7 @@ local function forward_https_request(proxy_uri, uri, skip_https_connect)
189189
if res then
190190
-- if we are using raw socket we will need to send the response back with sock:send
191191
if sock then
192-
chunked_writer(sock, res ,chunksize)
192+
write_response(sock, res ,chunksize)
193193
else
194194
httpc:proxy_response(res)
195195
end

gateway/src/resty/http/chunked.lua

Lines changed: 34 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
local co_wrap_iter = require("resty.coroutines").co_wrap_iter
2-
local co_yield = coroutine._yield
1+
local httpc = require "resty.resolver.http"
32

43
local _M = {
54
}
65

76
local cr_lf = "\r\n"
8-
local default_max_chunk_size = 32 * 1024 -- 32K
97

108
local function send(socket, data)
119
if not data or data == '' then
@@ -21,100 +19,9 @@ local function print_err(error_code, ...)
2119
return ngx.exit(error_code)
2220
end
2321

24-
-- This is a copy of lua-resty-http _chunked_body_reader function but with
25-
-- extra bits to make chunked encoding work with raw socket
26-
-- https://github.com/ledgetech/lua-resty-http/blob/v0.16.1/lib/resty/http.lua#L418
27-
28-
-- chunked_reader return a body reader that translates the data read from sock
29-
-- out of HTTP "chunked" format before returning it
30-
--
31-
-- The chunked reader return nil when the final 0-length chunk is read
32-
function _M.chunked_reader(sock, max_chunk_size)
33-
max_chunk_size = max_chunk_size or default_max_chunk_size
34-
35-
if not sock then
36-
return nil, "chunked_reader: invalid sock"
37-
end
38-
39-
return co_wrap_iter(function()
40-
local eof = false
41-
local remaining = 0
42-
local size = 0
43-
repeat
44-
-- If we still have data on this chunk
45-
if max_chunk_size and remaining > 0 then
46-
if remaining > max_chunk_size then
47-
-- Consume up to max_chunk_size
48-
size = max_chunk_size
49-
remaining = remaining - max_chunk_size
50-
else
51-
-- Consume all remaining
52-
size = remaining
53-
remaining = 0
54-
end
55-
else
56-
-- read a line from socket
57-
-- chunk-size CRLF
58-
local line, err = sock:receive()
59-
if not line then
60-
co_yield(nil, "chunked_reader: failed to receive chunk size, err: " .. (err or "unknown"))
61-
end
62-
63-
size = tonumber(line, 16)
64-
if not size then
65-
co_yield(nil, "chunked_reader: unable to read chunksize")
66-
end
67-
68-
if max_chunk_size and size > max_chunk_size then
69-
-- Consume up to max_chunk_size
70-
remaining = size - max_chunk_size
71-
size = max_chunk_size
72-
end
73-
end
74-
75-
76-
if size > 0 then
77-
-- Receive the chunk
78-
local chunk, err = sock:receive(size)
79-
if not chunk then
80-
co_yield(nil, "chunked_reader: failed to receive chunk of size " .. size .. " err: " .. (err or "unknown"))
81-
end
82-
83-
if remaining == 0 then
84-
-- We're at the end of a chunk, read the next two bytes
85-
-- and verify they are "\r\n"
86-
local data, err = sock:receive(2)
87-
if not data then
88-
co_yield(nil, "chunked_reader: failed to receive chunk terminator, err: " .. (err or "unknown"))
89-
end
90-
end
91-
92-
chunk = string.format("%x\r\n", size) .. chunk .. cr_lf
93-
94-
co_yield(chunk)
95-
else
96-
-- we're at the end of a chunk, read the next two
97-
-- bytes to verify they are "\r\n".
98-
local chunk, err = sock:receive(2)
99-
if not chunk then
100-
co_yield(nil, "chunked_reader: failed to receive chunk terminator, err: " .. (err or "unknown"))
101-
end
102-
103-
if chunk ~= "\r\n" then
104-
co_yield(nil, "chunked_reader: bad chunk terminator")
105-
end
106-
107-
eof = true
108-
co_yield("0\r\n\r\n")
109-
break
110-
end
111-
until eof
112-
end)
113-
end
114-
115-
-- chunked_writer writes response body reader to sock in the HTTP/1.x server response format,
22+
-- write_response writes response body reader to sock in the HTTP/1.x server response format,
11623
-- including the status line, headers, body, and optional trailer.
117-
function _M.chunked_writer(sock, res, chunksize)
24+
function _M.write_response(sock, res, chunksize)
11825
local bytes, err
11926
chunksize = chunksize or 65536
12027

@@ -163,4 +70,35 @@ function _M.chunked_writer(sock, res, chunksize)
16370
end
16471
end
16572

73+
-- chunked_reader return a body reader that translates the data read from
74+
-- lua-resty-http client_body_reader to HTTP "chunked" format before returning it
75+
--
76+
-- The chunked reader return nil when the final 0-length chunk is read
77+
function _M.chunked_reader(sock, chunksize)
78+
chunksize = chunksize or 65536
79+
local eof = false
80+
local reader = httpc:get_client_body_reader(chunksize, sock)
81+
if not reader then
82+
return nil
83+
end
84+
85+
return function()
86+
if eof then
87+
return nil
88+
end
89+
90+
local buffer, err = reader()
91+
if err then
92+
return nil, err
93+
end
94+
if buffer then
95+
local chunk = string.format("%x\r\n", #buffer) .. buffer .. cr_lf
96+
return chunk
97+
else
98+
eof = true
99+
return "0\r\n\r\n"
100+
end
101+
end
102+
end
103+
166104
return _M

t/http-proxy.t

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ $ENV{'LARGE_BODY'} = large_body();
1515

1616
require("policies.pl");
1717

18-
repeat_each(1);
18+
repeat_each(3);
1919

2020
run_tests();
2121

0 commit comments

Comments
 (0)