4

I would like to make a php script output like a real 404 page (as set in the Apache ErrorDocument directive) if certain conditions are not met. I'm not sure how I can / if it's possible to access this value from PHP..

if(!@$_SESSION['value']){
 header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found");
 echo $default_page['404'];
 exit();
}
echo 'Welcome to a secret place.';

I understand the ErrorDocument value can be overwritten, but I'm particularly interested in the 'default' value hardcoded by Apache. If it's possible to know the value which is overwitten (eg by a .htaccess file), then that's a bonus :)

http://httpd.apache.org/docs/2.0/mod/core.html#ErrorDocument

edit: to be clear, I'd like to send the content the default 404 page (or 403, etc) of Apache from PHP. If I only use header on its own then nothing is output to the client/user (at least in FF/Chrome, IE has its own built in pages which are shown).

3
  • I think the default page shows up when there is no ErrorDocument set at all. Not sure whether this is possible Commented Jan 31, 2011 at 21:40
  • Many thanks to both mario and RoUS, both answers are correct. A HTTP library is necessary.. which is a shame because I'll never get these libaries installed on the 'budget' hosting I'm using for my current hosting, oh well - a fun experiment. Commented Feb 8, 2011 at 0:28
  • 1
    You might want to double-check; curl may already be built into the version of PHP your host is using. Try creating a file phpinfo.php containing just <?php Header('Content-type: text/html'); phpinfo(); ?>, then navigate to that page and see if Curl is listed. Commented Feb 20, 2011 at 21:08

3 Answers 3

6

The recommended way to set the response code from PHP is as @mario suggested:

Header('Status: 404 Not Found');

If you want to get the body of the page the server would ordinarily provide for a 404, and don't care about the URL getting rewritten in the user's browser, you could use something like:

$uri_404 = 'http://'
    . $_SERVER['HTTP_HOST']
    . ($_SERVER['HTTP_PORT'] ? (':' . $_SERVER['HTTP_PORT']) : '')
    . '/was-nowhere-to-be-seen';
Header("Location: $uri");

(When you're directly frobbing the Location header field, you need to supply a full URI.) The result of this is that the user's browser's will end up pointing to that bogus location, which may not be what you want. (Probably isn't.) So then you could actuall collect the contents of the page yourself and combine the two, in effect:

Header('Status: 404 Not Found');

$uri_404 = 'http://'
    . $_SERVER['HTTP_HOST']
    . ($_SERVER['HTTP_PORT'] ? (':' . $_SERVER['HTTP_PORT']) : '')
    . '/was-nowhere-to-be-seen';
$curl_req = curl_init($uri);
curl_setopt($curl_req, CURLOPT_MUTE, true);
$body = curl_exec($curl_req);
print $body;
curl_close($curl_req);

That should fetch the contents of the 404 page the server reports for the bogus URI, and you can then copy it and use it yourself. This should properly handle any ErrorDocument 404 handler output.

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

1 Comment

Thanks, this also works.. I only had to change the CURLOPT_MUTE const to CURLOPT_RETURNTRANSFER
3
+50

There is no default method for that. But you can always cheat:

header("Status: 404 Not There");

// no worky
#readfile("http://$_SERVER[HTTP_HOST]/non-existant-url");

// doesn't work either (Apache detects the fraud)
#virtual("/non-existant-url");

// otherwise a HTTP class, this one works but is seldomly available
$request = new HttpRequest("http://localhost/error", 1);
$answer = $request->send();
print $answer->getBody();

This triggers a subrequest. Since it's on the local server, I would disregard any bigger performance penalties. But it might be worth to investiage using the Apache/mod_php virtual() function.

Notably this method depends on knowing a certain location of a 404 resource. If there is already url rewriting in place, then another trick is necessary in your .htaccess:

RewriteRule  ^non-existant-url$  error  [E=404,L]

This forces the resource to generate the expected result, thus making the default errordocument available.

7 Comments

I think this is the only way.
This looks promising, although I couldn't get it to work straight away. Will try again in the morning, thanks :)
I still don't get much result from this, there no output
@aland: Obvious oversight. PHPs readfile() and stream wrappers return no content if they encounter a HTTP error. So you would need to use a HTTP library for that. Or is virtual() available on your server?
@aland: No, then that's actually a concludent result. Then as last resort, you have to use one of the HTTP libraries (PEAR or Zend for example), maybe even curl. I've tried PHPs HttpRequest, which works well for that task, but it's not available on most servers.
|
0

Your example seems good. You need to use the php header function to do that:

<?php
header("HTTP/1.0 404 Not Found");
?>

Like that you're saying that this page is a 404, and you can then fill in the contents with what you want

A real 404 is just any piece of code that send's a 404 error code back to the browser, so ErrorDocument or header(..404...) are equivalent in this regard.

Comments

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.