apache / apache/apisix-java-plugin-runner

bug: api7-lua-resty-http包在解析带有Expect的响应时不符合RFC2616规范

未关闭
#306 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看
主要语言
Java
星标
152
派生
102
PR 合并指标
30 天内没有已合并 PR

描述

### 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

1. Postman 通过POST请求接口,Header头中增加Expect: 100-continue属性
2. Tomcat 容器下返回```HTTP/1.1 100 Continue ```
3. 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

贡献指南

这个仓库没有索引到贡献指南

评估

这个 Issue 还没有评估数据。

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。