-
Notifications
You must be signed in to change notification settings - Fork 170
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[THREESCALE-9542] Part 2: Add support to proxy request with Transfer-Encoding: chunked #1403
Merged
tkan145
merged 8 commits into
3scale:master
from
tkan145:THREESCALE-9542-chunked-request
Jan 22, 2024
Merged
Changes from 5 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
3efa69a
Fix 'Transfer-Encoding: chunked' issue when sending request via proxy
tkan145 b02a888
Support chunked requests when talking to proxy servers with request b…
tkan145 e3f6db5
Fixed response body not being sent
tkan145 f5af618
Handle "Expect:100-continue" header only when raw socket is used
tkan145 5e05612
Update CHANGELOG.md file
tkan145 2bfc227
Wrapping block I/O call in a coroutine
tkan145 f19b9e5
Update request_unbuffered policy README.md file
tkan145 b494ca8
Address PR comments
tkan145 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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,73 @@ | ||
local httpc = require "resty.resolver.http" | ||
local ngx_req = ngx.req | ||
|
||
local _M = { | ||
} | ||
|
||
local cr_lf = "\r\n" | ||
|
||
local function test_expect(sock) | ||
local expect = ngx_req.get_headers()["Expect"] | ||
|
||
if expect == "" or ngx_req.http_version == 1.0 then | ||
return true | ||
end | ||
|
||
if expect and expect:lower() == "100-continue" then | ||
local _, err = sock:send("HTTP/1.1 100 Continue\r\n\r\n") | ||
if err then | ||
ngx.log(ngx.ERR, "failed to handle expect header, err: ", err) | ||
return false, err | ||
end | ||
end | ||
return true | ||
end | ||
|
||
-- 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) | ||
eguzki marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if not reader then | ||
return nil | ||
end | ||
|
||
-- If Expect: 100-continue is sent upstream, lua-resty-http will only call | ||
-- _send_body after receiving "100 Continue". So it's safe to process the | ||
-- Expect header and send "100 Continue" downstream here. | ||
local ok, err = test_expect(sock) | ||
if not ok then | ||
return nil, err | ||
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 |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this safe to do for ALL requests which meet these conditions? I see that the calls in the
file_size
function are I/O blocking calls so I am wondering how harmful to performance those could be given they are not executed within a coroutine. If a coroutine cannot be used then we should consider using the lua-io-nginx module for example.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it enough to wrap that functionality with a coroutine? I don't know how useful that would be since it would yield on the first call anyway. Also the file_reader also call
io.open
all every request that has body buffered to file, so I guess we pay the price of callingio.open
one more time?But I totally agree with you that it is a I/O blocking function and should be avoided.
Checking the module
lua-io-nginx
I can see that this module is currently considered experimental. And it seems like it runs the task on another thread. However, I'm not so sure about this because we have to pay for context switching, threads, locking, etc.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No sure how expensive is
Theoretically any IO operation could block the thread. We could try coroutines or any other mean to make it non blocking. Reading lua-nginx-module introduction it says:
Not sure if we can follow that recommendation, though. @tkan145 we can try to discuss about this in a short call..
Anyway, AFAIK, we have never measured the capacity of APICast to handle traffic with request body big enough to be persisted in disk. All the tests performed where "simple" GET requests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed and also updated README file. @kevprice83 can you help review the README file and let me know if I need to add anything else?