如何在nginx配置中启用sub_filter?

3

我已经下载了版本为1.21.6的nginx windows镜像(https://nginx.org/en/download.html),nginx -V输出包含--with-http_sub_module

PS C:\Utils\nginx-1.21.6> .\nginx.exe -V
nginx version: nginx/1.21.6
built by cl 16.00.40219.01 for 80x86
built with OpenSSL 1.1.1m  14 Dec 2021
TLS SNI support enabled
configure arguments: --with-cc=cl --builddir=objs.msvc8 --with-debug --prefix= --conf-path=conf/nginx.conf --pid-path=logs/nginx.pid --http-log-path=logs/access.log --error-log-path=logs/error.log --sbin-path=nginx.exe --http-client-body-temp-path=temp/client_body_temp --http-proxy-temp-path=temp/proxy_temp --http-fastcgi-temp-path=temp/fastcgi_temp --http-scgi-temp-path=temp/scgi_temp --http-uwsgi-temp-path=temp/uwsgi_temp --with-cc-opt=-DFD_SETSIZE=1024 --with-pcre=objs.msvc8/lib/pcre2-10.39 --with-zlib=objs.msvc8/lib/zlib-1.2.11 --with-http_v2_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_stub_status_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module --with-http_secure_link_module --with-http_slice_module --with-mail --with-stream --with-openssl=objs.msvc8/lib/openssl-1.1.1m --with-openssl-opt='no-asm no-tests -D_WIN32_WINNT=0x0501' --with-http_ssl_module --with-mail_ssl_module --with-stream_ssl_module

很遗憾,我无法让替换工作 :( 我试着从这里获取一些灵感: https://samanbaboli.medium.com/modify-html-pages-on-the-fly-using-nginx-2e7a2d069086 以下是我的配置:
worker_processes 1;
worker_rlimit_nofile 8192;
pid nginx.pid;

events {
    worker_connections 24;
}
http {
  server {
    listen 80;
    server_name  localhost;

    location / {
      proxy_pass      https://example.org;
      sub_filter '</head>' '<script>alert("Hi")</script></head>';
      sub_filter_once on;
    }

    location /test {
      return 200 'OKAY';
      sub_filter 'OKAY' 'OK';
      sub_filter_once on;
    }
  }
}

有什么想法,我做错了什么吗?

http://localhost/不会弹出警报“Hi”,http://localhost/test返回“OKAY”,而不是期望的“OK”。

根据这个答案,不应该需要任何参数或额外的配置 :( Nginx,如何启用带有ngx_http_sub_module的服务

1个回答

6

除非使用default_type指令(在位置或任何级别上)明确指定,否则Content-Type HTTP头默认为text/plainsub_filter指令仅适用于具有text/html MIME类型的内容,除非使用sub_filter_types指令指定其他类型。因此,在/test位置使您的替换起作用,请使用以下任一选项:

location /test {
    default_type text/html;
    return 200 'OKAY';
    sub_filter 'OKAY' 'OK';
}

或者,如果您没有在其他地方指定除text/plain以外的其他类型的default_type指令,
location /test {
    return 200 'OKAY';
    sub_filter_types text/plain;
    sub_filter 'OKAY' 'OK';
}

我看不出为什么替换在你的主要位置不起作用。检查来自 https://example.org 的实际 MIME 类型和 HTML 标签的大小写使用情况。它真的是 </head> 而不是 </HEAD> 吗?
更新
正如 OP 注意到的那样,sub_filter 模块无法处理压缩的上游响应,因此如果上游能够压缩其响应,则不应将 Accept-Encoding 头传递给上游:
location / {
    proxy_pass https://example.org;
    proxy_set_header Accept-Encoding "";
    sub_filter '</head>' '<script>alert("Hi")</script></head>';
    sub_filter_once on;
}

1
感谢您的帮助,第一种情况下添加 sub_filter_types *; 很有帮助。在 example.org 中添加 proxy_set_header Accept-Encoding ""; 也很有帮助,因为 sub_filter 无法处理来自 proxy_host 的 gzip 压缩响应:https://til.hashrocket.com/posts/7ktzgumkmp-subfilter-proxypass-requires-no-gzip-encoding - tomas
1
使用 sub_filter_types *; 应该是最后的选择,因为它可能会对性能产生显著影响。 - Ivan Shatsky
谢谢提醒。我也发现,我不能使用sub_filter,因为源应用程序正在使用ETag,当我使用sub_filter时会被删除:( 我需要在上游服务器端进行替换。 - tomas
在我的情况下,我正在遵循这里的入门指南:https://docs.nginx.com/nginx/deployment-guides/setting-up-nginx-demo-environment/,我必须设置sub_filter_types text/html;。 - Jake Boomgaarden

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接