本 EdgeLang 教程演示如何在 OpenResty Edge 中使用其基于规则的小语言 EdgeLang 编写网关规则。每条 EdgeLang 规则由一个条件和一个结果(一组动作)组成,二者用箭头(=>)连接,并以分号结束——例如把 /foo/ 的请求重定向到 /bar/。下面我们添加一条页面规则重定向、用 curl 测试、把它从精确匹配改为前缀匹配,再编写一条 WAF 规则——所有改动都无需重载、重启或二进制升级即可推送到每台网关。初次接触 EdgeLang?请先了解 EdgeLang 是什么、为何优于手写 Lua

EdgeLang 如何编译规则以提升性能

用户可以使用 Edgelang 来编写复杂的网关规则,用于自定义认证、重写请求和响应、配置动态上游路由等等。这些规则的运行速度通常要比手写的 Lua 代码快很多。Edgelang 编译器会生成高效的原生代码,在网关服务器上运行。

Edgelang 编译器是非常高效的。它实现了许多先进的优化技术。它支持将所有 Edgelang 规则所引用的正则表达式合并到一个状态机中。这样只需扫描一次请求数据,就会立即知道能匹配上哪些规则以及这些规则的哪些部分。

它还支持把所有 Edgelang 规则的常量字符串前缀和后缀模式组合成单一的树状数据结构。

如何编写 EdgeLang 页面规则(URL 重定向示例)

让我们进入 OpenResty Edge 的 Admin Web 控制台。这就是我们控制台的样本部署。每个用户都有自己的本地部署。

OpenResty Edge web 控制台的样本部署

我们可以继续使用之前的示例应用,test-edge.com。

OpenResty Edge 应用列表,显示示例应用 test-edge.com

进入该应用。

进入 OpenResty Edge 中的 test-edge.com 应用

在之前的教程中我们已经创建了一个页面规则。

OpenResty Edge 应用中已有的一条页面规则

这个页面规则设置了一个反向代理到一个上游。

配置为反向代理到上游的页面规则

可以在这里添加我们的 Edgelang 代码。

页面规则中的 EdgeLang 代码编辑器

现在来添加第一条规则。

添加第一条 EdgeLang 规则

首先是规则的条件部分。条件是当 URI 是 “/foo/” 时。

匹配 URI /foo/ 的 EdgeLang 规则条件

用箭头来标志条件部分的结束。

用箭头结束 EdgeLang 条件部分

箭头之后,我们指定当条件得到满足时要执行的动作。

在箭头之后指定 EdgeLang 动作

这个动作启动了一个 HTTP 重定向到 “/bar/” 页面。

发起 HTTP 重定向到 /bar/ 的 EdgeLang 动作

保存这个规则。

保存 EdgeLang 规则

正如我们看到的那样,一段 EdgeLang 配置由若干条规则组成。每条规则都有两个基本部分:

显示两个基本部分的 EdgeLang 规则

一个是条件部分,

EdgeLang 规则的条件部分

另外一个是由动作组成的结果。

EdgeLang 规则的结果(动作)部分

条件和结果由一个箭头连接。

EdgeLang 条件与结果由箭头连接

整个规则以一个分号结束。

以分号结束的 EdgeLang 规则

这只是一个最简单的规则。我们可以随意添加各种规则。一条规则可以有多个条件,各个条件之间可以用 AND 或者 OR 连接。一条规则在其结果部分也可以执行多个动作。

带 AND/OR 条件和多个动作的多条 EdgeLang 规则

像往常一样,需要发布一个新的版本来推送我们刚才的改动。

在 OpenResty Edge 中发布新的配置版本

点击这个按钮。

OpenResty Edge 的配置发布按钮

发布!

确认配置发布

新版本现在已经同步到所有的网关服务器上了。

新版本已同步到所有网关服务器

现在,新的页面规则已经被推送到所有的网关集群和服务器。

配置发布正在同步到网关集群和服务器(开始)

配置发布正在同步到网关集群和服务器(进行中)

