Skip to content

Commit

Permalink
http/h1_stream: handle EOF when body_read_type==length
Browse files Browse the repository at this point in the history
If a client closes the connection before sending the expected number of bytes
then return `EPIPE`.
This fixes a potential infinite draining loop when trying to trying to
`:shutdown()` a stream.
  • Loading branch information
daurnimator committed Aug 26, 2023
1 parent f33b186 commit ddab283
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 0 deletions.
2 changes: 2 additions & 0 deletions http/h1_stream.lua
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,8 @@ function stream_methods:read_next_chunk(timeout)
if chunk ~= nil then
self.body_read_left = length_n - #chunk
end_stream = (self.body_read_left == 0)
elseif err == nil then
return nil, ce.strerror(ce.EPIPE), ce.EPIPE
end
elseif length_n == 0 then
chunk = ""
Expand Down
27 changes: 27 additions & 0 deletions spec/h1_stream_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,33 @@ describe("http1 stream", function()
server:close()
client:close()
end)
it("Doesn't hang when a content-length delimited stream is closed", function()
local server, client = new_pair(1.1)
local cq = cqueues.new()
cq:wrap(function()
local stream = client:new_stream()
local headers = new_headers()
headers:append(":method", "GET")
headers:append(":scheme", "http")
headers:append(":authority", "myauthority")
headers:append(":path", "/a")
assert(stream:write_headers(headers, true))
end)
cq:wrap(function()
local stream = server:get_next_incoming_stream()
assert(stream:get_headers())
local res_headers = new_headers()
res_headers:append(":status", "200")
res_headers:append("content-length", "100")
assert(stream:write_headers(res_headers, false))
assert(stream:write_chunk("foo", false))
assert(stream:shutdown())
end)
assert_loop(cq, TEST_TIMEOUT)
assert.truthy(cq:empty())
server:close()
client:close()
end)
it("allows pipelining", function()
local server, client = new_pair(1.1)
local cq = cqueues.new()
Expand Down

0 comments on commit ddab283

Please sign in to comment.