最新消息:

Nginx反向代理使用的一些坑(续)–gzip/gunzip 与sub_filter的那些事

VPS xunihao 2145浏览 0评论

需要反向代理访问某个网站(upstream.com),由于需要动态替换反向代理页面中的链接地址,因此使用sub_filter,但发现未替换成功。认为是响应结果gzip导致的,设置 proxy_set_header Accept-Encoding ” 或 proxy_http_version 1.0 ,sub_filter依然不生效。

按照《Nginx反向代理使用的一些坑》的经验,应该是上游网站强制返回gzip压缩过的内容。在使用文中提到的“与上游服务器连接依然启用gzip压缩,但在调用sub_filter前先解压缩,然后再做替换操作”几种方法时候,发现一些新的问题及注意事项,作为《Nginx反向代理使用的一些坑》的补充说明。

1、使用Nginx ngx_http_gunzip_module

proxy_pass https://upstream.com/;
gunzip on;
sub_filter 'upstream.com' 'mydomain.com';
sub_filter_once off;

使用以上代码,发现一个奇怪现象,有时候能够替换成功,有时候不行,现象随机,怀疑是gunzip与sub_filter并非串行执行的。
在 https://www.mail-archive.com/[email protected]/msg1313433.html 发现一个回答,提到gunzip on 需要配合 gzip_disable “.” 使用。

(gzip_disable is needed because the author of gunzip had a different use
case in mind. Without this option, as an optimization nginx does not
decompress the proxied data for a client which breaks the substitution
filter.)

尝试gzip_disable “.” 后,发现确实有效。
也即:

proxy_pass https://upstream.com/;
gunzip on;
gzip_disable ".";
sub_filter 'upstream.com' 'mydomain.com';
sub_filter_once off;

2、做两次proxy_pass
基本思路:
a、mydomain.com server 通过unix socket将请求proxy_pass发送给监听server
b、监听unix socket的server向上游upstream发起反向代理请求,请求为gzip on(proxy_set_header Accept-Encoding gzip;)
c、监听unxi socket的server对请求结果gunzip,将gunzip结果回复给mydomain.com server
d、在mydomain.com server对响应结果调用sub_filter替换

server {
  listen unix:/var/run/nginx-gunzip.sock;
  location / {

        proxy_pass https://upstream.com ;

        gunzip on;
        proxy_set_header Host "upstream.com";
        proxy_set_header Referer "https://upstream.com";
        proxy_set_header User-Agent "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:73.0) Gecko/20100101 Firefox/73.0";
        #proxy_http_version 1.1;
        proxy_set_header Accept-Encoding gzip;		
        proxy_set_header X-Real-IP $remote_addr;
        #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_connect_timeout 60s;
        proxy_read_timeout 5400s;
        proxy_send_timeout 5400s;
        proxy_buffer_size 64k;
        proxy_buffers 32 32k;
        proxy_busy_buffers_size 128k;
        proxy_ssl_verify off;
        proxy_ssl_server_name on;

  }
}

server {
        server_name mydomain.com;
        listen 80 ;
        listen 443 ssl http2;
        index index.html index.htm;
        root  /data/wwwroot/mydomain.com;
        error_page 400 = /400.html;

        location /
        {
        proxy_pass http://unix:/var/run/nginx-gunzip.sock:/;
        sub_filter_types *;
        sub_filter 'upstream.com'  'mydomain.com';
        sub_filter_once off;

        }
}

值得说明一下,相对于通过http请求,unix socket更为高效,但我用的1.6.1 版本存在重启nginx,不会自动删除创建的unix socket情况(SIGQUIT信号不会删除,SIGTERM会自动删除,参见:https://trac.nginx.org/nginx/ticket/753)。

可以把删除操作放到nginx 的service脚本中。

在Centos中,修改 vi /etc/systemd/system/nginx.service,增加

ExecStartPre=/usr/bin/rm -f /var/run/nginx-gunzip.sock

 

转载请注明:虚拟号之家 » Nginx反向代理使用的一些坑(续)–gzip/gunzip 与sub_filter的那些事

发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址