2021-02-26 21:40:08 +08:00
---
2021-03-01 12:00:06 +08:00
title: Router radixtree
2021-02-26 21:40:08 +08:00
---
2019-10-31 09:27:28 +08:00
<!--
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
-->
2019-08-20 22:07:59 +08:00
### what's libradixtree?
2021-01-06 11:06:43 +08:00
2019-08-20 22:07:59 +08:00
[libradixtree ](https://github.com/iresty/lua-resty-radixtree ), adaptive radix trees implemented in Lua for OpenResty.
2019-09-03 21:30:46 +08:00
APISIX using libradixtree as route dispatching library.
2019-08-20 22:07:59 +08:00
### How to use libradixtree in APISIX?
This is Lua-Openresty implementation library base on FFI for [rax ](https://github.com/antirez/rax ).
Let's take a look at a few examples and have an intuitive understanding.
#### 1. Full match
```
/blog/foo
```
It will only match `/blog/foo` .
#### 2. Prefix matching
```
/blog/bar*
```
It will match the path with the prefix `/blog/bar` , eg: `/blog/bar/a` ,
`/blog/bar/b` , `/blog/bar/c/d/e` , `/blog/bar` etc.
#### 3. Match priority
Full match -> Deep prefix matching.
Here are the rules:
```
/blog/foo/*
/blog/foo/a/*
/blog/foo/c/*
/blog/foo/bar
```
| path | Match result |
|------|--------------|
|/blog/foo/bar | `/blog/foo/bar` |
|/blog/foo/a/b/c | `/blog/foo/a/*` |
|/blog/foo/c/d | `/blog/foo/c/*` |
|/blog/foo/gloo | `/blog/foo/*` |
|/blog/bar | not match |
2019-09-03 21:30:46 +08:00
2021-04-08 09:02:57 +08:00
#### 4. Different routes have the same `uri`
When different routes have the same `uri` , you can set the priority field of the route to determine which route to match first, or add other matching rules to distinguish different routes.
Note: In the matching rules, the `priority` field takes precedence over other rules except `uri` .
1. Different routes have the same `uri` and set the `priority` field
Create two routes with different `priority` values (the larger the value, the higher the priority).
```shell
$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"priority": 3,
"uri": "/hello"
}'
```
```shell
$ curl http://127.0.0.1:9080/apisix/admin/routes/2 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"upstream": {
"nodes": {
"127.0.0.1:1981": 1
},
"type": "roundrobin"
},
"priority": 2,
"uri": "/hello"
}'
```
Test:
```shell
curl http://127.0.0.1:1980/hello
1980
```
All requests only hit the route of port `1980` .
2. Different routes have the same `uri` and set different matching conditions
Here is an example of setting host matching rules:
```shell
$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"hosts": ["localhost.com"],
"uri": "/hello"
}'
```
```shell
$ curl http://127.0.0.1:9080/apisix/admin/routes/2 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"upstream": {
"nodes": {
"127.0.0.1:1981": 1
},
"type": "roundrobin"
},
"hosts": ["test.com"],
"uri": "/hello"
}'
```
Test:
```shell
$ curl http://127.0.0.1:9080/hello -H 'host: localhost.com'
1980
```
```shell
$ curl http://127.0.0.1:9080/hello -H 'host: test.com'
1981
```
```shell
$ curl http://127.0.0.1:9080/hello
{"error_msg":"404 Route Not Found"}
```
The `host` rule matches, the request hits the corresponding upstream, and the `host` does not match, the request returns a 404 message.
#### 5. Parameter match
2020-12-30 22:13:05 +08:00
When `radixtree_uri_with_parameter` is used, we can match routes with parameters.
For example, with configuration:
2021-01-03 11:26:40 +08:00
2020-12-30 22:13:05 +08:00
```yaml
apisix:
router:
http: 'radixtree_uri_with_parameter'
```
route like
2021-01-03 11:26:40 +08:00
2020-12-30 22:13:05 +08:00
```
/blog/:name
```
will match both `/blog/dog` and `/blog/cat` .
For more details, see https://github.com/api7/lua-resty-radixtree/#parameters-in-path.
2019-09-03 21:30:46 +08:00
### How to filter route by Nginx builtin variable
Please take a look at [radixtree-new ](https://github.com/iresty/lua-resty-radixtree#new ),
2019-09-05 17:23:06 +08:00
here is an simple example:
2019-09-03 21:30:46 +08:00
```shell
2020-11-28 19:05:14 +08:00
$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
2019-09-03 21:30:46 +08:00
{
"uri": "/index.html",
2019-09-05 17:23:06 +08:00
"vars": [
2020-10-04 13:52:04 +08:00
["http_host", "==", "iresty.com"],
["cookie_device_id", "==", "a66f0cdc4ba2df8c096f74c9110163a9"],
["arg_name", "==", "json"],
["arg_age", ">", "18"],
["arg_address", "~~", "China.*"]
2019-09-05 17:23:06 +08:00
],
2019-09-03 21:30:46 +08:00
"upstream": {
"type": "roundrobin",
"nodes": {
"39.97.63.215:80": 1
}
}
}'
```
This route will require the request header `host` equal `iresty.com` , request cookie key `_device_id` equal `a66f0cdc4ba2df8c096f74c9110163a9` etc.
2020-12-10 15:51:00 +08:00
2021-06-21 15:18:09 +08:00
### How to filter route by GraphQL attributes
2020-12-10 15:51:00 +08:00
2021-06-21 15:18:09 +08:00
APISIX supports filtering route by some attributes of GraphQL. Currently we support:
2020-12-10 15:51:00 +08:00
* graphql_operation
* graphql_name
* graphql_root_fields
2021-06-21 15:18:09 +08:00
For instance, with GraphQL like this:
2021-01-03 11:26:40 +08:00
2020-12-10 15:51:00 +08:00
```graphql
query getRepo {
owner {
name
}
repo {
created
}
}
```
* The `graphql_operation` is `query`
* The `graphql_name` is `getRepo` ,
* The `graphql_root_fields` is `["owner", "repo"]`
We can filter such route out with:
2021-01-03 11:26:40 +08:00
2020-12-10 15:51:00 +08:00
```shell
$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
{
"methods": ["POST"],
"uri": "/_graphql",
"vars": [
["graphql_operation", "==", "query"],
["graphql_name", "==", "getRepo"],
["graphql_root_fields", "has", "owner"]
],
"upstream": {
"type": "roundrobin",
"nodes": {
"39.97.63.215:80": 1
}
}
}'
```
2021-06-21 15:18:09 +08:00
To prevent spending too much time reading invalid GraphQL request body, we only read the first 1 MiB
2020-12-10 15:51:00 +08:00
data from the request body. This limitation is configured via:
```yaml
graphql:
max_size: 1048576
```
2021-06-21 15:18:09 +08:00
If you need to pass a GraphQL body which is larger than the limitation, you can increase the value in `conf/config.yaml` .