Score:2

Redirect to other server and domain if file not found

sd flag

I have migrated from Apache to Nginx so I want to set all rules in Nginx.

Goal: Redirect a URL to another domain with the same filename if that file is not found on the requested server.

Example

If a user open https://www.example.com/data/1.jpg then my server will try to find "1.jpg" in "data" dir. If that file is not found then redirect the user to backup server URL like https://www.example2.com/backup/1.jpg

Example in .htaccess

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule (.*) - [L]
RewriteRule (.*) https://example2.com/backup/$1 [L]

What I have tried

  1. Search for existing solutions but I didn't find any working solution.
  2. Try to convert apache config to Nginx config via converters but not working.

Some tried config but not working.

    location ~ /data/.* {
        if (-e $request_filename){
            rewrite ^ https://www.example2.com/backup/$1 last;
        } 
    }


    location ~ /data/.* {
        if (-e $request_filename){
            rewrite ^ https://www.example2.com/backup/$1 permanent;
        } 
    }


    location ~ /data/.* {
        try_files $uri https://www.example2.com/backup/$uri;
    }
kz flag
In your example you are redirecting from `example.com/data/1.jpg` to `example2.com/backup/1.jpg` - is that intentional? Or should it be `example2.com/backup/data/1.jpg` (which is what your code and current answer is assuming)?
Shubham Panchal avatar
sd flag
Yes, example2.com/backup/1.jpg is intentional.
Score:1
sd flag

I got the solution after modifying @Rob answer.

set $v_filename nf;

location ~ ^/data/(.*)$ {
    try_files  $uri  @externalbackup;
    set $v_filename $1;
}

location @externalbackup {
     return 301  https://www.example2.com/backup/$v_filename ;
}
Score:1
us flag
Rob

In nginx you would use a try_files directive, which serves the content from a local file, if it exists in one (or more) local directories. When no file is found, an internal redirect to the uri specified in the last parameter is made.

Since that can't redirect externally, you need a little bit of trickery and a two tier approach. In the try_files options you use named location for that internal redirect, and from that named location you construct the external redirect.

location / {
    try_files  $uri  @externalbackup;
}

location @externalbackup {
     return 301  https://www.example2.com/backup$request_uri ;
}

The above code is untested.

kz flag
I would think this type of redirect should be a 302 (temporary) if there is any intention that the originally requested file might exist in the future.
Shubham Panchal avatar
sd flag
Thank you @Rob for your answer. I have tried this and the redirect is working but the file name is not working in redirected URL. It's like: https://www.example2.com/backup But it should: https://www.example2.com/backup/file_name_here
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.