Skip to content

Commit

Permalink
feat[batch-request]: cp all header to every request (apache#1697)
Browse files Browse the repository at this point in the history
  • Loading branch information
ShiningRush authored and SaberMaster committed Jun 30, 2020
1 parent 51ec5e0 commit 93b9692
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 29 deletions.
57 changes: 41 additions & 16 deletions apisix/plugins/batch-requests.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
local core = require("apisix.core")
local http = require("resty.http")
local ngx = ngx
local io_open = io.open
local ipairs = ipairs
local pairs = pairs
local core = require("apisix.core")
local http = require("resty.http")
local ngx = ngx
local io_open = io.open
local ipairs = ipairs
local pairs = pairs
local str_find = string.find
local str_lower = string.lower


local plugin_name = "batch-requests"

Expand Down Expand Up @@ -112,22 +115,42 @@ local function check_input(data)
end
end

local function lowercase_key_or_init(obj)
if not obj then
return {}
end

local function set_common_header(data)
local ck = core.request.header(nil, "Cookie")
local lowercase_key_obj = {}
for k, v in pairs(obj) do
lowercase_key_obj[str_lower(k)] = v
end

return lowercase_key_obj
end

local function ensure_header_lowercase(data)
data.headers = lowercase_key_or_init(data.headers)

for i,req in ipairs(data.pipeline) do
if not req.headers then
req.headers = {}
end
req.headers = lowercase_key_or_init(req.headers)
end
end

if ck then
req.headers["Cookie"] = ck

local function set_common_header(data)
local outer_headers = core.request.headers(nil)
for i,req in ipairs(data.pipeline) do
for k, v in pairs(data.headers) do
if not req.headers[k] then
req.headers[k] = v
end
end

if data.headers then
for k, v in pairs(data.headers) do
if not req.headers[k] then
if outer_headers then
for k, v in pairs(outer_headers) do
local is_content_header = str_find(k, "content-", 1, true) == 1
-- skip header start with "content-"
if not req.headers[k] and not is_content_header then
req.headers[k] = v
end
end
Expand Down Expand Up @@ -202,8 +225,10 @@ local function batch_requests()
core.response.exit(500, {error_msg = "connect to apisix failed: " .. err})
end

ensure_header_lowercase(data)
set_common_header(data)
set_common_query(data)

local responses, err = httpc:request_pipeline(data.pipeline)
if not responses then
core.response.exit(400, {error_msg = "request failed: " .. err})
Expand Down
4 changes: 4 additions & 0 deletions doc/plugins/batch-requests-cn.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@

`batch-requests` 插件可以一次接受多个请求并以 [http pipeline](https://en.wikipedia.org/wiki/HTTP_pipelining) 的方式在网关发起多个http请求,合并结果后再返回客户端,这在客户端需要访问多个接口时可以显著地提升请求性能。

> **提示**
>
> 外层的 Http 请求头会自动设置到每一个独立请求中,如果独立请求中出现相同键值的请求头,那么只有独立请求的请求头会生效。
## 属性

Expand Down
6 changes: 5 additions & 1 deletion doc/plugins/batch-requests.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@

`batch-requests` can accept mutiple request and send them from `apisix` via [http pipeline](https://en.wikipedia.org/wiki/HTTP_pipelining),and return a aggregated response to client,this can significantly improve performance when the client needs to access multiple APIs.

> **Tips**
>
> The HTTP headers for the outer batch request, except for the Content- headers such as Content-Type, apply to every request in the batch. If you specify a given HTTP header in both the outer request and an individual call, then the individual call header's value overrides the outer batch request header's value. The headers for an individual call apply only to that call.
## Attributes

None
Expand All @@ -41,7 +45,7 @@ None
Default enbaled

## Batch Api Request/Response
The plugin will create a api in `apisix` to handle your aggregation request.
The plugin will create a api in `apisix` to handle your batch request.

### Batch Api Request:

Expand Down
37 changes: 25 additions & 12 deletions t/plugin/batch-requests.t
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,16 @@ __DATA__
},
"headers": {
"Base-Header": "base",
"Conflict-Header": "header_value"
"ConflictHeader": "header_value",
"OuterConflict": "common_value"
},
"pipeline":[
{
"path": "/b",
"headers": {
"Header1": "hello",
"Header2": "world",
"Conflict-Header": "b-header-value"
"ConflictHeader": "b-header-value"
}
},{
"path": "/c",
Expand All @@ -71,7 +72,8 @@ __DATA__
"X-Res": "B",
"X-Header1": "hello",
"X-Header2": "world",
"X-Conflict-Header": "b-header-value"
"X-Conflict-Header": "b-header-value",
"X-OuterConflict": "common_value"
}
},
{
Expand All @@ -95,8 +97,11 @@ __DATA__
"X-Query-Conflict": "d_value"
}
}
]]=]
)
]]=],
{
ConflictHeader = "outer_header",
OuterConflict = "outer_confliect"
})
ngx.status = code
ngx.say(body)
Expand All @@ -110,7 +115,8 @@ __DATA__
ngx.header["Base-Query"] = ngx.var.arg_base
ngx.header["X-Header1"] = ngx.req.get_headers()["Header1"]
ngx.header["X-Header2"] = ngx.req.get_headers()["Header2"]
ngx.header["X-Conflict-Header"] = ngx.req.get_headers()["Conflict-Header"]
ngx.header["X-Conflict-Header"] = ngx.req.get_headers()["ConflictHeader"]
ngx.header["X-OuterConflict"] = ngx.req.get_headers()["OuterConflict"]
ngx.header["X-Res"] = "B"
ngx.print("B")
}
Expand Down Expand Up @@ -687,7 +693,7 @@ passed



=== TEST 15: copy cookie to every request
=== TEST 15: copy all header to every request except Contenct-
--- config
client_body_in_file_only on;
location = /aggregate {
Expand All @@ -697,7 +703,7 @@ passed
local code, body = t('/apisix/batch-requests',
ngx.HTTP_POST,
[=[{
"timeout": 100,
"timeout": 1000,
"pipeline":[
{
"path": "/b",
Expand All @@ -716,24 +722,28 @@ passed
{
"status": 200,
"headers": {
"X-Cookie": "request-cookies-b"
"X-Cookie": "request-cookies-b",
"X-HeaderB": "request-header-b"
}
},
{
"status": 201,
"headers": {
"X-Cookie": "request-cookies-c"
"X-Cookie": "request-cookies-c",
"X-HeaderC": "request-header-c"
}
},
{
"status": 202,
"headers": {
"X-Cookie": "request-cookies-d"
"X-Cookie": "request-cookies-d",
"X-HeaderD": "request-header-d"
}
}
]]=],
{
Cookie = "request-cookies"
Cookie = "request-cookies",
OuterHeader = "request-header"
})
ngx.status = code
Expand All @@ -745,18 +755,21 @@ passed
content_by_lua_block {
ngx.status = 200
ngx.header["X-Cookie"] = ngx.req.get_headers()["Cookie"] .. "-b"
ngx.header["X-HeaderB"] = ngx.req.get_headers()["OuterHeader"] .. "-b"
}
}
location = /c {
content_by_lua_block {
ngx.status = 201
ngx.header["X-Cookie"] = ngx.req.get_headers()["Cookie"] .. "-c"
ngx.header["X-HeaderC"] = ngx.req.get_headers()["OuterHeader"] .. "-c"
}
}
location = /d {
content_by_lua_block {
ngx.status = 202
ngx.header["X-Cookie"] = ngx.req.get_headers()["Cookie"] .. "-d"
ngx.header["X-HeaderD"] = ngx.req.get_headers()["OuterHeader"] .. "-d"
}
}
--- request
Expand Down

0 comments on commit 93b9692

Please sign in to comment.