Skip to main content

Version: 3.11.0

Router Options

In APISIX, there are three HTTP router options:

  1. radixtree_host_uri routes requests by hosts and URI paths, prioritizing hostnames over URI paths during matching. This is the default setting and the behaviour is the same as NGINX.

  2. radixtree_uri routes requests by hosts and URI paths, prioritizing URI paths over hostnames during matching.

  3. radixtree_uri_with_parameter supports the use of parameters in path matching.

These router options can be configured in conf/config.yaml under apisix.router.http.

radixtree_host_uri

This is the default router setting, which prioritizes hostnames over URI paths when route matching. If you would like to explicitly configure the option, add the following block to your configuration file:

config.yaml
apisix:
router:
http: radixtree_host_uri

Reload APISIX for changes to take effect.

Configuring two routes with the same URI but different matching hosts is useful for scenarios like multi-tenant SaaS platforms, where each tenant is served through a custom subdomain. For example, both tenants may access the same endpoint, but the requests are routed to different upstream services based on the host.

To do so, you can configure two routes with the same matching URI but different matching hosts and upstream services:

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
}
}
}'

Send a request that matches the host of the first route:

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

You should see a response from 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"
}

Send a request that matches the host of the second route:

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

You should see a response from 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"
}

To understand the behaviour more, create a third route that matches all requests:

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"
}
}'

Send a request with a random host name:

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

You should see the request is forwarded to the third route:

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.

Send another request that matches the host of the first route:

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

You should see the request is forwarded to the httpbin.org upstream. This demonstrates how the router prioritizes hostnames in routing when it is set to radixtree_host_uri.

radixtree_uri

radixtree_uri prioritizes URI paths over hostnames when route matching. To use radixtree_uri as the HTTP router setting, add the following block to your configuration file:

config.yaml
apisix:
router:
http: radixtree_uri

Reload APISIX for changes to take effect.

To understand the behaviour, create a route that matches test1.com host and all URI paths:

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
}
}
}'

Create another route that matches requests to /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"
}
}'

Send a request to /get with test1.com host:

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

You should see the request is forwarded to 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.

This shows the hostname is not being prioritized when router operates in radixtree_uri mode and full path matching takes the priority.

Send another request to /anything with test1.com host:

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

You should see the request is forwarded to the httpbin.org upstream.

radixtree_uri_with_parameter

radixtree_uri_with_parameter supports the use of parameters when route matching. To use radixtree_uri_with_parameter as the HTTP router setting, add the following block to your configuration file:

config.yaml
apisix:
router:
http: radixtree_uri_with_parameter

Reload APISIX for changes to take effect.

A common use case is to extract a part of the URI path and use it to compose the request sent to upstream services. This provides flexibility in dynamic routing and customization based on client requests. For example, a URI path like /user/123/profile could be matched, and the user ID 123 extracted and forwarded as in a new header to the upstream service.

To do so, create a route as such:

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": {
"serverless-pre-function": {
"phase": "rewrite",
"functions": [
"return function(conf, ctx)
local core = require \"apisix.core\"
local user_id = ctx.curr_req_matched.user_id
if user_id then
core.request.set_header(ctx, \"user-id\", user_id)
end
end"
]
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'

❶ Match requests to /anything/user/:user_id/profile where user_id is a parameter.

❷ Customize the serverless function to extract the user_id value from the requested path and attach the value to a new header User-Id.

To verify, send a request to the route:

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

You should see the following response:

{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Host": "127.0.0.1",
"User-Agent": "curl/8.6.0",
"User-Id": "123",
"X-Amzn-Trace-Id": "Root=1-6746b92d-509ab0186bd075c462ab0ac8",
"X-Forwarded-Host": "127.0.0.1"
},
...
}

The route parameter can also accept URL-encoded string. For instance, if you send a request as such:

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

The user ID would be extracted as 123 456.

Understand Route Matching

APISIX leverages the luaradixtree library for routing, an adaptive radix tree implemented in Lua for OpenResty. It utilizes the Foreign Function Interface (FFI) to integrate with rax, ensuring efficient and high-performance routing.

There are several ways of route matching.

Full Path

Suppose the route URI is:

/anything/foo

The route will only match request to /anything/foo.

Wildcard

Suppose the route URI is:

/anything/*

The route will match any request to sub-paths of /anything, such as /anything/foo and /anything/bar. Note that it will not match requests to /anything.

The wildcard does not need to be at the end of the URI. You can also have a route URI as such:

/*/*/test

This will match requests with URIs like /anything/foo/test.

Matching Priority

Full path matching has a higher priority than wildcard matching. Suppose you have two routes with URI /anything/foo and /anything/* respectively. The request to /anything/foo will be matched by the /anything/foo route, instead of the /anything/* route.


API7.ai Logo

API Management for Modern Architectures with Edge, API Gateway, Kubernetes, and Service Mesh.

Product

API7 Cloud

SOC2 Type IIISO 27001HIPAAGDPRRed Herring

Copyright © APISEVEN PTE. LTD 2019 – 2025. Apache, Apache APISIX, APISIX, and associated open source project names are trademarks of the

Apache Software Foundation