Showing error pages when sending header with header() function - php

I want to send some response codes in response (what else?) to various conditions.
The header is being sent - I tripped over the various errors you can make using header(), such as having output before the call before. I figured out those sort of issues, for instance, I now use ob_start() and ob_clean() before the header() function call.
Now I need to understand why my browser/server/whatever is not showing me an error page.
Here's the HTML page which I'm using for testing:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en"><head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<title>Header Testing</title>
</head>
<body>
<?php
error_reporting(E_ALL);
ini_set('display_errors', '1');
ob_start();
ob_clean();
header("HTTP/1.1 403 - Forbidden", true, 403); // I get the same results with or without "true, 403"
ob_flush();
?>
Here's the header from the access log:
127.0.0.1 - - [11/Feb/2012:19:14:35 -0600] "POST /commentprocessing.php HTTP/1.1" 403 266 "http://127.0.0.1/submitcomments.php" "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.24) Gecko/20111103 Firefox/3.6.24 ( .NET CLR 3.5.30729; .NET4.0C)"
Here is the HTML source:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en"><head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<title>Header Testing</title>
</head>
<body>
</body></html>
That is exactly what I'd get if I removed out the PHP code from the test page.
Is there any way to have an "error" page display automatically based on the return code in the header?
I am running Abyss server locally for this sort of testing. I have a custom error page defined in Abyss for 403 errors and I've checked that it is spelled correctly in the Abyss setup and the page actually exists.
That page is not being displayed for the header with the 403 response code - which seems to be sent properly since it shows in the access log.
Could this be an issue with my using Abyss locally and not the server of my hosting company?
Any suggestions?
EDIT***
tftd,
If what you said is true, that the server is ignoring my code, why is it logged in the access log with the code I specified?
And, if what you said about being unable to change the response code, why even have the header() statement OR why does not the documentation clearly point out that such as things as using ob_start() and ob_clean() won't resolve get around it.
I've see, in more than one place, references to using ob_start() and ob_clean() to delete generated output so that the header() call will work.
heera,
Thank you, at least for showing me that material can be placed above the doctype statement and still be effective. I would not have thought that would work. So, thank you for that.
However, your example merely outputs exactly what would be output if you stripped out all of the PHP and had just the HTML.
I have removed your onload call to eliminate the 'function not defined' error which would have occurred since you did not include a script containing the referenced function.
The following will produce the same output as your example:
<!DOCTYPE html>
<html>
<head></head>
<body>
This is some text
</body>
</html>
Here's your example, which produces the same output as the straight HTML above.
<?php ob_start();?>
<!DOCTYPE html>
<html> <head></head>>
<body>
This is some text
</body>></html>
<?php
$ob=ob_get_clean();
echo $ob;
ob_end_flush(); ?>
You take a convoluted journey to the same output.
Also, why get the contents of the buffer and turn around and echo it out? What does that demonstrate other than a call to ob_get_clean() returns the contents of the buffer, erases it, and, unlike ob_clean(), deletes the buffer and if you want to send the output you just erased, you have to use ob_get_clean() and save it and then use echo to write it out.
Doesn't that just demonstrate that you had better do something to save the contents of the buffer, if you want to output, before calling a clean function?
And, ob_end_flush() is documented, everywhere I've encountered it, as being automatically called went the script/page finishes. Why demonstrate something that happens automatically, unless you were showing that with our with out a flush call, of one type or another, results in the same output, provided additional out is not created after the flush call.
Seems like your ob_end_clean() call doesn't demonstrate anything at all, hmmm, or does it?
So, why generate output, get it from the buffer, erase and delete the buffer, and then output the contents you saved? What exactly, does that demonstrate? How to do something simple in a convoluted, strange way?
Now, if you wanted to demonstrate the difference the placement of the ob_start() makes on the output and that ob_clean() deletes previous output, why not start with an example like this:
<?php ob_start();?>
<!DOCTYPE html>
<html>
<head></head>
<body>
This is some text
</body>
</html>
<?php
ob_clean(); // erase output buffer
echo "It was the best of times, it was the worst of times."
?>
The only output from that would be
It was the best of times, it was the worst of times.
If you comment out the ob_clean() call:
<?php ob_start();?>
<!DOCTYPE html>
<html>
<head></head>
<body>
This is some text
</body>
</html>
<?php
//ob_clean(); // erase output buffer
echo "It was the best of times, it was the worst of times."
?>
The output is now:
<!DOCTYPE html>
<html>
<head></head>
<body>
This is some text
</body>
</html>
This is some textIt was the best of times, it was the worst of times.
If you take my original example and move the ob_start() down into the second piece PHP code, like this:
<!DOCTYPE html>
<html>
<head></head>
<body>
This is some text
</body>
</html>
<?php
ob_start();
ob_clean(); // erase output buffer
echo "It was the best of times, it was the worst of times."
?>
The output is:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
This is some text
</body>
</html>
This is some text It was the best of times, it was the worst of times.
Those are the examples I would provide to show the effect of the placement of the ob_start() and ob_clean() calls.
Again your example does exactly what the HTML would do were the PHP not there.
If you were saying that you must use ob_start, ob_get_clean(), echo, and ob_end_flush() to produce output - well, I would expect that from a programmer who only knew about ob_get_clean() and ob_end_flush().
I'd expect that from a programmer who, for some reason, thought he or she had to take charge to get the output to the user; that they had to take the buffer contents and use echo to send it to the user.
I simply don't understand why your wrote that example as you did or what, besides placement of the ob_start(), you were trying to demonstrate.
As for the "real world" - in the real world programmers are expected to understand the language features they use and any alternatives to them. They are expected to understand concepts - such as PHP automatically sending any generated output without the programmer having to call a function to get it to the user.
You called my use of buffering wrong. Well, it was, as regards the placement of the ob_sat() call, but everything else is just fine.
If you had posted your example in a question of some sort, my reply would have been -
There is absolutely no need to use an PHP to achieve what you are tyring to do. Take out the PHP and use the straight HTML - the output will be the same.
I'm sorry, but that example, except for the ob_start placement, demonstrates nothing but a strange and convo9luted way to get a HTML to a user.
Perhaps you just didn't take the time to consider the best example to use, after, first deciding what the example was to demonstrate.
If we ignore that fact that the example does nothing that the straight HTML does and it goes about outputting the buffer in a convoluted way, all your example did was set me straight on one thing - you can put something before the doctype and it will be "processed. And I thank you for pointing that out to me.
mc_kennedy,
I read the page you pointed me at but I don't think that applies since the first line of output does no start with HTTP/, as the page specifies.
I'm basing that on what I see in the source view window in my browser. The first line is either the doctype or a
To everyone in general --
It seems that what is being said, by some people, is that you have to have the header() call at the very top of the file and that will allow you to send response codes correctly.
Well, I tried that, with the PHP at the very top and followed by standard HTML, and I don't see any difference.
Am I wrong is thinking that a server will react differently to, say, a 200 than to a 403?
Do I have this all wrong and what I'm expecting - to have the server react, somehow, to the 403 or 500 error - is simply something that does not exist?
If the approach I was using would cause the header() call to be ignored, why does the log show the code I was sending?
I now understand that I should generate the error pages myself, I suspected (well, more than suspected, more like figured that was required.)
But am I expecting a server to react to different responses codes in different ways and this simply does not happen?
Bob

