bug: api7-lua-resty-http包在解析带有Expect的响应时不符合RFC2616规范
LiuYawei2019 opened this issue · 0 comments
LiuYawei2019 commented
Issue description
apisix作为中间代理层,通过ext-plugin-post-resp扩展使用Java插件,代理转发客户端请求到上游服务。其中客户端发起HTTP请求头中包含Expect属性,后端服务在接收到Expect属性时,分别响应HTTP/1.1 100 Continue
回应支持,或者HTTP/1.1 417 Expectation Failed
。当Response包含了响应头信息(例如Server属性)后apisix会出现failed to request: couldn't parse HTTP version from response status line:
的错误,客户端收到502的请求响应。
就如上业务场景,参考RFC2616规范内容:
在RFC2616规范中
4.4 Message Length
内容如下:
1.Any response message which "MUST NOT" include a message-body (such
as the 1xx, 204, and 304 responses and any response to a HEAD
request) is always terminated by the first empty line after the
header fields, regardless of the entity-header fields present in
the message.
6 Response
内容如下:
After receiving and interpreting a request message, a server responds
with an HTTP response message.
Response = Status-Line ; Section 6.1
*(( general-header ; Section 4.5
| response-header ; Section 6.2
| entity-header ) CRLF) ; Section 7.1
CRLF
[ message-body ] ; Section 7.2
结论:在请求头包含Expect
时,响应码100允许返回general-header
和response-header
信息。
ext-plugin-post-resp 插件实现依赖http.lua代码如下:
local function _handle_continue(sock, body)
-- _receive_status 方法中会读取1行数据。即:HTTP/1.1 100 Continue
local status, version, reason, err = _receive_status(sock) --luacheck: no unused
if not status then
return nil, nil, err
end
-- Only send body if we receive a 100 Continue
if status == 100 then
-- 当响应包含Header信息时会被读取到,后续的解析就会因此出错
local ok, err = sock:receive("*l") -- Read carriage return
if not ok then
return nil, nil, err
end
_send_body(sock, body)
end
return status, version, err
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
end
-- Only send body if we receive a 100 Continue
if status == 100 then
-- 读取到空行后再做后续处理
repeat
local ok, err = sock:receive("*l") -- Read carriage return
if not ok then
return nil, nil, err
end
until (ok and #ok == 0)
_send_body(sock, body)
end
return status, version, err
end
Environment
- apisix V3.2
- apisix-java-plugin-runner
Minimal test code / Steps to reproduce the issue
- Postman 通过POST请求接口,Header头中增加Expect: 100-continue属性
- Tomcat 容器下返回
HTTP/1.1 100 Continue
- Undertow 容器下返回(Undertow官方在2.2.21.Final版本修改并去掉了Content-Length的属性)
HTTP/1.1 100 Continue
Content-Length: 0
What's the actual result? (including assertion message & call stack if applicable)
当出现类似Undertow带有Content-Length的属性响应时,apisix解析报头时会报错
What's the expected result?
正常处理并返回客户端200