Home > Enterprise >  How to activate nginx sub_filter when it is present in configuration?
How to activate nginx sub_filter when it is present in configuration?

Time:05-25

I have downloaded nginx windows image in version 1.21.6 (https://nginx.org/en/download.html), the nginx -V output contains --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

Unfortunatelly, I am not able to make the substitution work :( I tried to get some inspiration here: https://samanbaboli.medium.com/modify-html-pages-on-the-fly-using-nginx-2e7a2d069086

Here is my config

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;
    }
  }
}

Any ideas, what I am doing wrong?

http://localhost/ won't throw alert "Hi", http://localhost/test returns "OKAY", not expected "OK".

According to this answer, there should not be any parameters or additional config required :( Nginx, how to start service with ngx_http_sub_module enabled

CodePudding user response:

The Content-Type HTTP header, unless being specified explicitly via the default_type directive (at the location or any level up) will be equal to text/plain by default. The sub_filter directive works only with on content with the text/html MIME type, unless additional types are specified using the sub_filter_types directive. So, to make your substitution work in the /test location, use either

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

or, if you didn't have default_type directive specifying some other type than text/plain somewhere else,

location /test {
    return 200 'OKAY';
    sub_filter_types text/plain;
    sub_filter 'OKAY' 'OK';
}

I don't see any reason the substitution does not work in your main location. Check the actual MIME type returned from the https://example.org and the used upper/lower case for the HTML tags. Is it really </head> and not the </HEAD>?

Update

As being noticed by OP the sub_filter module didn't work with compressed upstream responses, so if upstream is able to compress its response, the Accept-Encoding header should not be passed to the upstream:

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