Why does my 404 return 200 status code?

Not sure why but all of my error pages respond with a 200. That's feels a little strange to me, the pages exist but shouldn't they have their corresponding status codes? How do I get Nginx to render my 404 pages with a 404 status code?

For example:

▶ curl -I http://example.com/404
HTTP/1.1 200 OK <<--------------------------- WTF! THIS SHOULD BE 404!!
Server: nginx/1.8.0
Date: Tue, 17 Apr 2018 02:24:04 GMT
Content-Type: text/html; charset=UTF-8
...

Here is the relevant part of my config:

server {

listen 80 default_server;

server_name example.com;
root /var/www/example/static;
index index.html;

try_files $uri $uri/ $uri.html =404;

# error pages
error_page 400 =400 /400; # bad request
error_page 401 =401 /401; # unauthorized
error_page 403 =403 /403; # forbidden
error_page 404 =404 /404; # not found
error_page 408 =408 /408; # timeout
error_page 500 502 503 504 =500 /500; # error

} 

In the documentation is states:

... it is possible to change the response code ... using the “=response” syntax

It is true that the page exist but having set an error_page in the config should change that page's status. For example, if you curl Google's 404 you get the correct result:

curl -I https://www.google.com/404
HTTP/2 404  <<--------------------------- Ahhh, much better.
content-type: text/html; charset=UTF-8
referrer-policy: no-referrer
content-length: 1564

I need my 404 page to produce a 404 status code since I redirect to it from other parts of my app. This is fine for humans but bad for machines since a redirect produces a 302 followed by a 200 instead of a 404.


Solution 1:

Configure NGINX to point to that page for genuine 404 errors. Once that’s done, when you want to redirect your app in places just redirect them to a bogus page

A previous answer said it correctly, when you’re pulling your 404 page at it’s genuine place, it will return a 200, because you’ve requested a page that does exist.

Solution 2:

As joeqwerty said in a comment, nginx is correctly returning 200 because you asked for a document that exists. You would only get a 404 if you requested a document that does not exist. Try doing that instead. (And whether such a document exists on some other server is completely irrelevant.)