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

  • Can you rename the files? – Michael Hampton May 25 '16 at 16:09
  • I have no control over the files on the server. But how this will help? – user2035693 May 26 '16 at 7:13
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.

  • 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 :) – user2035693 May 27 '16 at 13:30
  • I moved try_files $uri $uri/ @thengine; inside location / {} and indeed is working without the need of error_page – user2035693 May 27 '16 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;
  • 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. – user2035693 May 26 '16 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. – Tero Kilkanen May 27 '16 at 10:36
  • My answer was compltely wrong for obvious reason, good news I have the correct one – Taras Chuhay May 27 '16 at 14:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.