The header() function only alters the existing headers which are sent by your web server.
In your case you can't alter the status. By opening http://localhost/index.php you're sending a request to Abyss, which searches for index.php. If it finds the file - it opens/executes it. And because your file actually exists Abyss/Apache/Nginx will act if you're sending Status: 200.
Even if you send header('Status: 403'); the server will not honor it.
I'm not sure if there's an option to override the server's response the way you want it but with apache,nginx you can't do this.
Edit:
As #Alex Lunix said - you can redirect the user to the error page via
header("Location: path/to/your/error/page");

You might want to check how your Abyss server is treating your PHP script. As the log entry is indicating you are sending a 403 response, the server is probably treating the script as an NPH script and thus sending the output, headers included, directly to the browser with no other actions (such as checking if it should go to the configured 403 page). See http://www.aprelium.com/data/doc/2/abyssws-win-doc-html/cgiinternals.html for more details.

Addition to other answers your use of object buffering is wrong, here's a simple example of that
<?php ob_start();?>
<!DOCTYPE html>
<html>
<head></head>
<body onload="initialize()">
This is some text
</body>
</html>
<?php
$ob=ob_get_clean();
echo $ob;
ob_end_flush();
?>
In real world you have to use it differently, it's just an example.

Sending the response code in PHP is not supposed to also forward them to the error page.
Use header("Location: /error/page/url"); to forward them to the page, and if your error pages already send the response code you don't need to send it before forwarding them.
And the problem with the headers already sent thing is due to have already sent content, headers need to be sent before all other content. So placing it above the html would fix that.
<?php
if(Condition for 403){
header("HTTP/1.1 403 - Forbidden", true, 403);//Tell the user that this page is forbidden (not necessary if /error/file/ sends response)
header("Location: /error/file/"); //Forward user to your error page
exit; //Used to prevent php from executing further in the script
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en"><head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<title>Header Testing</title>
</head>
<body>
EDIT:
The reason you place it at the top is so that they send before any output (which is what output buffering would do, but that adds unnecessary code). Sending the response code tells the user the nature of the page, if you were writing a 404 error page, then you would send a 404 response. If on this page you want to 403, you need to forward them to your 403 page using the Location header.

Related

What is wrong with this simple html/PHP form? It works when testing locally but fails on the actual server

I want to add a “send message” form to an existing website. I found this tutorial:
PHP Contact Form
I reviewed the code in the tutorial, learned how it worked, and then programmed it. I got it up and running and it passed all my tests, running it locally on my PC. It works perfectly.
Then I put it on a server as part of an existing website. It failed. A click on the Submit button clears the screen and the form is lost to view. No error messages. Nothing.
Both XAMPP and the actual server are running PHP version 8.1.12.
It fails on this line of PHP code: header('Location: contact.php', true, 303);
I have spent considerable time debugging this, learning more about PHP, following advice found here on Stack Overflow, and I read the PHP documentation about function header(). I took took two LinkedIn Learning classes on PHP. I cannot figure out what is wrong.
Then I reduced the problem to this simple code, making it as simple as possible, a form with a submit button only. It has the same problem as the complete form.
Here is my test code:
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Contact</title>
</head>
<?php
session_start();
$request_method = strtoupper($_SERVER['REQUEST_METHOD']);
if ($request_method === 'GET'){
?><form action="for_stack_overflow.php" method="post">
<button type="submit">Send Message</button>
</form>
<?php
}
elseif ($request_method === 'POST'){
header('Location: for_stack_overflow.php', true, 303);
exit;
}
?></html>
This simple html/php code has the same problem as my full up form: upon clicking the submit button, the screen is cleared and the form, only a single button, is gone. The form does not work.
I removed all indentation on purpose, because I learned that a common problem is that unseen whitespace causes failures of the PHP function header().
This program (and my complete form) each:
work perfectly when testing it locally on my PC;
fail when running on the real server, on my website hosting account.
I have exhausted all my remedies to solve this problem.
What is wrong? What could be wrong? What is it that I don’t understand?
Move the header() and session_start() calls to before the HTML output.
<?php session_start();
...
?>
<!doctype html>
...
Ref: https://www.php.net/manual/en/function.header.php
Remember that header() must be called before any actual output is
sent, either by normal HTML tags, blank lines in a file, or from PHP.
Ref: https://www.php.net/manual/en/function.session-start.php
Note:
To use cookie-based sessions, session_start() must be called before outputting anything to the browser.

php code not working after header code for downloading files

I have this code and for some reason after this forces downloading file code, the next php code does not run..
$file = "2.jpg";
header("Content-Type:application/force-download");
header("content-disposition:attachment; filename=".$file);
readfile("$file");
echo "hello"
the echo "hello" command for example does not work
Because of the way the HTTP protocol works, the contents of the header - in the reply from the server - are used to determine how to handle the contents of the reply body.
And you are adding headers that tell the browser(or whatever is receiving the reply) to treat the contents as JPG data. All of the contents. So that's what happens. You don't send both the data and some HTML/text to show. Either a page or JPG contents are sent.
If you look at the contents of your downloaded image file it should have "hello" at the end of it.
Update:
If you want to you could use the meta tag to first display a message and then redirect to your download URL. The 2 in the example is the number of seconds to wait before the redirect should happen.
<!doctype html>
<html lang="en">
<head>
<meta http-equiv="refresh" content="2;URL='http://example.com/readfile.php'" />
<title>You will soon be downloading</title>
</head>
<body>
Hello
</body>
</html>
This is the cleanest way. If you don't want to display the message until after the file has finished downloading you can do that as well, but then you'd have to resort to Javascript(AFAIK). And that's a little bit trickier.

codeigniter letter at start of every page

I'm working on a website, which I have temporarily hosted here.
You'll notice the mystery letter 'a' I'm getting at the start of every page. I've gone through all the php files (controllers, views, models) and cannot locate where this letter is coming from. Another curiosity is that all the head content is not residing in the head tags when inspected with Firebug. It appears in the body tags, however it still functions correctly. Are these two issues related?
The only thing I have found from searching the internet is that perhaps some files have been saved as ANSI instead of UTF-8. I've tried 'saving as' all my php files as UTF-8 using my editor, but it is a very slow process. Any help debugging this situation would be appreciated.
EDIT- thanks for your response, #erman-belegu. It doesn't seem to be in any controller. For instance, I've set up a 404 redirect, with its own controller and view. The view looks like this:
<!DOCTYPE html>
<html>
<head>
<meta name="description" content="No Page">
</head>
<body>
<h1>No page dude.</h1>
</body>
</html>
But when inspected with firebug, it looks like this:
<html>
<head></head>
<body>
a
<meta content="No Page" name="description">
<h1>No page dude.</h1>
</body>
</html>
I have encoded everything using UTFCast, and am still experiencing the same issue. Any help welcomed.
You see the head inside the body tag because the mysterious "a" is the first character of your output. It's put inside the body tag by the rendering engine of your browser, or by firebug.
If you find the cause of your "a" - almost certainly some content outside PHP tags - the head will return to normal in firebug.
Searching for the "a" is tricky.. I'm not sure how large your codebase is, but I'd say start by exiting the process right before output is sent. You should see only the "a". Then move the exit step by step untill your "a" disappears, and you'll find it.
Check your controllers at start or maybe any print somewhere. Check all your code on these pages because you print these "a ".
Also use UTF-8 without BOM. But, I think that you print it accidentally and dont think that this happens for any other reasons.

php file only works if file begins with php code

I am new to php and wonder what am I missing about the rules for interleaving html and php code.
This is now the second time I run into a situation where a php file only works if my php tag is at the beginning of the file. This is not the case for all my files. I wonder why that might be.
Here is an example:
My file structured as follows works just fine:
<?php
... my php code
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>Authentication</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div id="container">
</div>
</body>
</html>
But when I move that html block at the top (which is what I want ultimately since I use some echo statements in my php code), and leave only the following at the bottom:
</div>
</body>
</html>
then some portion of the php code do not work. For example, my setcookie function no longer sets a cookie (though it does not error out) while I can still run sql queries or echo statements just fine. I ran into a similar issue with a complete different code taken straight out of a tutorial site: the example would only work if the code started with
Some operations (like writing a cookie) must be performed by PHP before any output is sent to the browser, because those operations involve setting response headers (which are always sent before any other content). That seems to be the problem here.
Per the documentation:
setcookie() defines a cookie to be sent along with the rest of the
HTTP headers. Like other headers, cookies must be sent before any
output from your script (this is a protocol restriction). This
requires that you place calls to this function prior to any output,
including <html> and <head> tags as well as any whitespace.
Give those links a look, they will explain something, and never forget to ask here on stackOverflow
http://www.w3schools.com/php/php_cookies.asp
http://php.net/manual/en/features.cookies.php
http://www.w3schools.com/php/php_sessions.asp
http://it.php.net/manual/en/session.examples.basic.php
Answering your question, you can place the tag practically anywhere in the html code, as long as it's structured correctly.
However, there are some functions in php requires that no output is made before it is executed, like setcookie, setsession, header .. etc.
The output here is either;
a. an echo statement in php code.
b. an html code before the tag that the function is in.
and as for that some code in php doesn't work.
Usually, if you have any problem in your code, that php code doesn't work. So, it's better to check if it syntax correct or not before that.

PHP Export MySQL to CSV - Results showing HTML

I saw a post on this already, but it didn't really provide a solution (that has worked for me at least)...
I have a PHP page that does some basic MySQL queries, the results of which are displayed on the page. I'm using some $_GET and $_SESSION variables throughout this process.
In the same page, I also allow the user to "Export to CSV" (by calling a function). The file returned from the export has the CSV results at the bottom, but also contains the HTML of my page (which calls the function).
Now, at the top of the page I have ob_start() and at the bottom I have ob_flush(), otherwise on page load I will receive some "Cannot modify header..." errors. So, as suggested in the post that I read:
My guess is that you've got some sort of template that generates the same HTML header and footer regardless of the page that is requested. Sometime before the exportCSV function is called, the header is generated.
You don't show the bottom of the output, but I'll bet the footer is there too, since I suspect the flow control will continue on to that code after the function exits."
(http://stackoverflow.com/questions/207019/why-am-i-getting-html-in-my-mysql-export-to-csv/207046)
Does anyone have any ideas on how I can prevent this from happening? Let me know if I should post some of my code and I will...
Thanks!
EDIT:
When calling ob_end_clean() before I call my export function, it gets rid of any html before the CSV. However, I am still getting some HTML closing tags after the CSV results...
fname lname MONTH WeekdayCount WeekendCount
John Doe 8 1 0
John Doe 7 3 2
Jane Smith 7 3 2
</div>
</div>
</div>
</body>
</html>
EDIT:
This issue has been solved by calling exit() after calling the CSV export script.
You could try calling ob_end_clean() before you output the csv data, and it should throw away any output you have already printed as HTML.
You could call exit() after outputting your csv data in order to stop the rest of you page being printed.
This doesn't seem a particularly good approach, can you not have a separate PHP script to output the csv which doesn't include the headers and footers by default?
Without seeing your script it's hard to say what exactly the problem is other than to say that you can't send HTTP headers to the client after you've sent ANY content. This includes white-space. Sometimes you'll have non-printable characters before your opening <?php statement as well. If necessary use a hex editor to find these.
The top of your export.php script should look something like:
<?php
header('Content-Type: text/csv');
...
Is this the case?
I face this problem also and solved it already.
My code is:
<html>
<title> </title>
<body>
<?php
....Code which output MySQL to CSV
?>
</body></html>
Below are example of CSV file which come out with HTML code at top.
<html>
<head>
<meta http-equiv="Content-Language" content="th">
<meta http-equiv="content-Type" content="text/html; charset=window-874">
<meta http-equiv="content-Type" content="text/html; charset=tis-620">
<title> Super Man </title>
</head>
<body bgcolor="#FFFFD4">
<SQL rows resulted>
xx5497 1/7/2015 1:03 SSFTM SSFTVM 35 Condition2
xx5498 1/7/2015 1:04 SSDHN SSDHKN 13 Condition2
xx5499 1/7/2015 1:06 SSFTM SSFTVM 14 Condition2
When running, CSV file got the first 12 lines on the top. It looked so crazy to me. I solved it by moving the PHP code to the top. Then the result is OK. Only SQL results were output to CSV file.
<?php
....Code which output MySQL to CSV
?>
<html>
<title> </title>
<body>
</body></html>

Categories