Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 43 additions & 1 deletion apisix/plugins/batch-requests.lua
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ local plugin = require("apisix.plugin")
local ngx = ngx
local ipairs = ipairs
local pairs = pairs
local type = type
local str_find = core.string.find
local str_lower = string.lower

Expand Down Expand Up @@ -224,6 +225,39 @@ local function set_common_query(data)
end


-- When the request is received on a unix domain socket, $server_port is an
-- empty string, so we fall back to the first TCP port in `apisix.node_listen`.
-- The value read from the local conf is not normalized by the CLI, so it can
-- be a plain port number, or an array of port numbers or `{ip, port}` tables.
local function get_loopback_port()
local server_port = ngx.var.server_port
if server_port and server_port ~= "" then
return server_port
end

local local_conf = core.config.local_conf()
local node_listen = core.table.try_read_attr(local_conf, "apisix", "node_listen")
if type(node_listen) == "number" then
return node_listen
end

if type(node_listen) == "table" then
for _, value in ipairs(node_listen) do
if type(value) == "number" then
return value
end

if type(value) == "table" then
-- the port defaults to 9080 if not set, see `apisix/cli/ops.lua`
return value.port or 9080
end
end
end

return nil
end


local function batch_requests(ctx)
local metadata = plugin.plugin_metadata(plugin_name)
core.log.info("metadata: ", core.json.delay_encode(metadata))
Expand Down Expand Up @@ -269,9 +303,17 @@ local function batch_requests(ctx)
}
end

local server_port = get_loopback_port()
if not server_port then
return 503, {
error_msg = "this APISIX instance doesn't listen on a TCP port, " ..
"but the batch-requests plugin needs one to loop back requests"
}
end

local httpc = http.new()
httpc:set_timeout(data.timeout)
local ok, err = httpc:connect("127.0.0.1", ngx.var.server_port)
local ok, err = httpc:connect("127.0.0.1", server_port)
if not ok then
return 500, {error_msg = "connect to apisix failed: " .. err}
end
Expand Down
75 changes: 75 additions & 0 deletions t/plugin/batch-requests.t
Original file line number Diff line number Diff line change
Expand Up @@ -1194,3 +1194,78 @@ qr/property \\"path\\" is required/
GET /t
--- response_body
passed



=== TEST 31: aggregate requests arriving via a unix domain socket
--- config
listen unix:$TEST_NGINX_HTML_DIR/apisix.sock;

location = /t {
content_by_lua_block {
local json = require("toolkit.json")
local http = require("resty.http")
local httpc = http.new()
local ok, err = httpc:connect("unix:$TEST_NGINX_HTML_DIR/apisix.sock")
if not ok then
ngx.say("failed to connect: ", err)
return
end

local res, err = httpc:request({
method = "POST",
path = "/apisix/batch-requests",
headers = {
["Host"] = "127.0.0.1",
["Content-Type"] = "application/json",
},
body = [=[{
"pipeline":[
{
"path": "/uds-b"
},{
"path": "/uds-c",
"method": "PUT"
}]
}]=],
})
if not res then
ngx.say("request failed: ", err)
return
end

local body, err = res:read_body()
if not body then
ngx.say("failed to read response body: ", err)
return
end

if res.status ~= 200 then
ngx.status = res.status
ngx.print(body)
return
end

local data = json.decode(body)
for _, resp in ipairs(data) do
ngx.say(resp.status, " ", resp.body)
end
}
}

location = /uds-b {
content_by_lua_block {
ngx.print("B")
}
}
location = /uds-c {
content_by_lua_block {
ngx.status = 201
ngx.print("C")
}
}
--- request
GET /t
--- response_body
200 B
201 C
Loading