跳到主要内容

路由选项

在 APISIX 中,有三个 HTTP 路由选项:

  1. radixtree_host_uri 按主机和 URI 路径路由请求,在匹配期间优先考虑主机名而不是 URI 路径。这是默认设置,行为与 NGINX 相同。

  2. radixtree_uri 按主机和 URI 路径路由请求,在匹配期间优先考虑 URI 路径而不是主机名。

  3. radixtree_uri_with_parameter 支持在路径匹配中使用参数。

这些路由选项可以在 conf/config.yaml 中的 apisix.router.http 下配置。

radixtree_host_uri

这是默认的路由设置,在路由匹配时优先考虑主机名而不是 URI 路径。如果你想显式配置该选项,请将以下块添加到你的配置文件中:

config.yaml
apisix:
router:
http: radixtree_host_uri

重新加载 APISIX 以使更改生效。

配置两个具有相同 URI 但匹配主机不同的路由对于多租户 SaaS 平台等场景很有用,其中每个租户都通过自定义子域提供服务。例如,两个租户都可以访问相同的端点,但根据主机将请求路由到不同的上游服务。

为此,你可以配置两个具有相同匹配 URI 但匹配主机和上游服务不同的路由:

curl -i "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "httpbin-host-test1",
"uri": "/get",
"host": "test1.com",
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
curl -i "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "postman-host-test2",
"uri": "/get",
"host": "test2.com",
"upstream": {
"type": "roundrobin",
"nodes": {
"postman-echo.com:80": 1
}
}
}'

发送匹配第一个路由主机的请求:

curl "http://127.0.0.1:9080/get" -H 'host: test1.com'

你应该看到来自 httpbin.org 的响应:

{
"args": {},
"headers": {
"Accept": "*/*",
"Host": "test1.com",
"User-Agent": "curl/8.6.0",
"X-Amzn-Trace-Id": "Root=1-6746c0bf-653fac896be8818275f1e8da",
"X-Forwarded-Host": "test1.com"
},
"origin": "192.168.65.1, 43.252.208.90",
"url": "http://test1.com/get"
}

发送匹配第二个路由主机的请求:

curl "http://127.0.0.1:9080/get" -H 'host: test2.com'

你应该看到来自 postman-echo.com 的响应:

{
"args": {},
"headers": {
"host": "test2.com",
"x-request-start": "t=1732834286",
"connection": "close",
"x-forwarded-proto": "http",
"x-forwarded-port": "80",
"x-amzn-trace-id": "Root=1-6746c0ca-2b0b323902e784f512051ef6",
"x-forwarded-host": "test2.com",
"user-agent": "curl/8.6.0",
"accept": "*/*"
},
"url": "http://test2.com/get"
}

为了进一步了解该行为,创建第三个匹配所有请求的路由:

curl -i "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "mock-api7-all",
"uri": "/*",
"upstream": {
"type": "roundrobin",
"nodes": {
"mock.api7.ai:443": 1
},
"scheme": "https",
"pass_host": "node"
}
}'

发送带有随机主机名的请求:

curl "http://127.0.0.1:9080/get" -H 'host: random.com'

你应该看到请求被转发到第三个路由:

API7.ai, the creator of Apache APISIX, delivers a cloud-native API Gateway solution for the Enterprise, to help you maximize the value of APIs.

发送另一个匹配第一个路由主机的请求:

curl "http://127.0.0.1:9080/get" -H 'host: test1.com'

你应该看到请求被转发到 httpbin.org 上游。这演示了当路由器设置为 radixtree_host_uri 时,如何在路由中优先考虑主机名。

radixtree_uri

radixtree_uri 在路由匹配时优先考虑 URI 路径而不是主机名。要使用 radixtree_uri 作为 HTTP 路由器设置,请将以下块添加到你的配置文件中:

config.yaml
apisix:
router:
http: radixtree_uri

重新加载 APISIX 以使更改生效。

为了了解该行为,创建一个匹配 test1.com 主机和所有 URI 路径的路由:

curl -i "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "httpbin-host-test1",
"uri": "/*",
"host": "test1.com",
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'