配置发布已同步到所有网关集群和服务器(完成)

这些配置的变化不需要服务器重载、重启或二进制升级。所以它是非常高效和可扩展的。

配置变更推送到网关,无需重载、重启或二进制升级

用 curl 测试 EdgeLang 规则

在终端上,我们通过 curl 命令行工具向一个由 DNS 解析的网关服务器发送 HTTP 请求。

curl -I http://test-edge.com/bar/

终端:向 test-edge.com/bar/ 发送 curl -I 请求

请注意响应头没有重定向。

/bar/ 的响应头,没有重定向

接下来,让我们发送一个带有 /foo/ URI 的 HTTP 请求。

curl -I http://test-edge.com/foo/

终端:向 test-edge.com/foo/ 发送 curl -I 请求

可以看到这个请求已经被重定向了。

响应头显示 /foo/ 请求被重定向

它被重定向到 /bar/ 这个位置。刚才定义的 Edgelang 规则生效了!

响应确认重定向到 /bar/,EdgeLang 规则生效

让我们测试另一个前缀为 “/foo/” 的 URI。

终端:测试带 /foo/ 前缀的另一个 URI

这个 URI 有一个额外的后缀,“blah/"。

终端:带额外后缀的 /foo/blah/ 请求

发送请求。

发送 /foo/blah/ 请求

可以看到这个请求并没有命中 Edgelang 规则。这是因为我们的 Edgelang 条件需要完全匹配 “/foo/"。

响应显示精确匹配下 /foo/blah/ 未命中 EdgeLang 规则

修改 EdgeLang 规则:精确匹配 vs. 前缀匹配

我们可以修改 Edgelang 规则中的条件部分来处理这种情况。

编辑 EdgeLang 规则条件以处理前缀情况

单击 “编辑” 按钮。

EdgeLang 页面规则上的"编辑"按钮

删除原来的条件。

删除原来的精确匹配条件

将其改为匹配 URI 前缀 “/foo/"。

将条件改为匹配 URI 前缀 /foo/

保存这个规则。

保存修改后的 EdgeLang 规则

再做一次新配置的发布。

编辑规则后发布新的配置版本

配置发布对话框

配置发布进行中

配置发布已同步到网关

回到终端。再次发送我们之前的测试请求。

终端:再次发送之前的 /foo/blah/ 测试请求

仍然采用 “blah/” URI 的后缀。

终端:请求仍使用 /foo/blah/ 后缀

发送请求。

改为前缀匹配后发送 /foo/blah/ 请求

可以看到它触发了一个重定向,这次是命中了我们的 Edgelang 规则。

响应显示前缀匹配下 /foo/blah/ 现在被重定向

接下来,让我们发送一个没有任何额外 URI 后缀的 HTTP 请求。

curl -I http://test-edge.com/foo/

终端:向 test-edge.com/foo/ 发送不带后缀的 curl -I 请求

仍然能够命中。

响应显示前缀匹配下 /foo/ 仍被重定向

如何用 EdgeLang 编写 WAF 规则

我们可以在 Web 控制台的许多不同地方使用 Edgelang。例如,可以用 EdgeLang 为 WAF,或 Web 应用防火墙添加自定义规则。如需深入了解可编程 WAF 本身——包括如何启用、测试和拦截攻击,以及它对比 ModSecurity 的性能基准——请参阅这些专门的教程。

OpenResty Edge 控制台的 Web 应用防火墙(WAF)部分

OpenResty Edge 中的 WAF 规则列表

创建一个新的 WAF 规则。

在 OpenResty Edge 中创建新的 WAF 规则

在这里写入 Edgelang。

在 WAF 规则编辑器中编写 EdgeLang

EdgeLang 用户手册与更多示例

我们自主设计的 EdgeLang 网关小语言是一种非常强大的语言,有很多特性。语言支持调用自定义 Lua 模块和 Lua 代码,或者任意 .so 动态链接库——参见在 EdgeLang 中调用 Lua 模块的实操示例。其编译器支持跨规则深度优化。

