English | 中文 (Translated by ChatGPT)
Lua-Radix-Router 是一个轻量级高性能的路由器,用纯 Lua 编写。该路由器易于使用,只有两个方法,Router.new() 和 Router:match()。它可以集成到不同的运行时环境,如 Lua 应用程序、LuaJIT 或 OpenResty 中。
该路由器专为高性能而设计。采用了压缩动态 Trie(基数树)以实现高效匹配。即使有数百万个包含复杂路径的路由,匹配仍可在1纳秒内完成。
-
变量路径:语法
{varname}
。/users/{id}/profile-{year}.{format}
:允许在一个路径段中有多个变量
-
前缀匹配:语法
{*varname}
/api/authn/{*path}
-
变量绑定:路由器在匹配过程中会自动为您注入绑定结果。
-
最佳性能:Lua/LuaJIT 中最快的路由器。请参阅性能基准。
-
OpenAPI 友好:完全支持 OpenAPI。
在路线图中的特性:(start或创建issue来加速优先级)
-
尾部斜杠匹配:使 URL /foo/ 能够与 /foo 路径匹配。
-
表达式条件:通过使用表达式语言定义自定义匹配条件。
-
变量中的正则表达式
通过 LuaRocks 安装 radix-router:
luarocks install radix-router
或者从源码安装
make install
通过示例开始:
local Router = require "radix-router"
local router, err = Router.new({
{ -- 静态路径
paths = { "/foo", "/foo/bar", "/html/index.html" },
handler = "1" -- 处理程序可以是任何非空值(例如布尔值、表、函数)
},
{ -- 变量路径
paths = { "/users/{id}/profile-{year}.{format}" },
handler = "2"
},
{ -- 前缀路径
paths = { "/api/authn/{*path}" },
handler = "3"
},
{ -- 方法条件
paths = { "/users/{id}" },
methods = { "POST" },
handler = "4"
}
})
if not router then
error("failed to create router: " .. err)
end
assert("1" == router:match("/html/index.html"))
assert("2" == router:match("/users/100/profile-2023.pdf"))
assert("3" == router:match("/api/authn/token/genreate"))
assert("4" == router:match("/users/100", { method = "POST" }))
-- 变量绑定
local params = {}
router:match("/users/100/profile-2023.pdf", nil, params)
assert(params.year == "2023")
assert(params.format == "pdf")
有关更多用法示例,请参阅 /samples
目录。
创建一个 radix 路由器实例。
local router, err = Router.new(routes)
参数
- routes(
table|nil
): the array-like Route table.
路由定义了其处理程序的匹配条件:
属性 | 描述 |
---|---|
paths required* |
匹配条件的路径列表。 |
methods optional |
匹配条件的方法列表。 |
handler required* |
当路由匹配时,router:match() 将返回处理程序的值。 |
priority optional |
在 radix 树节点冲突的情况下,路由的优先级。 |
expression optional (TDB) |
expression 使用表达式语言定义的匹配条件 |
返回匹配路径和条件 ctx 的匹配路由的处理程序。
local handler = router:match(path, ctx, params)
参数
- path(
string
): 用于匹配的路径。 - ctx(
table|nil
): 用于匹配的可选条件 ctx。 - params(
table|nil
): 用于存储参数绑定结果的可选表。
$ make install
$ make bench
- Apple MacBook Pro(M1 Pro), 32GB
- LuaJIT 2.1.1700008891
$ make bench
TEST CASE | Router number | nanoseconds / op | QPS | RSS |
---|---|---|---|---|
static path | 100000 | 0.0129826 | 77,026,173 | 65.25 MB |
simple variable | 100000 | 0.0802077 | 12,467,630 | 147.52 MB |
simple variable | 1000000 | 0.084604 | 11,819,772 | 1381.47 MB |
simple prefix | 100000 | 0.0713651 | 14,012,451 | 147.47 MB |
complex variable | 100000 | 0.914117 | 1,093,951 | 180.30 MB |
simple variable binding | 100000 | 0.21054 | 4,749,691 | 147.28 MB |
github | 609 | 0.375829 | 2,660,784 | 2.72 MB |
展开输出
RADIX_ROUTER_ROUTES=100000 RADIX_ROUTER_TIMES=10000000 luajit benchmark/static-paths.lua
========== static path ==========
routes : 100000
times : 10000000
elapsed : 0.129826 s
QPS : 77026173
ns/op : 0.0129826 ns
path : /50000
handler : 50000
Memory : 65.25 MB
RADIX_ROUTER_ROUTES=100000 RADIX_ROUTER_TIMES=10000000 luajit benchmark/simple-variable.lua
========== variable ==========
routes : 100000
times : 10000000
elapsed : 0.802077 s
QPS : 12467630
ns/op : 0.0802077 ns
path : /1/foo
handler : 1
Memory : 147.52 MB
RADIX_ROUTER_ROUTES=1000000 RADIX_ROUTER_TIMES=10000000 luajit benchmark/simple-variable.lua
========== variable ==========
routes : 1000000
times : 10000000
elapsed : 0.84604 s
QPS : 11819772
ns/op : 0.084604 ns
path : /1/foo
handler : 1
Memory : 1381.47 MB
RADIX_ROUTER_ROUTES=100000 RADIX_ROUTER_TIMES=10000000 luajit benchmark/simple-prefix.lua
========== prefix ==========
routes : 100000
times : 10000000
elapsed : 0.713651 s
QPS : 14012451
ns/op : 0.0713651 ns
path : /1/a
handler : 1
Memory : 147.47 MB
RADIX_ROUTER_ROUTES=100000 RADIX_ROUTER_TIMES=1000000 luajit benchmark/complex-variable.lua
========== variable ==========
routes : 100000
times : 1000000
elapsed : 0.914117 s
QPS : 1093951
ns/op : 0.914117 ns
path : /aa/bb/cc/dd/ee/ff/gg/hh/ii/jj/kk/ll/mm/nn/oo/pp/qq/rr/ss/tt/uu/vv/ww/xx/yy/zz50000
handler : 50000
Memory : 180.30 MB
RADIX_ROUTER_ROUTES=100000 RADIX_ROUTER_TIMES=10000000 luajit benchmark/simple-variable-binding.lua
========== variable ==========
routes : 100000
times : 10000000
elapsed : 2.1054 s
QPS : 4749691
ns/op : 0.21054 ns
path : /1/foo
handler : 1
params : name = foo
Memory : 147.28 MB
RADIX_ROUTER_TIMES=1000000 luajit benchmark/github-routes.lua
========== github apis ==========
routes : 609
times : 1000000
elapsed : 0.375829 s
QPS : 2660784
ns/op : 0.375829 ns
path : /repos/vm-001/lua-radix-router/import
handler : /repos/{owner}/{repo}/import
Memory : 2.72 MB