5

I am trying to send both when a database result is empty (it's a product page).

My code I am using now, which works:

    header("Status: 404 Not Found");
    include_once("404.html");
    exit;

The code that I tried initially that did not work:

    header("Status: 404 Not Found");
    header("Location: 404.html");
    exit;

With the latter code, I could use either, but not both. In other words, I could send the 404 header and see it show up in Wireshark, OR I could send the Location header and redirect, but if i tried to send both, only the 404 would get sent and the Location header would nor redirect.

I have solved problem with a workable solution, but I would like to know why this is happening.

PHP 5.2 on Linux with FastCGI.

Thanks.

Jazzy
  • 6,029
  • 11
  • 50
  • 74
  • 2
    possible duplicate of [Redirect 404 or just 404 header](http://stackoverflow.com/questions/9709192/redirect-404-or-just-404-header) See also: [Is a “404 redirect” a legitimate redirect?](http://stackoverflow.com/questions/1626411/is-a-404-redirect-a-legitimate-redirect) Basically, it doesn't make sense (although it *can* be done) to send a 404 response when you really mean to redirect (and as an aside, it's extremely annoying to the user because they can't figure out which URL they mistyped). – Wesley Murch May 05 '12 at 22:26
  • I think this is a legit use of 404. The URL example is http:/domain.com/goodproduct will send 200 naturally, but if something else is entered that is an old or invalid product id, http:/domain.com/nonexistentproduct, I want to send a 404 AND redirect to the existing 404 page. I am using a mod_rewrite to send a GET param on a PHP file unless a directory exists, in which case that is served instead. – Jazzy May 05 '12 at 22:35
  • As far as I understand, if the page doesn't exist, 404 is correct. If it used to exist at the current URL but moved somewhere else, 301 is the correct status code. If it did exist at some point but no longer exists, then 410 (Gone) can be appropriate. In any case, you can *display* whatever you want. Is the fact that you're having issues with this not an indicator of any kind that you may be misusing headers? – Wesley Murch May 05 '12 at 22:45
  • I don't think I am misusing them if you look above at what I am trying to accomplish, I am just trying to figure out why I can't send a 404 and then follow it with Location header and have the page redirect. As I mentioned, the Location header just gets ignore whether I place it above or below the 404 header in the code. The reason I want to send a 404 at all is that if a product no longer exists or needs to be removed from the site (but not from the database), I want to send a 404 to tell everyone on the search engine side that it's gone and dislplay the 404 page for humans. – Jazzy May 05 '12 at 23:01

3 Answers3

7

You can't send both because they're mutually exclusive.

According to the docs for header():

The second special case is the "Location:" header. Not only does it send this header back to the browser, but it also returns a REDIRECT (302) status code to the browser unless the 201 or a 3xx status code has already been set.

So sending both would be nonsense. You'd be saying, to the browser, "That document does not exist. Also, the document was moved to the following location". Those are contradictory.

The solution you found is not "a workaround" -- it's the Right Way To Do It™

timdev
  • 61,857
  • 6
  • 82
  • 92
1

The latter code doesn't work because 404.html actually exists on the server. You're sending a 404 status code then redirecting to an existing page, resulting in a 200 (Found) status code.

Herbert
  • 5,698
  • 2
  • 26
  • 34
  • Is that right? When I try the latter code, I am indeed seeing a 404 when I watch HTTP using Wireshark: HTTP 279 HTTP/1.1 404 Not Found – Jazzy May 05 '12 at 22:38
0

In PHP 5.1.6 I happen to have on my test machine the order of header() commands determine which status is returned. So it is possible to return HTTP 404 along with Location header if the status is set after Location:

header("Location: ...");
header("HTTP/1.1 404 Not Found");
stema
  • 90,351
  • 20
  • 107
  • 135
pawel
  • 1