在 OpenResty Edge 中根据浏览器语言重定向,只需创建一条页面规则,同时匹配请求 URI / 客户端发送的 Accept-Language 请求头,再挂上一个跳转到对应语言路径(如 /fr/)的重定向动作。把它标记为置顶规则让它最先执行,再加一条兜底规则把其他所有语言都跳到 /en/。配置会下发到每个网关节点,无需服务器重载、重启或二进制升级。

下面我们在 OpenResty Edge 的 Admin 控制台里一步步创建这两条规则,并用 curl 和浏览器验证。如果你想先看一个更简单的规则,可以参考如何用 301 页面规则将 HTTP 重定向到 HTTPS

示意图:OpenResty Edge 根据 Accept-Language 头把访客重定向到对应语言的 URI

按路径提供多语言的源站

假设我们有一个支持在不同路径下展示不同语言的源站。例如,这是 /en/ 路径。

$ curl 'http://test-edge.com/en/'
Hello, world!

注意这里是英文, “Hello, world!”。

/fr/ 路径下还有一个法语版本。

$ curl 'http://test-edge.com/fr/'
Bonjour, le monde!

这里显示的是法语。

创建页面规则按 Accept-Language 重定向

今天设置的目标是,当客户端访问根路径 / 时,我们可以根据其语言配置自动重定向到特定语言的路径下。我们将使用客户端发送的 Accept-Language 请求头。

OpenResty Edge 根据 Accept-Language 头将根路径重定向到对应语言路径

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

这一次我们继续使用 test-edge.com 域名的样本应用。

进入这个应用。

在 OpenResty Edge Admin 控制台中进入 test-edge.com 应用

我们已经定义了一个上游。

应用中已定义的 my_backend 上游

这个 my backend 上游只有一个后端服务器。也就是我们在视频开头使用的源站。

my_backend 上游只有一个指向源站的后端服务器

而且我们也有一个已经定义好的页面规则。

应用现有的页面规则列表

这个页面规则设置了一个反向代理到我们刚才看到的 my backend 上游。

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

创建一个新的页面规则。

在 OpenResty Edge 控制台中创建新的页面规则

我们启用一个规则条件来检查 URI /

启用规则条件以匹配请求 URI

这个下拉框里列出了所有我们可以选择的变量。

页面规则条件可选的变量列表

选择变量 URI

为条件选择 URI 变量

运算符选择字符串等号。

为 URI 条件选择字符串等号运算符

URI 条件已选定字符串等号运算符

输入值 /,表示只匹配根路径。

输入 / 作为值,只匹配根路径

第二个条件用来检查语言。

添加检查请求语言的第二个条件

为语言条件选择变量

我们选择 Request header 作为变量。

为语言条件选择 Request header 变量

输入请求头名称 Accept-Language

输入要匹配的请求头名称 Accept-Language

运算符这里,

打开 Accept-Language 条件的运算符列表

我们选择“前缀”。

为 Accept-Language 请求头选择前缀运算符

这表示当同时指定多种语言时,我们只关心第一种。

我们选择正则表达式类型 Regex 作为匹配的值。

为 Accept-Language 值选择 Regex 正则匹配类型

Accept-Language 值已选定 Regex 匹配类型

输入正则值 fr\b

输入正则 fr\b 以匹配 fr、fr-CA 等法语标签

\b 的意思是匹配一个词的边界。这样写 frfr-CA 都会匹配得到。

这里,我们勾选“忽略大小写”以进行不区分大小写的匹配。

勾选忽略大小写,对 Accept-Language 做不区分大小写匹配

现在我们有了以 AND 相连接的两个条件。也就是说,必须同时满足这两个条件,才能执行下面的动作。已经完成条件的编写。

现在我们添加一个新的动作。

为页面规则添加新的动作

搜索动作“重定向”。

选择动作类型“重定向”。

选择重定向动作类型

然后我们配置跳转到的目标 URI 。

配置重定向动作的目标 URI

选择“自定义”。我们要自己输入 URI 。

为重定向选择自定义目标 URI

输入 /fr/

输入 /fr/ 作为法语访客的重定向目标

保持其余字段不动。

其余重定向字段保持默认

如果命中此条规则的话跳过所有余下的页面规则。

启用命中即跳过后续规则

我们需要确保这条规则总是在其他规则之前运行。我们把它标记为一个置顶规则。置顶规则不是一个普通规则。

将规则标记为置顶规则,使其先于普通规则运行

保存这个规则。

保存法语 Accept-Language 重定向规则

我们可以看到新添加的页面规则确实置顶在规则列表。

新的重定向规则出现在页面规则列表顶部

它确实出现在我们之前的代理规则之前。

和以往一样, 我们需要发布这条规则以使其生效。

