6

For my sites I typically have two server{} blocks: one serves the site, and the other serves static content for that site from a different domain. Because the favicon.ico file is always asked for from the primary domain instead of the static domain, I have to handle that specific file in the site's server{} block rather than the static file block.

When a favicon.ico file is not found, Nginx returns my define 404 error page, as well as the 404 HTTP status code. However, I don't want to send those bits for my pretty 404 page. I want to send a totally empty response with a 204 status code. Below is what I tried, however it does not work. Is there a correct way to do this? The idea being that a 204 would indicate a found file, however a totally blank image.

Also, is my attempt to save bits actually a bad idea? If, in fact, returning 204 instead of 404 is a bad idea, is there a more elegant way to return an empty 404 page without creating a new-and-actually-empty file and setting that as the error_page directive inside that location block?

server {
    ...


    error_page  404          /../static/404.html;

    location @return_204 {
        return  204;
    }

    # Case-insensitive matching of .txt and .xml files.
    # (Example: robots.txt, crossdomain.xml, and sitemap.xml)
    location ~* \.(txt|xml)$ {
        try_files  $uri /../static/$uri;
    }

    location = /favicon.ico {
        log_not_found  off;
        error_page     404 = @return_204;

        try_files      $uri /../static/$uri;
    }

    ...
}
Bryson
  • 1,186
  • 2
  • 13
  • 26

3 Answers3

9

I think this is what you're looking for:

location = /favicon.ico {
         try_files $uri = 204;
}

It will try to find the file at the URI or 204 as fallback. Here's the relevant documentation.

server_kitten
  • 386
  • 3
  • 13
  • 3
    For me it worked only when I removed the space between "=" and "204". – Valentin Stoykov Jan 30 '17 at 17:09
  • Also, when I add this code I noticed that nginx continues to execute other instructions instead of just give up and return error code. It did not add additional headers specified below in the nginx.conf if I change 204 to 404. ` location = /favicon.ico { try_files $uri =404; } set $TestingThisFix 'test 123'; add_header Testing-This-Fix $TestingThisFix; ` – Valentin Stoykov Jan 30 '17 at 17:33
  • I had problems to write code with multiple lines in comments. Is this feature disabled? Here is my testing of 404 vs 204 error code: https://github.com/vstoykovbg/nginx.conf-examples/blob/master/favicon.ico.md – Valentin Stoykov Jan 30 '17 at 18:41
  • 1
    This will just result in an error. It's **pointing to a file named `204`**: `*60 open() "/etc/nginx/html204" failed (2: No such file or directory)`. – kaiser Jan 06 '21 at 00:42
3

A simple

location /favicon.ico { return 204; }

would be the easiest.

frlan
  • 6,950
  • 3
  • 31
  • 72
itpp13
  • 444
  • 2
  • 6
  • I want it to return the ico if it exists, though, hence the try_files and setting of a 404 handler to return the 204. – Bryson Aug 21 '14 at 10:22
  • Have you added a location @return_204 .... section then to handle this? when you define a specific event you need to handle this event in a separate block. – itpp13 Aug 21 '14 at 10:28
0

The important bit is that the = and the HTTP status Code need to be one word and there must not be any space between. If you leave a space between, your error.log will fill quickly as 95% of all requests have a favicon.ico of some sort.

The following should be saved for reusability and just included where necessary.

# (i) No need to log presence or absence.
location = /favicon.ico {
  access_log     off;
  log_not_found  off;
  try_files      $uri  =204;
}
kaiser
  • 21,817
  • 17
  • 90
  • 110