feat[batch-request]: cp all header to every request (#1697)

This commit is contained in:
Vinci Xu 2020-06-16 18:09:02 +08:00 committed by GitHub
parent cd98a2bec8
commit 3010e04d47
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 76 additions and 30 deletions

View File

@ -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"
@ -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 = {}
req.headers = lowercase_key_or_init(req.headers)
end
end
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 ck then
req.headers["Cookie"] = ck
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
@ -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})

View File

@ -32,6 +32,10 @@
`batch-requests` 插件可以一次接受多个请求并以 [http pipeline](https://en.wikipedia.org/wiki/HTTP_pipelining) 的方式在网关发起多个http请求合并结果后再返回客户端这在客户端需要访问多个接口时可以显著地提升请求性能。
> **提示**
>
> 外层的 Http 请求头会自动设置到每一个独立请求中,如果独立请求中出现相同键值的请求头,那么只有独立请求的请求头会生效。
## 属性

View File

@ -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
@ -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:

View File

@ -40,7 +40,8 @@ __DATA__
},
"headers": {
"Base-Header": "base",
"Conflict-Header": "header_value"
"ConflictHeader": "header_value",
"OuterConflict": "common_value"
},
"pipeline":[
{
@ -48,7 +49,7 @@ __DATA__
"headers": {
"Header1": "hello",
"Header2": "world",
"Conflict-Header": "b-header-value"
"ConflictHeader": "b-header-value"
}
},{
"path": "/c",
@ -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"
}
},
{
@ -95,8 +97,11 @@ __DATA__
"X-Query-Conflict": "d_value"
}
}
]]=]
)
]]=],
{
ConflictHeader = "outer_header",
OuterConflict = "outer_confliect"
})
ngx.status = code
ngx.say(body)
@ -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")
}
@ -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 {
@ -697,7 +703,7 @@ passed
local code, body = t('/apisix/batch-requests',
ngx.HTTP_POST,
[=[{
"timeout": 100,
"timeout": 1000,
"pipeline":[
{
"path": "/b",
@ -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
@ -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