Mercurial > prosody-hg
comparison spec/net_http_parser_spec.lua @ 12889:94a99330ce87 0.12
net.http.parser: Fix off-by-one error in chunk parser
| author | Matthew Wild <mwild1@gmail.com> |
|---|---|
| date | Fri, 17 Feb 2023 17:01:19 +0000 |
| parents | 9ed628635dc6 |
| children | db30ffbf2090 |
comparison
equal
deleted
inserted
replaced
| 12887:68df46926c26 | 12889:94a99330ce87 |
|---|---|
| 6 local function CRLF(s) | 6 local function CRLF(s) |
| 7 return (s:gsub("\n", "\r\n")); | 7 return (s:gsub("\n", "\r\n")); |
| 8 end | 8 end |
| 9 | 9 |
| 10 local function test_stream(stream, expect) | 10 local function test_stream(stream, expect) |
| 11 local chunks_processed = 0; | |
| 11 local success_cb = spy.new(function (packet) | 12 local success_cb = spy.new(function (packet) |
| 12 assert.is_table(packet); | 13 assert.is_table(packet); |
| 13 if packet.body ~= false then | 14 if packet.body ~= false then |
| 14 assert.is_equal(expect.body, packet.body); | 15 assert.is_equal(expect.body, packet.body); |
| 15 end | 16 end |
| 17 if expect.chunks then | |
| 18 if chunks_processed == 0 then | |
| 19 assert.is_true(packet.partial); | |
| 20 packet.body_sink = { | |
| 21 write = function (_, data) | |
| 22 chunks_processed = chunks_processed + 1; | |
| 23 assert.equal(expect.chunks[chunks_processed], data); | |
| 24 return true; | |
| 25 end; | |
| 26 }; | |
| 27 end | |
| 28 end | |
| 16 end); | 29 end); |
| 17 | 30 |
| 18 local parser = http_parser.new(success_cb, error, stream:sub(1,4) == "HTTP" and "client" or "server") | 31 local function options_cb() |
| 19 for chunk in stream:gmatch("."..string.rep(".?", parser_input_bytes-1)) do | 32 return { |
| 20 parser:feed(chunk); | 33 -- Force streaming API mode |
| 34 body_size_limit = expect.chunks and 0 or nil; | |
| 35 buffer_size_limit = 10*1024*2; | |
| 36 }; | |
| 21 end | 37 end |
| 22 | 38 |
| 39 local parser = http_parser.new(success_cb, error, (stream[1] or stream):sub(1,4) == "HTTP" and "client" or "server", options_cb) | |
| 40 if type(stream) == "string" then | |
| 41 for chunk in stream:gmatch("."..string.rep(".?", parser_input_bytes-1)) do | |
| 42 parser:feed(chunk); | |
| 43 end | |
| 44 else | |
| 45 for _, chunk in ipairs(stream) do | |
| 46 parser:feed(chunk); | |
| 47 end | |
| 48 end | |
| 49 | |
| 50 if expect.chunks then | |
| 51 assert.equal(chunks_processed, #expect.chunks); | |
| 52 end | |
| 23 assert.spy(success_cb).was_called(expect.count or 1); | 53 assert.spy(success_cb).was_called(expect.count or 1); |
| 24 end | 54 end |
| 25 | 55 |
| 26 | 56 |
| 27 describe("net.http.parser", function() | 57 describe("net.http.parser", function() |
| 118 { | 148 { |
| 119 body = "Hello", count = 4; | 149 body = "Hello", count = 4; |
| 120 } | 150 } |
| 121 ); | 151 ); |
| 122 end); | 152 end); |
| 153 | |
| 154 it("should correctly find chunk boundaries", function () | |
| 155 test_stream({ | |
| 156 | |
| 157 CRLF[[ | |
| 158 HTTP/1.1 200 OK | |
| 159 Transfer-Encoding: chunked | |
| 160 | |
| 161 ]].."3\r\n:)\n\r\n"}, | |
| 162 { | |
| 163 count = 1; -- Once (partial) | |
| 164 chunks = { | |
| 165 ":)\n" | |
| 166 }; | |
| 167 } | |
| 168 ); | |
| 169 end); | |
| 123 end); | 170 end); |
| 124 | 171 |
| 125 it("should handle large chunked responses", function () | 172 it("should handle large chunked responses", function () |
| 126 local data = io.open("spec/inputs/http/httpstream-chunked-test.txt", "rb"):read("*a"); | 173 local data = io.open("spec/inputs/http/httpstream-chunked-test.txt", "rb"):read("*a"); |
| 127 | 174 |
