Nginx – Use of “sub_filter” in “IF” block under nginx config

nginx

I have nginx as reverse_proxy server for multiple applications running behind on various application servers. I want induce specific html/script into response content for set pre-registered urls. These URLs may belongs any application behind nginx. For this i am using sub_filter for all urls and it is working fine. But when i try to put "sub_filter" in "IF" block it is now allowing.

I need something like below.

 resolver 8.8.8.8;
 proxy_pass http://www.example.com;
 proxy_set_header Accept-Encoding *;
 gunzip on;
if ( $induceScript = 1) {

                       sub_filter "</body>" "<div class='induced' <font color=red size=8>Induced Text </font></div></body>";
                       sub_filter_types *;
                       sub_filter_once off;

                    }

The following error message is displaying when i try restart nginx.

nginx: [emerg] "sub_filter" directive is not allowed here in /etc/openresty/openresty.conf

From this if i understand correctly "IF" directive not allowing "sub_fiter" inside it. Any specific reason existed for that? Also provide correct way/alternative way to solve this.

Best Answer

The error appears because the directive sub_filter is just not allowed in any other directive besides following: http, server, location
Taken from http://nginx.org/en/docs/http/ngx_http_sub_module.html#sub_filter

server {
        listen 82;
        listen 83;
        server_name example.com;
        root /var/www/9000;
        try_files $uri $uri/index.html;
        sub_filter "</body>" $conditional_filter;
        sub_filter_types *;
        sub_filter_once off;
}
map $server_port $conditional_filter {
        82      "<br>Added content</body>";
        default "</body>";
}

You need to replace the if with a map directive.
In this example I add additional content based on the port of the server/website.
http://example.com:82 results in content like <body>abc</body>
where http://example.com:83 results in following content <body>abc<br>Added content</body>.
Instead of $server_port you can use your own variable $induceScript or a different condition.