Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
LiuYawei2019 opened this issue Apr 11, 2024 · 0 comments

Comments

@LiuYawei2019
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant