路由 RadixTree

    Apache APISIX 使用 libradixtree 作为路由调度库。

    libradixtree 是基于 raxlua-resty-* 实现。

    我们通过下面的示例可以有一个直观的理解。

    1. 完全匹配

    此时只能匹配 /blog/foo

    2. 前缀匹配

    1. /blog/bar*

    它将匹配带有前缀 /blog/bar 的路径, 例如: /blog/bar/a/blog/bar/b/blog/bar/c/d/e/blog/bar 等。

    3. 匹配优先级

    完全匹配 -> 深度前缀匹配

    以下是规则:

    1. /blog/foo/*
    2. /blog/foo/a/*
    3. /blog/foo/c/*
    4. /blog/foo/bar

    4. 不同的路由具有相同 uri

    当不同的路由有相同的 uri 时,可以通过设置路由的 priority 字段来决定先匹配哪条路由,或者添加其他匹配规则来区分不同的路由。

    注意:在匹配规则中, priority 字段优先于除 uri 之外的其他规则。

    1、不同的路由有相同的 uri 并设置 priority 字段

    1. $ curl http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
    2. {
    3. "upstream": {
    4. "nodes": {
    5. "127.0.0.1:1980": 1
    6. },
    7. "type": "roundrobin"
    8. },
    9. "priority": 3,
    10. "uri": "/hello"
    11. }'
    1. $ curl http://127.0.0.1:9180/apisix/admin/routes/2 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
    2. {
    3. "upstream": {
    4. "nodes": {
    5. "127.0.0.1:1981": 1
    6. },
    7. "type": "roundrobin"
    8. },
    9. "priority": 2,
    10. "uri": "/hello"

    测试:

    1. curl http://127.0.0.1:1980/hello
    2. 1980

    所有请求只到达端口 1980 的路由。

    2、不同的路由有相同的 uri 并设置不同的匹配条件

    以下是设置主机匹配规则的示例:

    1. $ curl http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
    2. {
    3. "nodes": {
    4. "127.0.0.1:1980": 1
    5. },
    6. "type": "roundrobin"
    7. },
    8. "hosts": ["localhost.com"],
    9. "uri": "/hello"
    10. }'

    测试:

    1. $ curl http://127.0.0.1:9080/hello -H 'host: localhost.com'
    2. 1980
    1. $ curl http://127.0.0.1:9080/hello -H 'host: test.com'
    2. 1981
    1. $ curl http://127.0.0.1:9080/hello
    2. {"error_msg":"404 Route Not Found"}

    host 规则匹配,请求命中对应的上游,host 不匹配,请求返回 404 消息。

    5. 参数匹配

    当使用 radixtree_uri_with_parameter 时,我们可以用参数匹配路由。

    例如,使用配置:

    1. apisix:
    2. router:
    3. http: 'radixtree_uri_with_parameter'

    示例:

    1. /blog/:name

    此时将匹配 /blog/dog/blog/cat

    具体参数及使用方式请查看 文档,下面是一个简单的示例:

    1. $ curl http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
    2. {
    3. "uri": "/index.html",
    4. "vars": [
    5. ["http_host", "==", "iresty.com"],
    6. ["cookie_device_id", "==", "a66f0cdc4ba2df8c096f74c9110163a9"],
    7. ["arg_name", "==", "json"],
    8. ["arg_age", ">", "18"],
    9. ["arg_address", "~~", "China.*"]
    10. ],
    11. "upstream": {
    12. "type": "roundrobin",
    13. "nodes": {
    14. "127.0.0.1:1980": 1
    15. }
    16. }
    17. }'

    这个路由需要请求头 host 等于 iresty.com, 请求 cookie _device_id 等于 等。

    APISIX 支持通过 POST 表单属性过滤路由,其中需要您使用 Content-Type = application/x-www-form-urlencoded 的 POST 请求。

    我们可以定义这样的路由:

    当 POST 表单中包含 name=json 的属性时,将匹配到路由。

    目前,APISIX 可以处理 HTTP GET 和 POST 方法。请求体正文可以是 GraphQL 查询字符串,也可以是 JSON 格式的内容。

    APISIX 支持通过 GraphQL 的一些属性过滤路由。 目前我们支持:

    • graphql_operation
    • graphql_name
    • graphql_root_fields

    例如,像这样的 GraphQL:

    1. query getRepo {
    2. owner {
    3. name
    4. repo {
    5. created
    6. }
    7. }
    • graphql_operationquery
    • graphql_namegetRepo
    • graphql_root_fields["owner", "repo"]

    我们可以用以下方法过滤掉这样的路由:

    1. $ curl http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
    2. {
    3. "methods": ["POST", "GET"],
    4. "uri": "/graphql",
    5. "vars": [
    6. ["graphql_operation", "==", "query"],
    7. ["graphql_name", "==", "getRepo"],
    8. ["graphql_root_fields", "has", "owner"]
    9. ],
    10. "upstream": {
    11. "type": "roundrobin",
    12. "nodes": {
    13. "127.0.0.1:1980": 1
    14. }
    15. }
    16. }'

    我们可以通过以下三种方式分别去验证 GraphQL 匹配:

    1. 使用 GraphQL 查询字符串
    1. $ curl -H 'content-type: application/graphql' -X POST http://127.0.0.1:9080/graphql -d '
    2. query getRepo {
    3. owner {
    4. name
    5. }
    6. repo {
    7. created
    8. }
    9. }'
    1. 使用 JSON 格式
    1. $ curl -H 'content-type: application/json' -X POST \
    2. http://127.0.0.1:9080/graphql --data '{"query": "query getRepo { owner {name } repo {created}}"}'
    1. 尝试 GET 请求
    1. $ curl -H 'content-type: application/graphql' -X GET \
    2. "http://127.0.0.1:9080/graphql?query=query getRepo { owner {name } repo {created}}" -g
    1. graphql:

    如果你需要传递一个大于限制的 GraphQL 查询语句 ,你可以增加 conf/config.yaml 中的值。