路由选项
在 APISIX 中,有三个 HTTP 路由选项:
-
radixtree_host_uri按主机和 URI 路径路由请求,在匹配期间优先考虑主机名而不是 URI 路径。这是默认设置,行为与 NGINX 相同。 -
radixtree_uri按主机和 URI 路径路由请求,在匹配期间优先考虑 URI 路径而不是主机名。 -
radixtree_uri_with_parameter支持在路径匹配中使用参数。
这些路由选项可以在 conf/config.yaml 中的 apisix.router.http 下配置。
radixtree_host_uri
这是默认的路由设置,在路由匹配时优先考虑主机名而不是 URI 路径。如果你想显式配置该选项,请将以下块添加到你的配置文件中:
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 路由器设置,请将以下块添加到你的配置文件中:
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 路由器设置,请将以下块添加到你的配置文件中:
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",
"uri": "/anything/user/:user_id/profile",
"plugins":{
"proxy-rewrite": {
"headers": {
"set": {
"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/* 路由。