#1010566 lua-socket: socket.http ignores HTTP trailing headers

Package:
lua-socket
Source:
luasocket
Description:
TCP/UDP socket library for the Lua language
Submitter:
Ronald Lembcke
Date:
2022-05-04 13:45:03 UTC
Severity:
normal
Tags:
#1010566#5
Date:
2022-05-04 13:41:36 UTC
From:
To:
Dear maintainers,

Trailing HTTP headers (which are specified for Chunked Transfer Coding
in RFC7230, RFC7231) get ignored, despite the mechanism for handling
them is mostly implemented.

There is generally little support for these, but it's the only
reasonable way to pass performance/processing time information back from
the server with chunked encoding (header/trailer field Server-Timing),
without modifying the HTTP body itself.

The bug lies in the fact, that the value passed for the "headers"
parameter is missing/nil instead of a table. This later gets
default-initialized with a new table, which is not the table being
passed back:

socket.sourcet["http-chunked"] = function(sock, headers)
                                                ^^^^^^^
                                        called with nil

The patch below resolves this by checking passing on the "headers"
parameter in case of a Chunked Transfer:

$ diff -u /usr/share/lua/5.1/socket/http.lua_orig /usr/share/lua/5.1/socket/http.lua
--- /usr/share/lua/5.1/socket/http.lua_orig	2022-05-04 15:03:22.032195296 +0200
+++ /usr/share/lua/5.1/socket/http.lua	2022-05-04 15:08:16.775942030 +0200
@@ -164,12 +164,15 @@
 function metat.__index:receivebody(headers, sink, step)
     sink = sink or ltn12.sink.null()
     step = step or ltn12.pump.step
-    local length = base.tonumber(headers["content-length"])
     local t = headers["transfer-encoding"] -- shortcut
     local mode = "default" -- connection close
-    if t and t ~= "identity" then mode = "http-chunked"
-    elseif base.tonumber(headers["content-length"]) then mode = "by-length" end
-    return self.try(ltn12.pump.all(socket.source(mode, self.c, length),
+    local param
+    if t and t ~= "identity" then
+        mode, param = "http-chunked", headers
+    elseif base.tonumber(headers["content-length"]) then
+        mode, param = "by-length", base.tonumber(headers["content-length"])
+    end
+    return self.try(ltn12.pump.all(socket.source(mode, self.c, param),
         sink, step))
 end