我最近读了 6 种将参数传递给 Spring REST API 的方法。虽然这个标题有点误导,因为它与REST无关,但它在列出向Spring应用程序发送参数的所有方法方面做得非常出色。我想为 Apache APISIX 做同样的事情;当您编写自定义插件时,这是有益的。
常规设置
常规设置使用 Docker Compose 和静态配置。我每种方式都有一个插件来传递参数。
YAML公司
services:
httpbin:
image: kennethreitz/httpbin #1
apisix:
image: apache/apisix:3.9.0-debian
volumes:
- ./apisix/conf/config.yml:/usr/local/apisix/conf/config.yaml:ro
- ./apisix/conf/apisix.yml:/usr/local/apisix/conf/apisix.yaml:ro #2
- ./apisix/plugins:/opt/apisix/plugins:ro #3
ports:
- "9080:9080"
本地 httpbin 可实现更可靠的结果和更少的出站网络流量
静态配置文件
插件文件夹,每个插件一个文件
YAML公司
deployment:
role: data_plane
role_data_plane:
config_provider: yaml #1
apisix:
extra_lua_path: /opt/?.lua #2
plugins:
- proxy-rewrite #3
- path-variables #4
# ...
设置静态配置
将下面的每个 Lua 文件用作插件
/opt/apisix/plugins
常规插件
自定义插件,每个备选方案一个
路径变量
路径变量是传递数据的一种简单方法。它们的主要问题是它们仅限于简单的值,例如 .朴素的方法是编写以下 Lua 代码:/links/{n}/{offset}
卢阿
local core = require("apisix.core")
function _M.access(_, ctx)
local captures, _ = ngx.re.match(ctx.var.uri, '/path/(.*)/(.*)') --1-2
for k, v in pairs(captures) do
core.log.warn('Order-Value pair: ', k, '=', v)
end
end
APISIX 将 URI 存储在
ctx.var.uri
Nginx 提供正则表达式 API
让我们试试:
壳
curl localhost:9080/path/15/3
日志显示:
纯文本
Order-Value pair: 0=/path/15/3
Order-Value pair: 1=15
Order-Value pair: 2=3
不过,我没有管理错误。或者,我们可以依靠 Apache APISIX 的功能:一个特定的路由器。默认路由器 使用主机和 URI 来匹配请求。 让我们去掉主机部分,但也匹配参数。radixtree_host_uri
radixtree_uri_with_parameter
YAML公司
apisix:
extra_lua_path: /opt/?.lua
router:
http: radixtree_uri_with_parameter
我们需要更新路由:
YAML公司
routes:
- path-variables
- uri: /path/:n/:offset #1
upstream_id: 1
plugins:
path-variables: ~
存储和在上下文中,在
n
offset
ctx.curr_req_matched
我们保留插件只是为了记录路径变量:
卢阿
function _M.access(_, ctx)
core.log.warn('n: ', ctx.curr_req_matched.n, ', offset: ', ctx.curr_req_matched.offset)
end
结果与预期相同,请求与上述相同:
纯文本
n: 15, offset: 3
查询参数
查询参数是传递数据的另一种常规方式。与路径变量一样,您只能传递简单的值,例如 .Lua 代码不需要正则表达式:/?foo=bar
卢阿
local core = require("apisix.core")
function _M.access(_, _)
local args, _ = ngx.req.get_uri_args()
for k, v in pairs(args) do
core.log.warn('Order-Value pair: ', k, '=', v)
end
end
让我们试试:
壳
curl localhost:9080/query\?foo=one\&bar=three
日志显示:
纯文本
Key-Value pair: bar=three
Key-Value pair: foo=one
请记住,查询参数没有顺序。
但是,我们的代码包含一个问题。accept 参数。请记住,客户端可以多次传递具有不同值的查询参数,例如?第一个参数是单个查询参数返回的最大值数。为了避免忽略值,我们应该将其设置为 0,即无界。ngx.req.get_uri_args()
?foo=one&foo=two
由于每个插件设计者都必须记住它,我们可以将结果添加到链中其他插件的上下文中。更新后的代码如下所示:
卢阿
local core = require("apisix.core")
function _M.get_uri_args(ctx)
if not ctx then
ctx = ngx.ctx.api_ctx
end
if not ctx.req_uri_args then
local args, _ = ngx.req.get_uri_args(0)
ctx.req_uri_args = args
end
return ctx.req_uri_args
end
function _M.access(_, ctx)
for k, v in pairs(ctx.req_uri_args) do
core.log.warn('Key-Value pair: ', k, '=', v)
end
end
请求标头
请求标头是传递参数的另一种方式。虽然它们通常只包含简单值,但您也可以使用它们来发送结构化值,例如 JSON。根据您的需求,APISIX 可以列出所有请求头或特定请求头。在这里,我得到了所有这些:
卢阿
local core = require("apisix.core")
function _M.access(_, _)
local headers = core.request.headers()
for k, v in pairs(headers) do
core.log.warn('Key-Value pair: ', k, '=', v)
end
end
我们用一个简单的请求来测试:
壳
curl -H 'foo: 1' -H 'bar: two' localhost:9080/headers
我们得到的比我们预期的要多,因为 curl 添加了默认标头:
纯文本
Key-Value pair: user-agent=curl/8.4.0
Key-Value pair: bar=two
Key-Value pair: foo=1
Key-Value pair: host=localhost:9080
Key-Value pair: accept=*/*
请求正文
设置请求正文是发送结构化数据(例如 JSON)的常用方法。Nginx 提供了一个简单的 API 来收集此类数据。
卢阿
local core = require("apisix.core")
function _M.access(_, _)
local args = core.request.get_post_args() --1
local body = next(args, nil) --2
core.log.warn('Body: ', body)
end
作为常规 Lua 表访问正文
在多部分有效负载(例如文件上传)的情况下,表是必要的。在这里,我们假设有一个 arg,即内容正文。
是时候测试了:
壳
curl localhost:9080/body -X POST -d '{ "foo": 1, "bar": { "baz": "two" } }'
结果如预期所示:
JSON的
Body: { "foo": 1, "bar": { "baz": "two" } }
饼干
最后但并非最不重要的一点是,我们可以通过cookie发送参数。与以前的替代方案的不同之处在于,cookie 保留在客户端,浏览器会随每个请求一起发送它们。在 Lua 方面,我们需要知道 cookie 名称,而不是列出所有查询参数或标头。
卢阿
local core = require("apisix.core")
function _M.access(_, ctx)
local foo = ctx.var.cookie_foo --1
core.log.warn('Cookie value: ', foo)
end
Cookie 已命名,不区分大小写
foo
让我们测试一下:
壳
curl --cookie "foo=Bar" localhost:9080/cookies
结果是正确的:
纯文本
Cookie value: Bar
总结
在这篇文章中,我们列举了五种在服务器端传递参数的替代方案,并解释了如何在 Apache APISIX 上访问它们。以下是 API 摘要:
另类 | 源 | 应用程序接口 |
---|---|---|
路径变量 | APISIX 路由器 | 使用路由器radixtree_uri_with_parameter |
查询参数 | Nginx的 | ngx.req.get_uri_args(0) |
请求标头 | APISIX 核心库 | core.request.headers() |
请求正文 | APISIX 核心库 | core.request.get_post_args() |
饼干 | 方法上下文参数 | ctx.var.cookie_ |