Nginx use rewrite as dynamic 404 image

http-status-code-404nginxphp-fpmrewrite

I want to get a dynamic 404 response depending on the requested url:

foo.jpg doesn't exist

http://example.com/img/style/thumbnail/foo.jpg  

should show

http://example.com/img/notfound/thumbnail.jpg  

with a 404 header status

I got the rewriting part right, but i can't seem to get it return with a 404 status code.
I tried this with the following code, but without success:

location ~ /img {
    if (!-f $request_filename){
            rewrite "^(.*img\/)style\/([a-zA-Z\_\-[0-9]*)\/?(.+)" $1notfound/$2.jpg;
            #so far so good. Now i want to return the rewrite result as a 404 response
            error_page 404 = $request_filename;
            return 404;
    }
}

This gives me the default nginx 404 error page instead of the rewritten url with 404 status code.
How can i tell nginx to use the rewrite result as 404 error page?

Best Answer

You have misunderstood the $request_filename variable. It represents the physical path mapped to the file considering root and alias directives values and the current URI being processed.

So your error_page directive will internally redirect to a URI corresponding to a physical path that doesn't exist as it the same as the path tested to enter your if block.

Operator = in error directive is not an issue, it simply tells nginx to keep the current error code as it is. You are also escaping some symbols in your regex that you don't need to and it hurts readability.

So, your if block does exactly what location blocks do with regular expressions.

You could simply reduce that to :

location /img {

    location ~ ^/img/style/([_-a-zA-Z0-9]*) {
        error_page 404 /img/notfound/$1.jpg;
    }

}
Related Topic