From 999d13d7477fed375d9751ba798ae5b7e5d6a797 Mon Sep 17 00:00:00 2001 From: Zhefeng Chen Date: Thu, 9 Mar 2023 15:21:58 +0800 Subject: [PATCH 1/3] fix 100 response with headers --- lib/resty/http.lua | 19 ++++-- t/03-requestbody.t | 156 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 164 insertions(+), 11 deletions(-) diff --git a/lib/resty/http.lua b/lib/resty/http.lua index 70c3bee9..ac6309ff 100644 --- a/lib/resty/http.lua +++ b/lib/resty/http.lua @@ -635,18 +635,23 @@ end local function _handle_continue(sock, body) local status, version, reason, err = _receive_status(sock) --luacheck: no unused if not status then - return nil, nil, err + return nil, nil, nil, err end -- Only send body if we receive a 100 Continue if status == 100 then - local ok, err = sock:receive("*l") -- Read carriage return + -- Read headers + local headers, err = _receive_headers(sock) + if not headers then + return nil, nil, nil, err + end + + local ok, err, partial = _send_body(sock, body) if not ok then - return nil, nil, err + return nil, nil, nil, err end - _send_body(sock, body) end - return status, version, err + return status, version, reason, err end @@ -764,11 +769,11 @@ function _M.read_response(self, params) -- If we expect: continue, we need to handle this, sending the body if allowed. -- If we don't get 100 back, then status is the actual status. if params.headers["Expect"] == "100-continue" then - local _status, _version, _err = _handle_continue(sock, params.body) + local _status, _version, _reason, _err = _handle_continue(sock, params.body) if not _status then return nil, _err elseif _status ~= 100 then - status, version, err = _status, _version, _err -- luacheck: no unused + status, version, reason, err = _status, _version, _reason, _err -- luacheck: no unused end end diff --git a/t/03-requestbody.t b/t/03-requestbody.t index c1fdd241..86fbf358 100644 --- a/t/03-requestbody.t +++ b/t/03-requestbody.t @@ -164,6 +164,7 @@ c: 3 [error] [warn] + === TEST 4: Return non-100 status to user --- http_config eval: $::HttpConfig --- config @@ -205,7 +206,154 @@ Expectation Failed [warn] -=== TEST 5: Non string request bodies are converted with correct length +=== TEST 5: Return 100 Continue with headers +--- http_config eval: $::HttpConfig +--- config + location = /a { + content_by_lua_block { + local http = require "resty.http" + local httpc = http.new() + httpc:connect({ + scheme = "http", + host = "127.0.0.1", + port = ngx.var.server_port + }) + + local res, err = httpc:request{ + body = "a=1&b=2&c=3", + path = "/b", + headers = { + ["Expect"] = "100-continue", + ["Content-Type"] = "application/x-www-form-urlencoded", + } + } + + if not res then + ngx.log(ngx.ERR, "httpc:request failed: ", err) + end + + ngx.say(res.status) + ngx.say(res:read_body()) + httpc:close() + } + } + location = /b { + content_by_lua_block { + local len = ngx.req.get_headers()["Content-Length"] + + local sock, err = ngx.req.socket(true) + if not sock then + ngx.log(ngx.ERR, "server: failed to get raw req socket: ", err) + return + end + + -- with additional header + ngx.log(ngx.NOTICE, "before send 100") + local ok, err = sock:send("HTTP/1.1 100 Continue\r\nConnection: keep-alive\r\n\r\n") + if not ok then + ngx.log(ngx.ERR, "failed to send 100 response: ", err) + end + + local data, err = sock:receive(len) + if not data then + ngx.log(ngx.ERR, "failed to receive: ", err) + return + end + + local ok, err = sock:send("HTTP/1.1 200 OK\r\n" .. + "Content-Length: " .. len .. "\r\n" .. + "Content-Type: application/x-www-form-urlencoded\r\n\r\n" .. + data) + if not ok then + ngx.log(ngx.ERR, "failed to send 200 response: ", err) + return + end + } + } +--- request +GET /a +--- response_body +200 +a=1&b=2&c=3 +--- no_error_log +[error] +[warn] + + +=== TEST 6: Return 100 Continue without headers +--- http_config eval: $::HttpConfig +--- config + location = /a { + content_by_lua_block { + local http = require "resty.http" + local httpc = http.new() + httpc:connect({ + scheme = "http", + host = "127.0.0.1", + port = ngx.var.server_port + }) + + local res, err = httpc:request{ + body = "a=1&b=2&c=3", + path = "/b", + headers = { + ["Expect"] = "100-continue", + ["Content-Type"] = "application/x-www-form-urlencoded", + } + } + + if not res then + ngx.log(ngx.ERR, "httpc:request failed: ", err) + end + + ngx.say(res.status) + ngx.say(res:read_body()) + httpc:close() + } + } + location = /b { + content_by_lua_block { + local len = ngx.req.get_headers()["Content-Length"] + + local sock, err = ngx.req.socket(true) + if not sock then + ngx.log(ngx.ERR, "server: failed to get raw req socket: ", err) + return + end + + -- without additional headers + local ok, err = sock:send("HTTP/1.1 100 Continue\r\n\r\n") + if not ok then + ngx.log(ngx.ERR, "failed to send 100 response: ", err) + end + + local data, err = sock:receive(len) + if not data then + ngx.log(ngx.ERR, "failed to receive: ", err) + return + end + + local ok, err = sock:send("HTTP/1.1 200 OK\r\n" .. + "Content-Length: " .. len .. "\r\n" .. + "Content-Type: application/x-www-form-urlencoded\r\n\r\n" .. + data) + if not ok then + ngx.log(ngx.ERR, "failed to send 200 response: ", err) + return + end + } + } +--- request +GET /a +--- response_body +200 +a=1&b=2&c=3 +--- no_error_log +[error] +[warn] + + +=== TEST 7: Non string request bodies are converted with correct length --- http_config eval: $::HttpConfig --- config location = /a { @@ -247,7 +395,7 @@ mix123edtable [warn] -=== TEST 6: Request body as iterator +=== TEST 8: Request body as iterator --- http_config eval: $::HttpConfig --- config location = /a { @@ -284,7 +432,7 @@ foobar [warn] -=== TEST 7: Request body as iterator, errors with missing length +=== TEST 9: Request body as iterator, errors with missing length --- http_config eval: $::HttpConfig --- config location = /a { @@ -319,7 +467,7 @@ Request body is a function but a length or chunked encoding is not specified [warn] -=== TEST 8: Request body as iterator with chunked encoding +=== TEST 10: Request body as iterator with chunked encoding --- http_config eval: $::HttpConfig --- config location = /a { From 584ac852b029fda630a221f8ffe20dc338df07db Mon Sep 17 00:00:00 2001 From: Zhefeng Chen Date: Thu, 9 Mar 2023 15:43:06 +0800 Subject: [PATCH 2/3] update --- t/03-requestbody.t | 2 -- 1 file changed, 2 deletions(-) diff --git a/t/03-requestbody.t b/t/03-requestbody.t index 86fbf358..50b876ba 100644 --- a/t/03-requestbody.t +++ b/t/03-requestbody.t @@ -164,7 +164,6 @@ c: 3 [error] [warn] - === TEST 4: Return non-100 status to user --- http_config eval: $::HttpConfig --- config @@ -248,7 +247,6 @@ Expectation Failed end -- with additional header - ngx.log(ngx.NOTICE, "before send 100") local ok, err = sock:send("HTTP/1.1 100 Continue\r\nConnection: keep-alive\r\n\r\n") if not ok then ngx.log(ngx.ERR, "failed to send 100 response: ", err) From 46355447f7103cfe35a86282dbfcd6bb59ff32c8 Mon Sep 17 00:00:00 2001 From: Zhefeng Chen Date: Thu, 9 Mar 2023 19:12:01 +0800 Subject: [PATCH 3/3] remove unused variable --- lib/resty/http.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/resty/http.lua b/lib/resty/http.lua index ac6309ff..e97c456b 100644 --- a/lib/resty/http.lua +++ b/lib/resty/http.lua @@ -646,7 +646,7 @@ local function _handle_continue(sock, body) return nil, nil, nil, err end - local ok, err, partial = _send_body(sock, body) + local ok, err = _send_body(sock, body) if not ok then return nil, nil, nil, err end