-
Notifications
You must be signed in to change notification settings - Fork 170
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support to proxy request with Transfer-Encoding: chunked and proxy_bu…
…ffering: off
- Loading branch information
Showing
4 changed files
with
253 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
local httpc = require "resty.resolver.http" | ||
|
||
local _M = { | ||
} | ||
|
||
local cr_lf = "\r\n" | ||
|
||
-- chunked_reader return a body reader that translates the data read from | ||
-- lua-resty-http client_body_reader to HTTP "chunked" format before returning it | ||
-- | ||
-- The chunked reader return nil when the final 0-length chunk is read | ||
local function chunked_reader(sock, chunksize) | ||
chunksize = chunksize or 65536 | ||
local eof = false | ||
local reader = httpc:get_client_body_reader(chunksize, sock) | ||
if not reader then | ||
return nil | ||
end | ||
|
||
return function() | ||
if eof then | ||
return nil | ||
end | ||
|
||
local buffer, err = reader() | ||
if err then | ||
return nil, err | ||
end | ||
if buffer then | ||
local chunk = string.format("%x\r\n", #buffer) .. buffer .. cr_lf | ||
return chunk | ||
else | ||
eof = true | ||
return "0\r\n\r\n" | ||
end | ||
end | ||
end | ||
|
||
function _M.get_client_body_reader(sock, chunksize, is_chunked) | ||
if is_chunked then | ||
return chunked_reader(sock, chunksize) | ||
else | ||
return httpc:get_client_body_reader(chunksize, sock) | ||
end | ||
end | ||
|
||
return _M |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
local _M = { | ||
} | ||
|
||
local cr_lf = "\r\n" | ||
|
||
local function send(socket, data) | ||
if not data or data == '' then | ||
ngx.log(ngx.DEBUG, 'skipping sending nil') | ||
return | ||
end | ||
|
||
return socket:send(data) | ||
end | ||
|
||
-- write_response writes response body reader to sock in the HTTP/1.x server response format, | ||
-- including the status line, headers, body, and optional trailer. | ||
-- The connection is closed if send() fails or when returning a non-zero | ||
function _M.send_response(sock, res, chunksize) | ||
local bytes, err | ||
chunksize = chunksize or 65536 | ||
|
||
if ngx.headers_sent then | ||
return nil, "headers have already been sent" | ||
end | ||
|
||
if not sock then | ||
return nil, "socket not initialized yet" | ||
end | ||
|
||
-- Status line | ||
-- FIXME: should get protocol version from res? | ||
local status = "HTTP/1.1 " .. res.status .. " " .. res.reason .. cr_lf | ||
bytes, err = send(sock, status) | ||
if not bytes then | ||
return nil, "failed to send status line, err: " .. (err or "unknown") | ||
end | ||
|
||
-- Rest of header | ||
for k, v in pairs(res.headers) do | ||
local header = k .. ": " .. v .. cr_lf | ||
bytes, err = send(sock, header) | ||
if not bytes then | ||
return nil, "failed to send header, err: " .. (err or "unknown") | ||
end | ||
end | ||
|
||
-- End-of-header | ||
bytes, err = send(sock, cr_lf) | ||
if not bytes then | ||
return nil, "failed to send end of header, err: " .. (err or "unknown") | ||
end | ||
|
||
-- Write body | ||
if res.has_body then | ||
local reader = res.body_reader | ||
repeat | ||
local chunk, read_err | ||
|
||
chunk, read_err = reader(chunksize) | ||
if read_err then | ||
return nil, "failed to read response body, err: " .. (err or "unknown") | ||
end | ||
|
||
if chunk then | ||
bytes, err = send(sock, chunk) | ||
if not bytes then | ||
return nil, "failed to send response body, err: " .. (err or "unknown") | ||
end | ||
end | ||
until not chunk | ||
end | ||
end | ||
|
||
return _M |