Nginx 反向代理配置与 URLSearchParams 中空格处理的实践指南

300 阅读2分钟

需求背景

今天处理了一个需求,需要将一个外部页面嵌入到我们自己的页面中,通过现有的微前端架构实现。

问题描述

外部页面的资源是以相对路径的形式引用的,例如使用 "publicPath: '.'"。在微前端架构下,通常的 Nginx 反向代理配置如下:

location ~* /subSystem {
    proxy_pass http://subSystem:30970;  # 注意最后没有 /
}

这种配置要求子应用的资源必须放置在 /usr/share/nginx/html/subSystem 目录下,即子应用的资源路径(publicPath)必须为 /subSystem/。对于内部子系统,我们可以要求其遵循这一规则,但对于外部页面则无法做到这一点。

解决方案

为了适应外部页面的需求,我们需要调整 Nginx 的反向代理配置,以便支持任意的资源路径。具体的配置如下:

location ~* /subSystem/(.*)$ {
    proxy_pass http://ip:port/$1?$args;
}

其中,$1 是捕获的路径部分,$args 是查询字符串参数。

规则总结

  1. 路径重写: 如果 proxy_pass 后面指定了路径名称,则会覆盖 location 中的路径,而不是简单拼接。
  2. 查询参数: 必须显式添加 $args 以传递查询参数,否则它们将被忽略。

进一步的问题

在解决了上述问题后,又遇到了一个新的挑战:用户的 token 作为外部页面的查询参数没有生效,http://ip:port?token=xxx。尽管 token 值是正确的,但仍然不起作用。排查后发现,如果子应用使用的是前端路由的 hash 模式,那么需要以 http://ip:port/#/?token=xxx 的形式访问页面,这样路由系统才能解析成功。

注意事项

  • 正常情况下,无需在 Nginx 层面对 hash 进行特殊处理,因为它默认会忽略 hash 值。
  • 确保前端框架能够正确解析 hash 模式的路由。

URLSearchParams 小贴士

在使用 URLSearchParams 处理查询参数时,需要注意空格会被转换为 +。可以复制下面代码试一试:

const searchParams = new URLSearchParams();
searchParams.append('token', 'Bearer 1234');
searchParams.toString() // 'token=Bearer+1234'

解决方法

  1. 使用 %20 替换空格:
javascript
const searchParams = new URLSearchParams();
searchParams.append('token', 'Bearer%201234');
console.log(searchParams.toString()); // 'token=Bearer%201234'
  1. 手动编码:
javascript
const searchParams = new URLSearchParams();
searchParams.append('token', encodeURIComponent('Bearer 1234'));
console.log(searchParams.toString()); // 'token=Bearer%201234'

这样,你可以根据具体需求选择合适的方法来处理查询参数中的空格。