创建另一个匹配 /get 请求的路由:

curl -i "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "mock-api7-all",
"uri": "/get",
"upstream": {
"type": "roundrobin",
"nodes": {
"mock.api7.ai:443": 1
},
"scheme": "https",
"pass_host": "node"
}
}'

使用 test1.com 主机向 /get 发送请求:

curl "http://127.0.0.1:9080/get" -H 'host: test1.com'

你应该看到请求被转发到 mock.api7.ai

API7.ai, the creator of Apache APISIX, delivers a cloud-native API Gateway solution for the Enterprise, to help you maximize the value of APIs.

这表明当路由器以 radixtree_uri 模式运行时,主机名未被优先考虑,全路径匹配具有 优先级

使用 test1.com 主机向 /anything 发送另一个请求:

curl "http://127.0.0.1:9080/anything" -H 'host: test1.com'

你应该看到请求被转发到 httpbin.org 上游。

radixtree_uri_with_parameter

radixtree_uri_with_parameter 支持在路由匹配时使用参数。要使用 radixtree_uri_with_parameter 作为 HTTP 路由器设置,请将以下块添加到你的配置文件中:

config.yaml
apisix:
router:
http: radixtree_uri_with_parameter

重新加载 APISIX 以使更改生效。

一个常见的用例是提取 URI 路径的一部分并使用它来构建发送到上游服务的请求。这可用于重写 URL 路径或设置自定义标头,从而实现基于客户端输入的灵活动态路由和请求自定义。可以使用 uri_param_<parameter_name> 轻松提取匹配的 URI 路径。

例如,你可以匹配像 /user/123/profile 这样的 URI 路径,提取用户 ID 123,并将该值转发到新标头中的上游服务。

为此,请创建如下路由:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "httpbin",
// Annotate 1
"uri": "/anything/user/:user_id/profile",
"plugins":{
"proxy-rewrite": {
"headers": {
"set": {
// Annotate 2
"X-User-ID": "$uri_param_user_id"
}
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'

❶ 匹配请求 /anything/user/:user_id/profile,其中 user_id 是一个参数。

❷ 将 user_id 参数值分配给新标头 X-User-ID

要进行验证,请向路由发送请求:

curl "http://127.0.0.1:9080/anything/user/123/profile"

你应该看到以下响应:

{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Host": "127.0.0.1",
"User-Agent": "curl/8.6.0",
"X-Amzn-Trace-Id": "Root=1-68873cf5-7248f64d19d607ea50aa9735",
"X-Forwarded-Host": "127.0.0.1",
"X-User-Id": "123"
},
...
}

路由参数还可以接受 URL 编码的字符串。例如,如果你发送如下请求:

curl -i "http://127.0.0.1:9080/anything/user/123%20456/profile"

用户 ID 将被提取为 123 456

{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Host": "127.0.0.1",
"User-Agent": "curl/8.6.0",
"X-Amzn-Trace-Id": "Root=1-68873d37-7634825b20d05dee3a852cb9",
"X-Forwarded-Host": "127.0.0.1",
"X-User-Id": "123 456"
},
...
}

了解路由匹配

APISIX 利用 luaradixtree 库进行路由,这是一个在 Lua 中为 OpenResty 实现的自适应基数树。它利用外部函数接口 (FFI) 与 rax 集成,确保高效和高性能的路由。

有几种路由匹配方式。

全路径

假设路由 URI 为:

/anything/foo

该路由将仅匹配对 /anything/foo 的请求。

通配符

假设路由 URI 为:

/anything/*

该路由将匹配对 /anything 的子路径的任何请求,例如 /anything/foo/anything/bar。请注意,它将不匹配对 /anything 的请求。

通配符不需要在 URI 的末尾。你还可以有如下路由 URI:

/*/*/test

这将匹配类似 /anything/foo/test 的 URI 请求。

匹配优先级

全路径匹配的优先级高于通配符匹配。假设你有两个路由,URI 分别为 /anything/foo/anything/*。对 /anything/foo 的请求将由 /anything/foo 路由匹配,而不是 /anything/* 路由。