EdgeLang 能力:调用自定义 Lua 模块、.so 库和跨规则优化

如需了解更多,欢迎阅读 Edgelang 用户手册英文版更完整更新一些。

EdgeLang 用户手册文档页面

手册里有许多代码实例。

EdgeLang 用户手册展示大量代码示例

非常详细地介绍了 Edgelang 的各种用法。

EdgeLang 用户手册页面,列出详细的用法说明

常见问题

如何编写一条 EdgeLang 规则?

一段 EdgeLang 配置由若干条规则组成。每条规则有两个部分——一个条件和一个结果(一组动作)——用箭头(=>)连接,并以分号结束。一条规则可以用 AND/OR 组合多个条件,其结果部分也可以执行多个动作。例如,一条条件匹配 URI /foo/ 的规则,可以触发一个把请求重定向到 /bar/ 的动作。

修改 EdgeLang 规则后需要重载或重启网关吗?

不需要。编辑 EdgeLang 规则后,你发布一个新的配置版本,它会同步到所有网关服务器和集群。这些改动不需要任何服务器重载、重启或二进制升级,因此推送新规则非常高效且可扩展。

EdgeLang 能定义 WAF 规则吗?

可以。除了页面规则,EdgeLang 还能用在 Web 控制台的许多地方,包括为 Web 应用防火墙(WAF)编写自定义规则。你直接在 WAF 规则编辑器中写 EdgeLang,使用同样的条件与动作语法。

EdgeLang 中精确匹配和前缀匹配有什么区别?

/foo/ 的精确匹配条件只在 URI 恰好是 /foo/ 时命中,因此对 /foo/blah/ 的请求不会命中。如果你希望规则也覆盖子路径,就把条件改为匹配 URI 前缀 /foo/;这样 /foo//foo/blah/ 都会触发规则。

关于 OpenResty Edge

OpenResty Edge 是一款专为微服务和分布式流量架构设计的全能型网关软件,由我们自主研发。它集流量管理、私有 CDN 构建、API 网关、安全防护等功能于一体,帮助您轻松构建、管理和保护现代应用程序。OpenResty Edge 拥有业界领先的性能和可扩展性,能够满足高并发、高负载场景下的苛刻需求。它支持调度 K8s 等容器应用流量,并可管理海量域名,轻松满足大型网站和复杂应用的需求。

如果你喜欢这个教程,请订阅这个博客网站和我们的 YouTube 频道B 站频道。谢谢!

关于作者

章亦春是开源 OpenResty® 项目创始人兼 OpenResty Inc. 公司 CEO 和创始人。

章亦春(Github ID: agentzh),生于中国江苏,现定居美国湾区。他是中国早期开源技术和文化的倡导者和领军人物,曾供职于多家国际知名的高科技企业,如 Cloudflare、雅虎、阿里巴巴, 是 “边缘计算“、”动态追踪 “和 “机器编程 “的先驱,拥有超过 22 年的编程及 16 年的开源经验。作为拥有超过 4000 万全球域名用户的开源项目的领导者。他基于其 OpenResty® 开源项目打造的高科技企业 OpenResty Inc. 位于美国硅谷中心。其主打的两个产品 OpenResty XRay(利用动态追踪技术的非侵入式的故障剖析和排除工具)和 OpenResty Edge(最适合微服务和分布式流量的全能型网关软件),广受全球众多上市及大型企业青睐。在 OpenResty 以外,章亦春为多个开源项目贡献了累计超过百万行代码,其中包括,Linux 内核、Nginx、LuaJITGDBSystemTapLLVM、Perl 等,并编写过 60 多个开源软件库。

关注我们

如果您喜欢本文,欢迎关注我们 OpenResty Inc. 公司的博客网站 。也欢迎扫码关注我们的微信公众号:

我们的微信公众号

翻译

我们提供了英文版原文和中译版(本文) 。我们也欢迎读者提供其他语言的翻译版本,只要是全文翻译不带省略,我们都将会考虑采用,非常感谢!