function _M.go()

in t/lib/ext-plugin.lua [154:615]


function _M.go(case)
    local sock = ngx.req.socket(true)
    local ty, data = ext.receive(sock)
    if not ty then
        ngx.log(ngx.ERR, data)
        return
    end
    ngx.log(ngx.WARN, "receive rpc call successfully")

    if ty == constants.RPC_PREPARE_CONF then
        if case.inject_error then
            ty = constants.RPC_ERROR
            err_resp.Start(builder)
            err_resp.AddCode(builder, err_code.BAD_REQUEST)
            local req = prepare_conf_req.End(builder)
            builder:Finish(req)
            data = builder:Output()

        else
            local buf = flatbuffers.binaryArray.New(data)
            local pc = prepare_conf_req.GetRootAsReq(buf, 0)

            if case.with_conf then
                local conf = pc:Conf(1)
                assert(conf:Name(), "foo")
                assert(conf:Value(), "bar")
                local conf = pc:Conf(2)
                assert(conf:Name(), "cat")
                assert(conf:Value(), "dog")
            else
                assert(pc:ConfLength() == 0)
            end

            if case.expect_key_pattern then
                local m = ngx.re.find(pc:Key(), case.expect_key_pattern, "jo")
                assert(m ~= nil, pc:Key())
            else
                assert(pc:Key() ~= "")
            end

            prepare_conf_resp.Start(builder)
            prepare_conf_resp.AddConfToken(builder, 233)
            local req = prepare_conf_req.End(builder)
            builder:Finish(req)
            data = builder:Output()
        end

    elseif case.no_token then
        ty = constants.RPC_ERROR
        err_resp.Start(builder)
        err_resp.AddCode(builder, err_code.CONF_TOKEN_NOT_FOUND)
        local req = prepare_conf_req.End(builder)
        builder:Finish(req)
        data = builder:Output()

    elseif ty == constants.RPC_HTTP_REQ_CALL then
        local buf = flatbuffers.binaryArray.New(data)
        local call_req = http_req_call_req.GetRootAsReq(buf, 0)
        if case.check_input then
            assert(call_req:Id() == 0)
            assert(call_req:ConfToken() == 233)
            assert(call_req:SrcIpLength() == 4)
            assert(call_req:SrcIp(1) == 127)
            assert(call_req:SrcIp(2) == 0)
            assert(call_req:SrcIp(3) == 0)
            assert(call_req:SrcIp(4) == 1)
            assert(call_req:Method() == a6_method.PUT)
            assert(call_req:Path() == "/hello")

            assert(call_req:ArgsLength() == 4)
            local res = {}
            for i = 1, call_req:ArgsLength() do
                local entry = call_req:Args(i)
                local r = res[entry:Name()]
                if r then
                    res[entry:Name()] = {r, entry:Value()}
                else
                    res[entry:Name()] = entry:Value() or true
                end
            end
            assert(json.encode(res) == '{\"xx\":[\"y\",\"z\"],\"y\":\"\",\"z\":true}')

            assert(call_req:HeadersLength() == 5)
            local res = {}
            for i = 1, call_req:HeadersLength() do
                local entry = call_req:Headers(i)
                local r = res[entry:Name()]
                if r then
                    res[entry:Name()] = {r, entry:Value()}
                else
                    res[entry:Name()] = entry:Value() or true
                end
            end
            assert(json.encode(res) == '{\"connection\":\"close\",\"host\":\"localhost\",' ..
                   '\"x-req\":[\"foo\",\"bar\"],\"x-resp\":\"cat\"}')
        elseif case.check_input_ipv6 then
            assert(call_req:SrcIpLength() == 16)
            for i = 1, 15 do
                assert(call_req:SrcIp(i) == 0)
            end
            assert(call_req:SrcIp(16) == 1)
        elseif case.check_input_rewrite_host then
            for i = 1, call_req:HeadersLength() do
                local entry = call_req:Headers(i)
                if entry:Name() == "host" then
                    assert(entry:Value() == "test.com")
                end
            end
        elseif case.check_input_rewrite_path then
            assert(call_req:Path() == "/xxx")
        elseif case.check_input_rewrite_args then
            assert(call_req:Path() == "/xxx")
            assert(call_req:ArgsLength() == 1)
            local entry = call_req:Args(1)
            assert(entry:Name() == "x")
            assert(entry:Value() == "z")
        elseif case.get_request_body then
            assert(call_req:Method() == a6_method.POST)
        else
            assert(call_req:Method() == a6_method.GET)
        end

        if case.extra_info then
            ask_extra_info(sock, case.extra_info)
        end

        if case.stop == true then
            local len = 3
            http_req_call_stop.StartBodyVector(builder, len)
            builder:PrependByte(string.byte("t"))
            builder:PrependByte(string.byte("a"))
            builder:PrependByte(string.byte("c"))
            local b = builder:EndVector(len)

            local hdrs = {
                {"X-Resp", "foo"},
                {"X-Req", "bar"},
                {"X-Same", "one"},
                {"X-Same", "two"},
            }
            local len = #hdrs
            local textEntries = {}
            for i = 1, len do
                local name = builder:CreateString(hdrs[i][1])
                local value = builder:CreateString(hdrs[i][2])
                text_entry.Start(builder)
                text_entry.AddName(builder, name)
                text_entry.AddValue(builder, value)
                local c = text_entry.End(builder)
                textEntries[i] = c
            end
            http_req_call_stop.StartHeadersVector(builder, len)
            for i = len, 1, -1 do
                builder:PrependUOffsetTRelative(textEntries[i])
            end
            local vec = builder:EndVector(len)

            http_req_call_stop.Start(builder)
            if case.check_default_status ~= true then
                http_req_call_stop.AddStatus(builder, 405)
            end
            http_req_call_stop.AddBody(builder, b)
            http_req_call_stop.AddHeaders(builder, vec)
            local action = http_req_call_stop.End(builder)
            build_action(action, http_req_call_action.Stop)

        elseif case.rewrite == true or case.rewrite_host == true then
            local hdrs
            if case.rewrite_host then
                hdrs = {{"host", "127.0.0.1"}}
            else
                hdrs = {
                    {"X-Delete", nil},
                    {"X-Change", "bar"},
                    {"X-Add", "bar"},
                }
            end

            local len = #hdrs
            local textEntries = {}
            for i = 1, len do
                local name = builder:CreateString(hdrs[i][1])
                local value
                if hdrs[i][2] then
                    value = builder:CreateString(hdrs[i][2])
                end
                text_entry.Start(builder)
                text_entry.AddName(builder, name)
                if value then
                    text_entry.AddValue(builder, value)
                end
                local c = text_entry.End(builder)
                textEntries[i] = c
            end
            http_req_call_rewrite.StartHeadersVector(builder, len)
            for i = len, 1, -1 do
                builder:PrependUOffsetTRelative(textEntries[i])
            end
            local vec = builder:EndVector(len)

            local path = builder:CreateString("/uri")

            http_req_call_rewrite.Start(builder)
            http_req_call_rewrite.AddPath(builder, path)
            http_req_call_rewrite.AddHeaders(builder, vec)
            local action = http_req_call_rewrite.End(builder)
            build_action(action, http_req_call_action.Rewrite)

        elseif case.rewrite_args == true or case.rewrite_args_only == true then
            local path = builder:CreateString("/plugin_proxy_rewrite_args")

            local args = {
                {"a", "foo"},
                {"d", nil},
                {"c", "bar"},
                {"a", "bar"},
            }

            local len = #args
            local textEntries = {}
            for i = 1, len do
                local name = builder:CreateString(args[i][1])
                local value
                if args[i][2] then
                    value = builder:CreateString(args[i][2])
                end
                text_entry.Start(builder)
                text_entry.AddName(builder, name)
                if value then
                    text_entry.AddValue(builder, value)
                end
                local c = text_entry.End(builder)
                textEntries[i] = c
            end
            http_req_call_rewrite.StartHeadersVector(builder, len)
            for i = len, 1, -1 do
                builder:PrependUOffsetTRelative(textEntries[i])
            end
            local vec = builder:EndVector(len)

            http_req_call_rewrite.Start(builder)
            if not case.rewrite_args_only then
                http_req_call_rewrite.AddPath(builder, path)
            end
            http_req_call_rewrite.AddArgs(builder, vec)
            local action = http_req_call_rewrite.End(builder)
            build_action(action, http_req_call_action.Rewrite)

        elseif case.rewrite_bad_path == true then
            local path = builder:CreateString("/plugin_proxy_rewrite_args?a=2")
            http_req_call_rewrite.Start(builder)
            http_req_call_rewrite.AddPath(builder, path)
            local action = http_req_call_rewrite.End(builder)
            build_action(action, http_req_call_action.Rewrite)

        elseif case.rewrite_resp_header == true or case.rewrite_vital_resp_header == true then
            local hdrs = {
                {"X-Resp", "foo"},
                {"X-Req", "bar"},
                {"Content-Type", "application/json"},
                {"Content-Encoding", "deflate"},
            }
            local len = #hdrs
            local textEntries = {}
            for i = 1, len do
                local name = builder:CreateString(hdrs[i][1])
                local value = builder:CreateString(hdrs[i][2])
                text_entry.Start(builder)
                text_entry.AddName(builder, name)
                text_entry.AddValue(builder, value)
                local c = text_entry.End(builder)
                textEntries[i] = c
            end
            http_req_call_rewrite.StartRespHeadersVector(builder, len)
            for i = len, 1, -1 do
                builder:PrependUOffsetTRelative(textEntries[i])
            end
            local vec = builder:EndVector(len)

            local path = builder:CreateString("/plugin_proxy_rewrite_resp_header")

            http_req_call_rewrite.Start(builder)
            http_req_call_rewrite.AddRespHeaders(builder, vec)
            http_req_call_rewrite.AddPath(builder, path)
            local action = http_req_call_rewrite.End(builder)
            build_action(action, http_req_call_action.Rewrite)

        elseif case.rewrite_same_resp_header == true then
            local hdrs = {
                {"X-Resp", "foo"},
                {"X-Req", "bar"},
                {"X-Same", "one"},
                {"X-Same", "two"},
            }
            local len = #hdrs
            local textEntries = {}
            for i = 1, len do
                local name = builder:CreateString(hdrs[i][1])
                local value = builder:CreateString(hdrs[i][2])
                text_entry.Start(builder)
                text_entry.AddName(builder, name)
                text_entry.AddValue(builder, value)
                local c = text_entry.End(builder)
                textEntries[i] = c
            end
            http_req_call_rewrite.StartRespHeadersVector(builder, len)
            for i = len, 1, -1 do
                builder:PrependUOffsetTRelative(textEntries[i])
            end
            local vec = builder:EndVector(len)

            local path = builder:CreateString("/plugin_proxy_rewrite_resp_header")

            http_req_call_rewrite.Start(builder)
            http_req_call_rewrite.AddRespHeaders(builder, vec)
            http_req_call_rewrite.AddPath(builder, path)
            local action = http_req_call_rewrite.End(builder)
            build_action(action, http_req_call_action.Rewrite)

        elseif case.rewrite_request_body == true then
            local len = 4
            http_req_call_rewrite.StartBodyVector(builder, len)
            builder:PrependByte(string.byte("\n"))
            builder:PrependByte(string.byte("c"))
            builder:PrependByte(string.byte("b"))
            builder:PrependByte(string.byte("a"))
            local b = builder:EndVector(len)
            http_req_call_rewrite.Start(builder)
            http_req_call_rewrite.AddBody(builder, b)
            local action = http_req_call_rewrite.End(builder)
            build_action(action, http_req_call_action.Rewrite)

        else
            http_req_call_resp.Start(builder)
        end

        local req = http_req_call_resp.End(builder)
        builder:Finish(req)
        data = builder:Output()

    elseif ty == constants.RPC_HTTP_RESP_CALL  then
        local buf = flatbuffers.binaryArray.New(data)
        local call_req = http_resp_call_req.GetRootAsReq(buf, 0)
        if case.check_input then
            assert(call_req:Id() == 0)
            assert(call_req:ConfToken() == 233)
            assert(call_req:Status() == 200)
            local len = call_req:HeadersLength()

            local headers = {}
            for i = 1, len do
                local entry = call_req:Headers(i)
                local r = headers[entry:Name()]
                if r then
                    headers[entry:Name()] = {r, entry:Value()}
                else
                    headers[entry:Name()] = entry:Value() or true
                end
            end
            assert(json.encode(headers), '{"Connection":"close","Content-Length":"12",' ..
                                    '"Content-Type":"text/plain","Server":"openresty"}')
            http_resp_call_resp.Start(builder)

        elseif case.modify_body then
            local len = 3
            http_resp_call_resp.StartBodyVector(builder, len)
            builder:PrependByte(string.byte("t"))
            builder:PrependByte(string.byte("a"))
            builder:PrependByte(string.byte("c"))
            local b = builder:EndVector(len)


            http_resp_call_resp.Start(builder)
            http_resp_call_resp.AddBody(builder, b)

        elseif case.modify_header then
            local len = call_req:HeadersLength()

            local headers = {}
            for i = 1, len do
                local entry = call_req:Headers(i)
                local r = headers[entry:Name()]
                if r then
                    headers[entry:Name()] = {r, entry:Value()}
                else
                    headers[entry:Name()] = entry:Value() or true
                end
            end

            if case.same_header then
                headers["x-same"] = {"one", "two"}
            else
                local runner = headers["x-runner"]
                if runner and runner == "Go-runner" then
                    headers["x-runner"] = "Test-Runner"
                end

                headers["Content-Type"] = "application/json"
            end

            local i = 1
            local textEntries = {}
            for k, v in pairs(headers) do
                local name = builder:CreateString(k)
                if type(v) == "table" then
                    for j = 1, #v do
                        local value = builder:CreateString(v[j])
                        text_entry.Start(builder)
                        text_entry.AddName(builder, name)
                        text_entry.AddValue(builder, value)
                        local c = text_entry.End(builder)
                        textEntries[i] = c
                        i = i + 1
                    end
                else
                    local value = builder:CreateString(v)
                    text_entry.Start(builder)
                    text_entry.AddName(builder, name)
                    text_entry.AddValue(builder, value)
                    local c = text_entry.End(builder)
                    textEntries[i] = c
                    i = i + 1
                end
            end

            len = #textEntries
            http_resp_call_resp.StartHeadersVector(builder, len)
            for i = len, 1, -1 do
                builder:PrependUOffsetTRelative(textEntries[i])
            end
            local vec = builder:EndVector(len)

            http_resp_call_resp.Start(builder)
            http_resp_call_resp.AddHeaders(builder, vec)

        elseif case.modify_status then
            local status = call_req:Status()
            if status == 200 then
                status = 304
            end
            http_resp_call_resp.Start(builder)
            http_resp_call_resp.AddStatus(builder, status)

        elseif case.extra_info then
            ask_extra_info(sock, case.extra_info)
            http_resp_call_resp.Start(builder)
        else
            http_resp_call_resp.Start(builder)
        end

        local resp = http_resp_call_resp.End(builder)
        builder:Finish(resp)
        data = builder:Output()
    end

    local ok, err = ext.send(sock, ty, data)
    if not ok then
        ngx.log(ngx.ERR, err)
        return
    end
    ngx.log(ngx.WARN, "send rpc call response successfully")
end