【干货】将参数传递给 Apache APISIX 的五种方式

我最近读了 6 种将参数传递给 Spring REST API 的方法。虽然这个标题有点误导,因为它与REST无关,但它在列出向Spring应用程序发送参数的所有方法方面做得非常出色。我想为 Apache APISIX 做同样的事情;当您编写自定义插件时,这是有益的。

46ca6dff17cadf6c77e088067f938e19.png

常规设置

常规设置使用 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"
  1. 本地 httpbin 可实现更可靠的结果和更少的出站网络流量

  2. 静态配置文件

  3. 插件文件夹,每个插件一个文件

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
# ...
  1. 设置静态配置

  2. 将下面的每个 Lua 文件用作插件/opt/apisix/plugins

  3. 常规插件

  4. 自定义插件,每个备选方案一个

路径变量

路径变量是传递数据的一种简单方法。它们的主要问题是它们仅限于简单的值,例如 .朴素的方法是编写以下 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
  1. APISIX 将 URI 存储在ctx.var.uri

  2. 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: ~
  1. 存储和在上下文中,在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
  1. 作为常规 Lua 表访问正文

  2. 在多部分有效负载(例如文件上传)的情况下,表是必要的。在这里,我们假设有一个 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
  1. 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_
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晨曦_子画

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值