From 8d9df64fe56c77902ec34347684c82007aa34286 Mon Sep 17 00:00:00 2001 From: Abhishek Choudhary Date: Mon, 10 Aug 2026 16:54:35 +0545 Subject: [PATCH 1/2] fix: reframe request body forwarded upstream in serverless plugins The openfunction, aws-lambda and azure-functions plugins share generic-upstream.lua, which forwarded every inbound client header verbatim, including Transfer-Encoding, while supplying the request body already de-chunked by nginx. resty.http then kept Transfer-Encoding: chunked and wrote the unframed body raw, so the upstream request advertised chunked framing over a body that had none, letting the upstream misread the message length. Drop transfer-encoding and content-length before forwarding so the http client reframes the body with a correct Content-Length. Adds an end-to-end test that a chunked client body reaches the upstream reframed. --- .../plugins/serverless/generic-upstream.lua | 5 ++ t/plugin/aws-lambda.t | 72 +++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/apisix/plugins/serverless/generic-upstream.lua b/apisix/plugins/serverless/generic-upstream.lua index 52a0cb3ea346..c6eafb09c416 100644 --- a/apisix/plugins/serverless/generic-upstream.lua +++ b/apisix/plugins/serverless/generic-upstream.lua @@ -62,6 +62,11 @@ return function(plugin_name, version, priority, request_processor, authz_schema, local uri_args = core.request.get_uri_args(ctx) local headers = core.request.headers(ctx) or {} + -- body is already de-chunked by nginx; drop the client's framing headers + -- so the http client reframes it with a correct Content-Length + headers["transfer-encoding"] = nil + headers["content-length"] = nil + local req_body, err = core.request.get_body() if err then diff --git a/t/plugin/aws-lambda.t b/t/plugin/aws-lambda.t index 4a3ea8a6d531..b47cd8822fb9 100644 --- a/t/plugin/aws-lambda.t +++ b/t/plugin/aws-lambda.t @@ -510,3 +510,75 @@ end passed query: a=%2A&a-=x&flag=&multi=m1&multi=m2&with%20space=a%2Fb%20c signature: ok + + + +=== TEST 12: create route for chunked-body framing check +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "plugins": { + "aws-lambda": { + "function_uri": "http://localhost:8765/generic" + } + }, + "uri": "/aws" + }]] + ) + if code >= 300 then + ngx.status = code + ngx.say("fail") + return + end + ngx.say(body) + } + } +--- response_body +passed + + + +=== TEST 13: chunked client body is reframed with a correct Content-Length +--- inside_lua_block + ngx.req.read_body() + local te = ngx.req.get_headers()["transfer-encoding"] + ngx.say("te=", tostring(te)) + ngx.say("body=", ngx.req.get_body_data() or "") +--- config + location /t { + content_by_lua_block { + local sock = ngx.socket.tcp() + sock:settimeout(2000) + local ok, err = sock:connect("127.0.0.1", 1984) + if not ok then + ngx.say("connect failed: ", err) + return + end + local payload = "hello world" + local req = "POST /aws HTTP/1.1\r\n" + .. "Host: 127.0.0.1\r\n" + .. "Transfer-Encoding: chunked\r\n" + .. "Content-Type: text/plain\r\n" + .. "Connection: close\r\n\r\n" + .. string.format("%x\r\n%s\r\n0\r\n\r\n", #payload, payload) + local bytes, err = sock:send(req) + if not bytes then + ngx.say("send failed: ", err) + return + end + local data, err, partial = sock:receive("*a") + data = data or partial or "" + sock:close() + if data:find("te=nil", 1, true) and data:find("body=hello world", 1, true) then + ngx.say("PASS") + else + ngx.say("FAIL: ", data) + end + } + } +--- response_body +PASS From 773fb25eef16129db30b612f85ced34385625142 Mon Sep 17 00:00:00 2001 From: Abhishek Choudhary Date: Wed, 12 Aug 2026 10:58:25 +0545 Subject: [PATCH 2/2] test: reindex aws-lambda.t test numbering --- t/plugin/aws-lambda.t | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/t/plugin/aws-lambda.t b/t/plugin/aws-lambda.t index b47cd8822fb9..e79e43715c59 100644 --- a/t/plugin/aws-lambda.t +++ b/t/plugin/aws-lambda.t @@ -513,7 +513,7 @@ signature: ok -=== TEST 12: create route for chunked-body framing check +=== TEST 10: create route for chunked-body framing check --- config location /t { content_by_lua_block { @@ -542,7 +542,7 @@ passed -=== TEST 13: chunked client body is reframed with a correct Content-Length +=== TEST 11: chunked client body is reframed with a correct Content-Length --- inside_lua_block ngx.req.read_body() local te = ngx.req.get_headers()["transfer-encoding"]