hyperscan: Hyperscan for nginx-module-lua
安装
如果您尚未设置 RPM 仓库订阅,请 注册。然后您可以继续以下步骤。
CentOS/RHEL 7 或 Amazon Linux 2
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install lua-resty-hyperscan
CentOS/RHEL 8+、Fedora Linux、Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install lua5.1-resty-hyperscan
要在 NGINX 中使用此 Lua 库,请确保已安装 nginx-module-lua。
本文档描述了 lua-resty-hyperscan v0.3,于 2022 年 4 月 14 日发布。
lua-resty-hyperscan - Hyperscan for Openresty
!!! 旧分支 遇到 太多回调 问题,因为 luajit 并不完全支持 CALLBACK。因此我们需要一个 C 包装器 来处理回调。
首先,您应该安装 openresty
git clone git@github.com:LubinLew/lua-resty-hyperscan.git cd lua-resty-hyperscan make make install make test
##
##
## 概述
配置示例
```lua
user nobody;
worker_processes auto;
error_log logs/error.log error;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
access_log logs/access.log;
init_by_lua_block {
local whs, err = require('hyperscan')
if not whs then
ngx.log(ngx.ERR, "失败:", err)
return
end
-- 新建
local obj = whs.block_new("a-uniq-name", true) -- true : 启用调试模式
local patterns = {
{id = 1001, pattern = "\\d3", flag = "iu"},
{id = 1002, pattern = "\\s{3,5}", flag = "u"},
{id = 1003, pattern = "[a-d]{2,7}", flag = ""}
}
-- 编译
ret, err = obj:compile(patterns)
if not ret then
ngx.log(ngx.ERR, "hyperscan 块编译失败, ", err)
return
end
}
server {
listen 80;
server_name localhost;
location / {
content_by_lua_block {
local whs = require('hyperscan')
local obj = whs.block_get("a-uniq-name")
-- 扫描
local ret, id, from, to = obj:scan(ngx.var.uri)
if ret then
return ngx.print("[", ngx.var.uri,"] 匹配: ", id, " 区域 [", from, " - ", to, ").\n")
else
return ngx.print("[", ngx.var.uri, "] 不匹配任何规则.\n")
end
}
}
}
}
测试用例:
$ curl http://localhost
[/] 不匹配任何规则。
$ curl http://localhost/131111111
[/131111111] 匹配: 1001 区域 [0 - 3)。
$ curl "http://localhost/ end"
[/ end] 匹配: 1002 区域 [0 - 4)。
$ curl http://localhost/aaaaaaa
[/aaaaaaa] 匹配: 1003 区域 [0 - 3)。
方法
加载此库的方法
local whs,err = require('hyperscan')
if not whs then
ngx.log(ngx.ERR, "原因: ", err)
end
block_new
为块模式创建一个 hyperscan 实例。
local handle, err = whs.block_new(name, debug)
if not handle then
ngx.log(ngx.ERR, "原因: ", err)
end
| 字段 | 名称 | Lua 类型 | 描述 |
|---|---|---|---|
| 参数 | name |
string | 实例名称,主要用于日志 |
debug |
boolean | 启用/禁用将调试日志写入 syslog | |
| 返回值 | handle |
table/nil | 实例引用 |
err |
string | 失败原因 |
block_free
销毁块模式的 hyperscan 实例。
whs.block_free(name)
block_get
通过名称获取实例引用。
local handle = whs.block_get(name)
| 字段 | 名称 | Lua 类型 | 描述 |
|---|---|---|---|
| 参数 | name |
string | 实例名称 |
| 返回值 | handle |
table/nil | 实例引用 |
vector_new
为向量模式创建一个 hyperscan 实例。
local handle, err = whs.vector_new(name, debug)
if not handle then
ngx.log(ngx.ERR, "原因: ", err)
end
| 字段 | 名称 | Lua 类型 | 描述 |
|---|---|---|---|
| 参数 | name |
string | 实例名称,主要用于日志 |
debug |
boolean | 启用/禁用将调试日志写入 syslog | |
| 返回值 | handle |
table/nil | 实例引用 |
err |
string | 失败原因 |
vector_free
销毁向量模式的 hyperscan 实例。
whs.vector_free(name)
vector_get
通过名称获取实例引用。
local handle = whs.vector_get(name)
| 字段 | 名称 | Lua 类型 | 描述 |
|---|---|---|---|
| 参数 | name |
string | 实例名称 |
| 返回值 | handle |
table/nil | 实例引用 |
handle:compile
将正则表达式编译成 Hyperscan 数据库。
--local handle = whs.block_new(name, debug)
local ok, err = handle:compile(patterns)
if not ok then
ngx.log(ngx.ERR, "原因: ", err)
end
| 字段 | 名称 | Lua 类型 | 描述 |
|---|---|---|---|
| 参数 | patterns |
table | 模式列表 |
| 返回值 | ok |
boolean | 成功/失败 |
err |
string | 失败原因 |
模式列表
示例
local patterns = {
{id = 1001, pattern = "\\d3", flag = "iu" },
{id = 1002, pattern = "\\s{3,5}", flag = "dmsu" },
{id = 1003, pattern = "[a-d]{2,7}", flag = "" }
}
标志
| 标志 | Hyperscan 值 | 描述 |
|---|---|---|
'i' |
HS_FLAG_CASELESS | 设置不区分大小写的匹配 |
'd' |
HS_FLAG_DOTALL | 匹配 . 不会排除换行符。 |
'm' |
HS_FLAG_MULTILINE | 设置多行锚定。 |
's' |
HS_FLAG_SINGLEMATCH | 设置仅单次匹配模式。 |
'e' |
HS_FLAG_ALLOWEMPTY | 允许可以匹配空缓冲区的表达式。 |
'u' |
HS_FLAG_UTF8 | 启用此表达式的 UTF-8 模式。 |
'p' |
HS_FLAG_UCP | 启用此表达式的 Unicode 属性支持。 |
'f' |
HS_FLAG_PREFILTER | 启用此表达式的预过滤模式。 |
'l' |
HS_FLAG_SOM_LEFTMOST | 启用最左侧匹配报告。 |
'c' |
HS_FLAG_COMBINATION | 逻辑组合。 |
'q' |
HS_FLAG_QUIET | 不进行任何匹配报告。 |
handle:scan
实际的模式匹配发生在块模式的模式数据库中。
--local handle = whs.block_get(name)
local ok, id, from, to = handle:scan(data)
if ok then
ngx.log(ngx.INFO, "匹配成功", id, from, to)
end
实际的模式匹配发生在向量模式的模式数据库中。
--local handle = whs.vector_get(name)
--local data = {"s","s2"}
--local data = "s"
local ok, id, dataindex, to = handle:scan(data)
if ok then
ngx.log(ngx.INFO, "匹配成功", id, from, to)
end
| 字段 | 名称 | Lua 类型 | 描述 |
|---|---|---|---|
| 参数 | data |
string/string[] | 要扫描的字符串(仅向量模式为 string[]) |
| 返回值 | ok |
boolean | true 表示匹配,false 表示不匹配 |
id |
number | 匹配 ID | |
from |
number | 匹配开始字节数组索引(包括自身) | |
to |
number | 匹配结束字节数组索引(不包括自身) | |
dataindex |
number | 匹配数据索引(仅向量模式) |
handle:free
销毁一个 hyperscan 实例。
--local handle = whs.block_get(name)
handle:free()
GitHub
您可以在 nginx-module-hyperscan 的 GitHub 仓库 中找到此模块的其他配置提示和文档。