Nginx rewrite URL only if file exists

Solution 1:

location /images/ {
    if (-f $request_filename) {

    rewrite ^/images/(.*) /new_images/$1 permanent;

Though, you might want to bug your host to upgrade or find a better host.

Solution 2:

Please don't use if inside a location block. Bad things may happen.

location ~* ^/images/(.+)$ {
    root /www;
    try_files /path/to/$1 /website_images/path_to/$1 /any/dir/$1 @your404;

$1 becomes the filename to try in the try_files directive, which is made for what you're trying to accomplish.

This, OR, just rewrite it without checking. If that image isn't there, you'll get a 404 anyway.

Solution 3:

You could use something like this (untested for your specific case):

location ^/images/(?<imgpath>.*)$ {

    set $no_old  0;
    set $yes_new 0;

    if (!-f $request_filename)
        set $no_old 1;

    if (-f ~* "^/new_path/$imgpath")
        set $yes_new 1$no_old;

    # replacement exists in the new path
    if ($yes_new = 11)
        rewrite ^/images/(.*)$ /new_path/$1 permanent;

    # no image in the new path!
    if ($yes_new = 01)
        return 404;

Which is basically an alternative way of writing nested if statements, since you cannot nest in Nginx. See here for official reference on this "hack".