4

I'm currently moving to an nginx server. I tried putting this in my 404 ErrorDocument named 404.php:

<?php
    header("Location: http://www.google.com/");
?>

If I now try to access http://mydomain.com/404.php, this works as expected: It redirects me to Google. But once I try to access http://mydomain.com/iDoNotExist, the 404 ErrorDocument is shown without redirecting me to Google.

This behavior seems weird to me. Is there any way I can fix this?

Edit:

Here's what curling the page gives me:

curl -I mydomain.com/404.php

HTTP/1.1 302 Moved Temporarily
Server: nginx/1.2.1
Date: Sun, 05 Jan 2014 11:31:15 GMT
Content-Type: text/html
Connection: keep-alive
X-Powered-By: PHP/5.4.4-14+deb7u7
Location: http://google.com/

curl -I mydomain.com/iDoNotExist

HTTP/1.1 404 Not Found
Server: nginx/1.2.1
Date: Sun, 05 Jan 2014 11:33:49 GMT
Content-Type: text/html
Connection: keep-alive
X-Powered-By: PHP/5.4.4-14+deb7u7
Location: http://google.com/

Edit 2:

As asked by hakre, I'm coming from an Apache setup, and yes, I'm using Chromium. As for Apache, this used to work for all the Gecko and Webkit browsers and even console-based browsers such as Lynx. It would probably have worked for Internet Explorer as well, but I've never tried that (no Windows around here, phew).

9
  • No, I disagree. Valid configuration files can be a matter of good programming, regardless of the purpose they serve. Neither "look into the source" nor "read the manual" is constructive advice to any kind of problem where you assume that this (and lots of googling) hasn't already been tried. Anyway, accessing the site from http://mydomain.com/iDoNotExist will trigger the execution of the PHP code in my ErrorDocument (I just echoed a string to make sure). Commented Jan 5, 2014 at 11:22
  • Then look with curl (or another HTTP client that is able to show) which headers are received by the client. Please add those response headers to your question. Commented Jan 5, 2014 at 11:26
  • I already did, and it matches with what my browser shows me as well. Curling http://mydomain.com/404.php will alter the HTTP status code to 302, curling http://mydomain.com/iDoNotExist won't. I'll attach the results to my original post (just in case you want to see). Commented Jan 5, 2014 at 11:30
  • That's clear because it's a 404 page, so you've got the 404 status code. The meaning of the Location response header is based on response status code. This is documented here: tools.ietf.org/search/rfc2616#section-14.30 - So the behavior of your browser is not weird but just standard, just following the HTTP specs. Probably weird is your expectation that the browser should do something that has no place in the protocol. ;) Commented Jan 5, 2014 at 11:33
  • I guessed in my title edit you've used Chrome here as browser, but you should write down which browser you're testing with actually as this is related to browser. Also you should write from which configuration you're moving from and tell whether or not this did work before the move (and with which browser/server) or not. Commented Jan 5, 2014 at 11:42

1 Answer 1

5

The behavior of your browser is correct. The Location: response header has no meaning for status code 404 (compare 14.30 Location and 10.4 Client Error 4xx).

Therefore the response's hypertext body is displayed in the browser - as specified by the HTTP specs for code 404 (see 10.4.5 404 Not Found).


To allow changing the HTTP response code from 404 to a different one (e.g. 302 for the temporary redirect), you have to configure Nginx error_page directive accordingly:

error_page   404 = /404.php;

Without the equal sign (=), it is not possible to change the status code with your PHP script:

header("Location: http://google.com"); # PHP sets 302 status code

SAPI: php5-fpm

Sign up to request clarification or add additional context in comments.

6 Comments

Okay, I see. But consider the following change: header("Location: http://www.google.com/", true, 302); Putting this in 404.php won't alter my 404 status code either. So accessing http://mydomain.com/iDoNotExist will still be the 404 page. Is there anything I'm missing? Edit: Sorry, the whole formatting got a little broken.
@Chiru: For the server used (Nginx) PHP it's SAPI used (no idea how you configured it) requires knowledge how to set the response code in PHP so that the webserver returns it. Which SAPI do you use? Also Nginx must allow to overwrite that status code in this specific 404 error situation I assume. It's probably better to not use 404 handler here, but just do pass all non-existing requests to your script to turn them into a 302.
As for the SAPI, I'm using php5-fpm in my setup. I just tried fiddling arround with the 302 I've used in the above code snippet and changed it to various other status codes. Overwriting the HTTP status code seems to be allowed when I try to access the file directly (according to curl replies).
This would then signal that perhaps Nginx prevents that. I'm not so fit with Nginx, but this is probably documented. It might be helpful you add your nginx configuration for that error page as well to the question. And since PHP 5.4 there is: http_response_code()
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.