发布新配置以下发该页面规则

将新配置发布到各网关集群

发布!

配置发布已同步到所有网关集群

这里可以看到同步完成了。

新页面规则已推送到每个网关集群和服务器

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

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

OpenResty Edge 将配置同步到网关节点,无需重载、重启或二进制升级

用 curl 测试法语 Accept-Language 重定向

在终端上,我们可以用 curl 发送 HTTP 请求。

curl -I -H 'Accept-Language: fr-CA, fr, en' http://test-edge.com/

这里我们指定了 3 种语言:fr-CA, fr, 和 en 。所以对于这个请求,法语优先于英语。

用 Accept-Language: fr-CA, fr, en 发送 curl 请求测试重定向

运行这个命令。

注意看这里确实重定向到了 /fr/

响应显示对法语 Accept-Language 头重定向到 /fr/

我们可以让 curl 命令自动跟随重定向。

curl -L -H 'Accept-Language: fr, en' http://test-edge.com/

这里使用 -L 选项。

用 curl -L 自动跟随语言重定向

运行这个命令。

我们可以看到返回的法语文本。

跟随重定向后返回的法语页面内容

添加兜底页面规则将其他语言重定向到英文

接下来,我们会添加一个通用的页面规则以实现当客户端发送的请求头带有其他语言时重定向到英文页面。

为英文兜底创建第二条页面规则

创建一个新的页面规则。

为兜底规则启用 URI 条件

我们仍然启用一个规则条件来检查 URI /

为兜底条件选择 URI 变量

兜底条件已选定 URI 变量

仍然选择 URI

为兜底条件选择字符串等号运算符

仍然选择字符串等号。

准备为兜底条件输入 URI 值

输入 / 为兜底规则匹配根路径

像以前一样输入值 /

兜底条件只匹配根 URI、不检查语言

条件编写完成。这一次我们不用再去检查请求头了。

像上次一样添加一个新的重定向动作。

为兜底规则添加重定向动作

为兜底规则选择重定向动作类型

配置兜底规则的重定向目标

为兜底重定向选择自定义目标 URI,输入 /en/

这一次,我们为目标 URI 输入 /en/

为兜底规则启用命中即跳过后续规则

如果命中此条规则的话跳过所有余下的页面规则。

让兜底规则仍先于其他普通规则运行

我们仍然要确保这个规则在其他“普通规则”之前运行。

保存英文兜底重定向规则

保存这个规则。

兜底规则排在代理规则之前、法语规则之后

我们可以看到新添加的页面规则在代理规则之前,但在上次添加的那条法语规则之后。

再次发布新配置

再做一次新配置的发布。

发布更新后的配置

再次将配置发布到所有网关集群

再次发布!

配置再次同步完成

同步又完成了。

在浏览器中测试英文兜底重定向

这次我们使用浏览器测试 / 路径。我们的浏览器的语言设置是英文。

这里可以看到返回的是英文文本 Hello, world。

浏览器显示英文页面,地址栏 URL 改写为 /en/

从地址栏我们还可以看到,URI 变成了 /en/

常见问题

OpenResty Edge 如何判断访客的语言?

它读取 Accept-Language 请求头,也就是客户端随每个请求发送的语言偏好。页面规则用前缀运算符加正则(如 fr\b)匹配这个头,因此 frfr-CA 这类地区变体都会命中。任何设置了 Accept-Language 的客户端——包括 curl——都会触发同一条重定向。

不改 nginx.conf 也能根据浏览器语言重定向吗?

可以。整条规则都在 OpenResty Edge 的 Admin 控制台里搭建:一个 URI 条件、一个 Accept-Language 请求头条件,再加一个重定向动作。发布一次配置后,规则就会下发到所有网关集群,无需服务器重载、重启或二进制升级。

如何设置默认语言兜底?

再加一条页面规则,只匹配根路径 /、不检查 Accept-Language,动作是重定向到 /en/。把语言专属规则排在它前面,让兜底规则最后执行。本教程里法语规则先匹配法语客户端,其余所有语言都落到英文页面。

为什么把语言重定向标记为置顶规则?

置顶规则总是先于普通规则运行,因此语言重定向会在服务根路径的反向代理规则之前被判定。配合“命中即跳过后续规则”,就能保证客户端在任何其他规则响应之前,被送到正确的语言路径。

客户端一次发送多种语言时会怎样?

Accept-Language 头可以列出多种语言,例如 fr-CA, fr, en。由于用的是前缀匹配,只有第一个(优先级最高的)语言会被考虑。在这个例子里法语优先于英语,因此请求被重定向到 /fr/

关于 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. 公司的博客网站 。也欢迎扫码关注我们的微信公众号:

我们的微信公众号

翻译

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