由於項目需要使用Nginx做反向代理時,需要對源站返回的內容做一些替換,這些內容有 HTML,CSS,和JS等,Nginx自帶的ngx_http_sub_module 模塊可以實現替換的功能,但相對於YaoWenBin開發的ngx_http_substitutions_filter_module來說,功能還是稍弱一些:1、不支持大小寫區分;2、不支持正則表達式;3、不支持替換多個字符串(ngx_http_sub_module從1.9.4版本開始支持此功能)。
但在使用ngx_http_substitutions_filter_module發現 HTML的內容可以替換,但是JS\CSS文件卻替換不了,我將Respone Body內容復制到另外一台服務器上,然后再做反代,發現並沒有什么問題,可以正常工作。
我的核心配置文件如下(已經設置了禁用gzip壓縮)
location /demo/ { proxy_pass http://192.168.1.2 proxy_set_header Accept-Encoding ''; subs_filter src_string dst_string; subs_filter_types *; proxy_redirect off; }排查了近兩天,嘗試過升級Nginx版本等一系列操作,並沒有解決我的問題。
最后只能使用Nginx的Debug功能來排查,發現Debug的日志如下:
2016/05/20 10:47:59 [debug] 390#0: *1 http proxy header: "Content-Encoding: gzip" 2016/05/20 10:47:59 [warn] 390#0: *1 http subs filter header ignored, this may be a compressed response. while reading response header from upstream, client: 192.168.1.2, server: demo.xxxx.com, request: "GET /demo/login.js HTTP/1.1", upstream: "http://192.168.1.2:80/demo/login.js", host: "demo.xxxx.com"日志反映兩個問題:1、響應的HTTP HEADER中顯示內容使用GZIP格式壓縮;2、響應的內容可能時壓縮過的,http subs filter 模塊忽略,不處理!原來源站返回的JS和CSS內容還是被壓縮了,但是我已經設置了proxy_set_header Accept-Encoding ''了啊?為何返回的內容還是壓縮的?決定使用Wireshark抓包查看底層的數據包。
從數據包來看,請求的HEADER確實設置了不壓縮,但返回的內容確還是壓縮的,看來問題出在源站的WEB服務器。
向源站的管理員求證,得到的結果是:JS和CSS的文件已經是被壓縮過了的,所以不論請求的是否接收壓縮,返回的內容都是被壓縮的,這一點不能修改。
源站不能修改,只能從Nginx這里想辦法了,但是Nginx替換必須得不是解壓縮的,這就不好辦了。
摸索中發現這篇文章: Nginx 反代 Gzip 內容時, sub_filter 等 content filter 無效的另一種解決
雖然多了一次請求,但更加節省網絡帶寬資源。由於使用gunzip模塊解壓縮,只能再次重新編譯Nginx(這次排查問題,重新編譯了10次都不止啊
)。
文章中采用的是unix socket的方式,但從一些網友的測試來看,並不如tcp socket穩定(Php-fpm TcpSocket vs UnixSocket),我覺得還是采用監聽TCP端口的方式。最終的配置如下:
location /demo-gzip/ { proxy_pass http://192.168.1.2/; gunzip on; allow 127.0.0.1/32; deny all; } location /demo/ { proxy_pass http://127.0.0.1/t5060-gzip/; proxy_set_header Host demo.xxxx.com; proxy_set_header Accept-Encoding ''; subs_filter src_string dst_string; subs_filter_types application/javascript text/css; }