0

If a file with ".html" extension doesn't exist I need to know if the same file exists with ".th.html" extension and make a redirect.

Right now on 404 I'm doing a rewrite and if $request_filename exists I do the redirect.

    try_files $uri $uri/ @thengine;

    error_page 404 = @thengine;

    location @thengine {
            rewrite ^/(.*)\.(htm|html)$ /$1.th.html;

            if (-f $request_filename) {
                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                    proxy_set_header Host $http_host;
                    proxy_intercept_errors on;
                    proxy_redirect off;

                    proxy_pass http://thengine_backend;
            }
    }

I'm wondering if there is a better way to do that without rewrite.

Maybe something like

if ($request_filename ~ (some rule to replace extension)){...}

Thank you.

Edit: All requests from browser will come with .html, but in case the file with .html doesn't exist, I have to check if the same file exists with .th.html and do redirect only on this case.

Edit2: Let's say someone access domain-nginx.com/path/to/index.html

  • nginx must check if file exist, and if it does, show the page
  • if file doesn't exist, look for index.th.html
  • if index.th.html doesn't exist give directly 404
  • if index.th.html DOES exist set some headers and serve domain-app.com/path/to/index.th.html (here is an application that will process these kind of templates)

All this time the user must see only domain-nginx.com/path/to/index.html and not see any redirect or the url to change.

Notice that .th.html is handled by another application

2
  • Can you rename the files? May 25, 2016 at 16:09
  • I have no control over the files on the server. But how this will help? May 26, 2016 at 7:13

2 Answers 2

0

You don't need the error_page directive here, since you already have @thengine as the last part in your try_files directive. To answer the actual question, I need clarification what you actually want to happen..

For your actual use case, I think this is the most simple solution. You could modify the @thengine like this:

 location @thengine {
     rewrite ^/(.*)\.(htm|html)$ /$1.th.html;

     if (-f $request_filename) {
             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
             proxy_set_header Host $http_host;
             proxy_intercept_errors on;
             proxy_redirect off;

             proxy_pass http://thengine_backend;
             break;
     }
     return 404;
}

However, I am not 100% sure that this configuration is safe, because of this article: https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/.

The current implementation of the if directive in nginx easily causes unwanted side-effects, and the implementation needs to be properly checked. After reading the article above, and the article explaining if behavior, I still am not sure whether this solution is safe.

A safer solution could be implemented with a Lua script.

2
  • I tried with @thengine only as last directive of try_files, but doesn't seems to work; that part is never executed, that's why I put it on error_page 404. (I'm using nginx 1.10). I updated my question. I hope you can understand what I try to do now :) May 27, 2016 at 13:30
  • I moved try_files $uri $uri/ @thengine; inside location / {} and indeed is working without the need of error_page May 27, 2016 at 14:49
-1

This one should work. With a little help from rewrite engine. It is not full as you still need to check for non-existent file.

location /your_location {
try_files $uri $uri/ @rewrite;
}
location @rewrite {
    if (!-e $request_filename) {
    rewrite ^/(.*)\.html$ /$1.th.html last;
    }
}

Wrong answer:

What if you try something like this:

try_files $uri.html $uri.th.html =404;
3
  • unfortunately is not having the desired behavior. Is redirecting all my traffic to @thengine even if .th.html extension doesn't exist. I updated my question with extra explanation. May 26, 2016 at 7:12
  • $uri contains the complete filename. So, for example, if the request URI is /test.html, this solution would try /test.html.html, /test.html.th.html and then return 404. May 27, 2016 at 10:36
  • My answer was compltely wrong for obvious reason, good news I have the correct one May 27, 2016 at 14:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .