So I'm using a single entry point found in a previous question of mine: How to include config.php efficiently?
We all know what 404 errors is, so no explanation needed there. However, when using the single entry point index.php?page=pokemon, it doesn't go to the 404 page when trying to access a page that is non-existent. So how can I solve this problem which would make it more user friendly and direct the visitors to my 404 page so they won't see all the PHP errors?
You should output your own error page (you could just include() a .html file, for example), and set the HTTP status code using the header() function:
header("HTTP/1.0 404 Not Found");
Of course, you must set the header before including the error template.
I assume you do sort of an if / elseif or a switch on the variable $page to figure out which page to display, right?
If so, just add an ELSE resp. default: branch which will display a custom error note
to the user if an unexpected value is passed as $page.
HTH
If you’re actually using user187291’s code, alter it like this:
$page = "home";
if (isset($_GET['page'])) {
$page = $_GET['page'];
}
$file = "$page.php";
if (preg_match('/\W/', $file) || !is_file($file)) {
header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found', true, 404);
// print error message
exit;
} else {
include $file;
}
But since you’re using header, you need to make sure that no output has been sent to the client. Otherwise the HTTP header is already sent and you cannot modify it. You can use the output control functions to buffer any output and discard it in case of an error.
Related
I am trying to figure out how to allow PHP index only if it matches the URL I put in, something like this:
Example if you put in URL site.com/myfile.php I want to show message like 404 Error or something
But if you put site.com/myfile.php?=123 to show the page content.
I think it might be considered bad practice to send someone to a 404 when the page that they are accessing does actually exist, it's only a variable that they are missing.
Firstly, I'd expect to see something like
site.com/myfile.php?variablename=123
instead.
If you absolutely wanted to, you could at the top of your file then add a:
if(!isset($_GET['variablename']){
header('location:404.php');
}
Where 404.php is your 404 file that you'd like the user to see.
Hope that helps?
You could run a conditional looking for the request info, i would make it specific like using a ?page_id=123
<?php
if ( $_REQUEST AND isset($_REQUEST['page_id']) )
{
// SHOW PAGE CONTENT
}
else
{
// RETURN 404
}
?>
You would have to test the $_GET parameters.
if (!$_GET) {
echo "404 Error"; //or redirect using header();
} elseif ($_GET['key'] == 'value') {
//code here
}
I see you are using ?=123, I'm not 100% on if that will work, but it's easier (IMO) to have a key=>value association in the URL.
This should be enough for what you need. If there are other requirements let us know.
if(!isset($_GET)){
//do whatever you want to validate the get input provided.
} else {
header("HTTP/1.0 404 Not Found");
}
Well first of all this ?=123 might be an issue because when ?=123 is passed then it should be stored somewhere, it could be like this ?uid=123 and then you retrieve it in a variable through the get method and then check its value and accordingly redirect the user.
You can do something like this
if(isset($_GET['uid']))
{
refresh(to whatever location you want);
}
else
refresh(to some other location);
but if you want the error 404 something then its not possible according to me, because the values will be sent to a page that exists and if the page exists then the server cannot give a "not found" error.
By simply comparing a string.
if (#$_GET['secret'] != 'mysecret'){
header('location: noaccess.php'); //redirect the user to access denied page.
die(); // terminate the script. A
}
// The rest of the page
Or to keep everything in one file:
if ((isset($_GET['secret'])) && ($_GET['secret'] == 'mysecret')){
// Show the page
} else {
// Show an error message
}
site.com/myfile.php?secret=mysecret
if (strstr($_SERVER['REQUEST_URI'],'index.php')) {
header('HTTP/1.0 404 Not Found');
}
Why wont this work? I get a blank page.
Your code is technically correct. If you looked at the headers of that blank page, you'd see a 404 header, and other computers/programs would be able to correctly identify the response as file not found.
Of course, your users are still SOL. Normally, 404s are handled by the web server.
User: Hey, do you have anything for me at this URI webserver?
Webserver: No, I don't, 404! Here's a page to display for 404s.
The problem is, once the web server starts processing the PHP page, it's already passed the point where it would handle a 404
User: Hey, do you have anything for me at this URI webserver?
Webserver: Yes, I do, it's a PHP page. It'll tell you what the response code is
PHP: Hey, OMG 404!!!!!!!
Webserver: Well crap, the 404 page people have already gone home, so I'll just send along whatever PHP gave me
In addition to providing a 404 header, PHP is now responsible for outputting the actual 404 page.
if (strstr($_SERVER['REQUEST_URI'],'index.php')){
header('HTTP/1.0 404 Not Found');
echo "<h1>404 Not Found</h1>";
echo "The page that you have requested could not be found.";
exit();
}
If you look at the last two echo lines, that's where you'll see the content. You can customize it however you want.
That is correct behaviour, it's up to you to create the contents for the 404 page.
The 404 header is used by spiders and download-managers to determine if the file exists.
(A page with a 404 header won't be indexed by google or other search-engines)
Normal users however don't look at http-headers and use the page as a normal page.
For the record, this is the all-case handler:
<?php
header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found");
header("Status: 404 Not Found");
$_SERVER['REDIRECT_STATUS'] = 404;
?> <!-- 404 contents below this line -->
Load default server 404 page, if you have one, e.g. defined for apache:
if(strstr($_SERVER['REQUEST_URI'],'index.php')){
header('HTTP/1.0 404 Not Found');
readfile('404missing.html');
exit();
}
Since php 5.4 you can now do http_response_code(404);
Another solution, based on #Kitet's.
header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found");
header("Status: 404 Not Found");
$_SERVER['REDIRECT_STATUS'] = 404;
//If you don't know which web page is in use, use any page that doesn't exists
$handle = curl_init('http://'. $_SERVER["HTTP_HOST"] .'/404missing.html');
curl_exec($handle);
If you are programming a website that hosted in a server you do not have control, you will not know which file is the "404missing.html". However you can still do this.
In this way, you provided exactly the same outcome of a normal 404 page on the same server. An observer will not be able to distinguish between an existing PHP page returns 404 and a non-existing page.
try with:
header("Status: 404 Not Found");
header('HTTP/1.0 404 Not Found');
Bye!
A little bit shorter version. Suppress odd echo.
if (strstr($_SERVER['REQUEST_URI'],'index.php')){
header('HTTP/1.0 404 Not Found');
exit("<h1>404 Not Found</h1>\nThe page that you have requested could not be found.");
}
if($_SERVER['PHP_SELF'] == '/index.php'){
header('HTTP/1.0 404 Not Found');
echo "<h1>404 Not Found</h1>";
echo "The page that you have requested could not be found.";
die;
}
never simplify the echo statements, and never forget the semi colon like above, also why run a substr on the page, we can easily just run php_self
If you want the server’s default error page to be displayed, you have to handle this in the server.
You're doing it right though it could use some refining. Looks like that's been addressed so let's talk practical application benefits:
An old website of ours that has a large collection of multilingual tech docs was executing this inside an if else conditional:
if (<no file found>){
die("NO FILE HERE");
}
The problem (besides the unhelpful message and bad user experience) being that we generally use a link crawler (in our case integrity) to check out bad links and missing documents. This means that we were getting a perfectly correct 200 no error response telling us that there was a file there. Integrity didn't know that we were expecting a PDF so we had to manually add a 404 header with php. By adding your code above the die (because nothing afterwards would execute and header should always be before any rendered html anyway), integrity (which behaves more or less like a browser) would return a 404 and we would know exactly where to look for missing files. There are more elegant ways of telling the user that there is an error, but by serving a 404 error you are not only notifying browsers and browser-like programs of the error but (I believe-correct me if I'm wrong) are also recording those errors in your server logs where you can easily grep for 404s.
header('HTTP/1.0 404 Not Found');
die("NO FILE HERE");
Try this:
if (strstr($_SERVER['REQUEST_URI'],'index.php')) {
header('HTTP/1.0 404 Not Found');
echo "<head><title>404 Not Found</title></head>";
echo "<h1>Not Found</h1>";
$uri = rtrim(dirname($_SERVER['PHP_SELF']), '/\\');
echo "<p>The requested URL ".$uri." was not found on this server.</p>";
exit();
}
You know, in my website i created something like this:
$uri=$_SERVER['REQUEST_URI'];
$strpos=strpos($uri, '.php');
if ($strpos!==false){
$e404="The page requested by you: "".$_SERVER['REQUEST_URI']."", doesn't exists on this server.";
$maybe=str_replace('.php','',$uri);
$maybe=str_replace('/','',$maybe);
die("<center><h1>404</h1><hr><h3>$e404</h3><h3>Maybe try <a href=$maybe>www.leaveyortexthere.p.ht/$maybe</a>?</center>");
}
i hope it helps you.
I came up to this problem.. I think that redirecting to a non existing link on your server might do the trick ! Because the server would return his 404:
header('Redirect abbb.404.nonexist'); < that doesnt exist for sure
If you want to show the server’s default 404 page, you can load it in a frame like this:
echo '<iframe src="/something-bogus" width="100%" height="100%" frameBorder="0" border="0" scrolling="no"></iframe>';
I havea code that should redirect in case it doesnt have some request parameter set correctly.
if(!is_numeric($_GET['id'])){
header("HTTP/1.0 404 Not Found");
header('Location: '.$url);
exit();
}
Problem is that whenever I check with Firefoxes plugin, live HTTP headers, I see 302 temporary redirect. why is that? why no 404 response is given?
It doesn't make sense to send a Location header with a 404 status code.
Location means "What you asked for is over here"
404 means "I don't have what you asked for"
The two statements are incompatible.
If you want to send a particular human readable explanation of the error, then just output it as you would for any other kind of document. You could include() it if you like. Don't try to redirect to it.
Problem is that whenever I check with Firefoxes plugin, live HTTP
headers, I see 302 temporary redirect. why is that? why no 404
response is given?
Not sure what you want to do here but following will provide your purpose.
if (! is_numeric($_GET['id'])) {
header('Location: ' . $url, true, 404);
exit();
}
You can only send ONE of the headers you are attempting as stated above.
In case of 404 - this will display the error relevant error pages as defined by you're web server config.
To do what you want... you will need to modify the server's 404 from a plain html to a php page and work out what to display from there (you can base on referrer etc).
From within the 'dynamic' 404 page, you can then do you're redirect if required.
I'm creating a PHP CMS and have some system pages like a 404 page, a maintenance page, and an unauthorized access page. When Page A isn't found, the CMS will redirect to the 404 page; if the user doesn't have access to Page B, it will redirect to the unauthorized access page, etc.
I'd like to use the proper status code in the header of each page, but I need clarification on how to handle the header/redirect. Do I put the 404 header on Page A and then redirect to the 404 page or do I put the 404 status on the 404 page itself? Also, if the latter is the correct answer, what kind of redirect should I use to get there, a 301 or a 302?
If a user arrives on page A and that page doesn't exist, then do not redirect : just send a 404 error code from page A -- and, to be nice for your user, an HTML content indicating that the page doesn't exist.
This way, the browser (and it's even more true for crawlers ! ) will know that the page that is not found is page A, and not anything else you'd have tried to redirect to.
Same for other kind of errors, btw : if a specific URL corresponds to an error, then, the error code should be sent from that URL.
Basically, something as simple as this should be enough :
if (page not found) {
header("404 Not Found");
echo "some nice message that says the page doesn't exist";
die;
}
(Well, you could output something nicer, of course ; but you get the idea ;-) )
I'm not sure if the redirecting is the best way for doing this. Id rather use some built in functionality that is included into the project.
If the data is not found, do not redirect the user to another page, just send him an error message, like Hey, this site does not exists! Try an other one and so.
And not at the end, you should build into the code, the code-part from the answer of Pascal Martin.
I would do this into a function, and call it from a bootstrap or something with a similar behavior.
function show_error($type="404", $header = true, $die = false)
{
if($header)
header("404 Not Found");
echo file_get_contents($type.'.php');
if($die) die; //
// and so on...
}
I posted this earlier
301 Redirect of Static HTML to Dynamic PHP Page
But have a new idea, and am wondering if there are any issues why I should NOT do this...
If someone tries to go to a dead page on our site like:
(domain)/somepage.html
That now exists here:
(domain)/dynamic.php?id=1
It fails and goes to a custom Error 404 page (/404.php)
If I look at the $_SERVER['REDIRECT_URL'] variable, I can see where they were trying to go. My idea is to add an include at the top of the 404.php page to check this value, and if it's in my list of items to redirect, then to use PHP to do the 301.
Something like this...
// -- php include at top of 404.php page
switch(trim($_SERVER['REDIRECT_URL'])){
case "/oldpage.html" : $location = "/dynamic.php?id=1"; break;
case "/oldpage2.html" : $location = "/dynamic.php?id=2"; break;
}
if(isset($location) && trim($location) != ''){
header ('HTTP/1.1 301 Moved Permanently');
header ('Location: '.$location);
exit(0);
}
// -- end of php include
This gives me a single point to enter in all the links I see in the google webmaster tools that are in blog entries, etc. that are now dead.
Thanks
Well, yes. 301, accompanied by a Location header, is the proper response for a request that you can positively identify as being moved.