hyperscan: Hyperscan para nginx-module-lua
Instalación
Si no has configurado la suscripción al repositorio RPM, regístrate. Luego puedes proceder con los siguientes pasos.
CentOS/RHEL 7 o 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
Para usar esta biblioteca Lua con NGINX, asegúrate de que nginx-module-lua esté instalado.
Este documento describe lua-resty-hyperscan v0.3 lanzado el 14 de abril de 2022.
lua-resty-hyperscan - Hyperscan para Openresty
!!! Old Branch tuvo un problema de demasiados callbacks, porque luajit no soporta completamente CALLBACK. Así que necesitamos un C wrapper para manejar callbacks.
Primero, debes instalar openresty
git clone git@github.com:LubinLew/lua-resty-hyperscan.git cd lua-resty-hyperscan make make install make test
##
##
## Sinopsis
Ejemplo de configuración
```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, "Fallo:", err)
return
end
-- nuevo
local obj = whs.block_new("a-uniq-name", true) -- true : habilitar modo de depuración
local patterns = {
{id = 1001, pattern = "\\d3", flag = "iu"},
{id = 1002, pattern = "\\s{3,5}", flag = "u"},
{id = 1003, pattern = "[a-d]{2,7}", flag = ""}
}
-- compilar
ret, err = obj:compile(patterns)
if not ret then
ngx.log(ngx.ERR, "la compilación del bloque hyperscan falló, ", 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")
-- escanear
local ret, id, from, to = obj:scan(ngx.var.uri)
if ret then
return ngx.print("[", ngx.var.uri,"] coincide: ", id, " zona [", from, " - ", to, ").\n")
else
return ngx.print("[", ngx.var.uri, "] no coincide con ninguna regla.\n")
end
}
}
}
}
Casos de prueba:
$ curl http://localhost
[/] no coincide con ninguna regla.
$ curl http://localhost/131111111
[/131111111] coincide: 1001 zona [0 - 3).
$ curl "http://localhost/ end"
[/ end] coincide: 1002 zona [0 - 4).
$ curl http://localhost/aaaaaaa
[/aaaaaaa] coincide: 1003 zona [0 - 3).
Métodos
Forma de cargar esta biblioteca
local whs,err = require('hyperscan')
if not whs then
ngx.log(ngx.ERR, "razón: ", err)
end
block_new
Crea una instancia de hyperscan para el modo bloque.
local handle, err = whs.block_new(name, debug)
if not handle then
ngx.log(ngx.ERR, "razón: ", err)
end
| Campo | Nombre | Tipo Lua | Descripción |
|---|---|---|---|
| Parámetro | name |
string | nombre de la instancia, principalmente para el registro |
debug |
boolean | habilitar/deshabilitar el registro de depuración en syslog | |
| Valor de Retorno | handle |
table/nil | referencia de la instancia |
err |
string | razón del fallo |
block_free
Destruir una instancia de hyperscan para el modo bloque.
whs.block_free(name)
block_get
Obtener la referencia de la instancia por nombre.
local handle = whs.block_get(name)
| Campo | Nombre | Tipo Lua | Descripción |
|---|---|---|---|
| Parámetro | name |
string | nombre de la instancia |
| Valor de Retorno | handle |
table/nil | referencia de la instancia |
vector_new
Crea una instancia de hyperscan para el modo vector.
local handle, err = whs.vector_new(name, debug)
if not handle then
ngx.log(ngx.ERR, "razón: ", err)
end
| Campo | Nombre | Tipo Lua | Descripción |
|---|---|---|---|
| Parámetro | name |
string | nombre de la instancia, principalmente para el registro |
debug |
boolean | habilitar/deshabilitar el registro de depuración en syslog | |
| Valor de Retorno | handle |
table/nil | referencia de la instancia |
err |
string | razón del fallo |
vector_free
Destruir una instancia de hyperscan para el modo vector.
whs.vector_free(name)
vector_get
Obtener la referencia de la instancia por nombre.
local handle = whs.vector_get(name)
| Campo | Nombre | Tipo Lua | Descripción |
|---|---|---|---|
| Parámetro | name |
string | nombre de la instancia |
| Valor de Retorno | handle |
table/nil | referencia de la instancia |
handle:compile
Compilar una expresión regular en una base de datos de Hyperscan.
--local handle = whs.block_new(name, debug)
local ok, err = handle:compile(patterns)
if not ok then
ngx.log(ngx.ERR, "razón: ", err)
end
| Campo | Nombre | Tipo Lua | Descripción |
|---|---|---|---|
| parámetro | patterns |
table | lista de patrones |
| Valor de Retorno | ok |
boolean | éxito/fallo |
err |
string | razón del fallo |
Lista de Patrones
Ejemplo
local patterns = {
{id = 1001, pattern = "\\d3", flag = "iu" },
{id = 1002, pattern = "\\s{3,5}", flag = "dmsu" },
{id = 1003, pattern = "[a-d]{2,7}", flag = "" }
}
Flags
| Flag | Valor de Hyperscan | Descripción |
|---|---|---|
'i' |
HS_FLAG_CASELESS | Establecer coincidencias sin distinción entre mayúsculas y minúsculas |
'd' |
HS_FLAG_DOTALL | Coincidir un . no excluirá nuevas líneas. |
'm' |
HS_FLAG_MULTILINE | Establecer anclaje de varias líneas. |
's' |
HS_FLAG_SINGLEMATCH | Establecer modo de coincidencia única. |
'e' |
HS_FLAG_ALLOWEMPTY | Permitir expresiones que pueden coincidir con búferes vacíos. |
'u' |
HS_FLAG_UTF8 | Habilitar modo UTF-8 para esta expresión. |
'p' |
HS_FLAG_UCP | Habilitar soporte de propiedades Unicode para esta expresión. |
'f' |
HS_FLAG_PREFILTER | Habilitar modo de prefiltrado para esta expresión. |
'l' |
HS_FLAG_SOM_LEFTMOST | Habilitar el informe del inicio de coincidencia más a la izquierda. |
'c' |
HS_FLAG_COMBINATION | Combinación lógica. |
'q' |
HS_FLAG_QUIET | No hacer ningún informe de coincidencias. |
handle:scan
La coincidencia real de patrones tiene lugar para bases de datos de patrones en modo bloque.
--local handle = whs.block_get(name)
local ok, id, from, to = handle:scan(data)
if ok then
ngx.log(ngx.INFO, "coincidencia exitosa", id, from, to)
end
La coincidencia real de patrones tiene lugar para bases de datos de patrones en modo vector.
--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, "coincidencia exitosa", id, from, to)
end
| Campo | Nombre | Tipo Lua | Descripción |
|---|---|---|---|
| Parámetro | data |
string/string[] | cadena a escanear (solo string[] en modo vector) |
| Valor de Retorno | ok |
boolean | true para coincidencia, false para no coincidencia |
id |
number | id de coincidencia | |
from |
number | índice de byte de inicio de coincidencia (incluido) | |
to |
number | índice de byte de fin de coincidencia (excluido) | |
dataindex |
number | índice de datos coincidente (solo modo vector) |
handle:free
Destruir una instancia de hyperscan.
--local handle = whs.block_get(name)
handle:free()
GitHub
Puedes encontrar consejos adicionales de configuración y documentación para este módulo en el repositorio de GitHub para nginx-module-hyperscan.