反向代理解决微信小程序业务域名限制问题

最近项目上有需求需要在小程序中跳转第三方网页,但微信业务域名限制了跳转,当聊到这个问题的时候马上就想到了nginx的反向代理。然后就进行了尝试。

nginx 版本为 1.12-alpine。

nginx配置反向代理

1
2
3
4
5
6
7
8
9
server {
...

location ^~ /testre/ {
proxy_pass https://xxx.com/;
}

...
}

在nginx配置中添加代理,将访问 xxx.com 的所有链接代理到自己服务器的 /testre/* 路径下。然后在小程序中访问。

结果: 成功绕过域名限制,但css js 图片等资源加载失败,因为路径匹配不上。如 src=”/js/main.js”,因为匹配不到 /testre/ 路径,所以没有代理上。

修改响应以代理其它资源

为了解决这个问题,马上想到是否可以用 lua 在将资源返回到前端前进行内容的修改。但因为项目中使用的 nginx 镜像没有 lua-nginx-module ,我也无法对镜像进行修改,所以另寻它法。

使用 nginx -V 命令查看的时候,虽然没有发现 lua-nginx-module,但看到了 ngx_http_sub_module;该模块可以修改网站响应内容中的字符串达到我的目的。于是修改 nginx 配置文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
server {
...

location ^~ /testre/ {
proxy_pass https://xxx.com/;

sub_filter_types *;
sub_filter xxx.com myserver.com/testre;
sub_filter 'src="/images/' 'src="/testre/images/';
sub_filter 'href="/css/' 'href="/testre/css/';
sub_filter 'src="/js/' 'src="/testre/js/';
sub_filter_once off;
}

...
}

然后访问,发现没有替换成功;网上搜索了一下发现了原因: xxx.com 开启了 gzip 压缩,而 ngx_http_sub_module 对压缩内容是匹配不到相应字符串的,于是加上请求头 Accept-Encoding “”。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
server {
...

location ^~ /testre/ {
proxy_set_header Accept-Encoding "";
proxy_pass https://xxx.com/;

sub_filter_types *;
sub_filter xxx.com myserver.com/testre;
sub_filter 'src="/images/' 'src="/testre/images/';
sub_filter 'href="/css/' 'href="/testre/css/';
sub_filter 'src="/js/' 'src="/testre/js/';
sub_filter_once off;
}

...
}

结果: 页面大部分资源加载成功,还是有小部分资源加载失败。

查看这些加载失败的资源,发现是在 css 内部定义的,并且其 url 由 url(../ 变为了 url(../testre/ 。继续修改配置文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
server {
...

location ^~ /testre/ {
proxy_set_header Accept-Encoding "";
proxy_pass https://xxx.com/;

sub_filter_types *;
sub_filter xxx.com myserver.com/testre;
sub_filter 'src="/images/' 'src="/testre/images/';
sub_filter 'href="/css/' 'href="/testre/css/';
sub_filter 'src="/js/' 'src="/testre/js/';
sub_filter url(../testre/ url(../;
sub_filter_once off;
}

...
}

结果: 未替换成功。猜测还是 gzip 的原因。

在网上找到一个方法,反代理自身,利用 gunzip 模块先解压,然后再进行替换。修改配置文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

server {
listen unix:/var/run/nginx-gunzip.sock;
location / {
proxy_set_header Accept-Encoding gzip;
proxy_pass https://xxx.com/;
gunzip on;
access_log off;
}
}

server {
...

location ^~ /testre/ {
proxy_pass http://unix:/var/run/nginx-gunzip.sock:https://xxx.com/;

sub_filter_types *;
sub_filter xxx.com myserver.com/testre;
sub_filter 'src="/images/' 'src="/testre/images/';
sub_filter 'href="/css/' 'href="/testre/css/';
sub_filter 'src="/js/' 'src="/testre/js/';
sub_filter url(../testre/ url(../;
sub_filter_once off;
}

...
}

再访问结果即ok了。

参考链接