常规设置
常规设置使用 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_uriradixtree_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: ~
存储和在上下文中,在noffsetctx.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_