Everything we do with building websites has a dark underside, and it’s called the HTTP Protocol. Actually, it’s not dark, it’s great as this is what makes all this internet stuff possible. You see when you visit a website and the server sends HTML to you over the internet, there is something that comes first, before any of the HTML even gets to your browser. This is called the HTTP Header and it contains some valuable information about the web session to provide to the Browser. This gets sent before anything else. In fact, it is by the very fact that you tried to visit a website in the first place that this process began. When you go and type your favorite URL into your browser of choice and then hit enter, what do you think happens? Your Browser makes use of the HTTP protocol to send a GET
request to the server in the form of an HTTP Header. So you see all of this is the underpinning of how websites and the internet works, so we’ll need to get a good grasp of how to use this in PHP. Many times people will use a dedicated php http client to handle http. There are tons of functions and approaches to working directly with HTTP and HTTP Headers in PHP, so let’s get right into it!
Is HTTP Evil?
You may have noticed the scary implications that the title of this post assigns to PHP. Actually, HTTP is not all that bad, it may be our friend in fact. It is a bit quirky and tricky at first however, and this is why we must remain vigilant in our learning. One way to really learn about the HTTP protocol is to install something like the Live HTTP Headers add on to Firefox. This gives you the ability to watch all the communication between your web browser and a remote server in real time. It is quite slick actually. If you have Live HTTP Headers installed, you can click Tools->Live HTTP Headers and a new window will open that displays all of the HTTP Headers in a web session. Here is an example of a Request / Response to Twitter.
request
GET / HTTP/1.1
Host: twitter.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Cookie: guest_id=example cookie data
Connection: keep-alive
response
Cache-Control: no-cache, no-store, must-revalidate, pre-check=0, post-check=0
Content-Encoding: gzip
Content-Length: 12361
content-security-policy-report-only: default-src https:; connect-src https:; font-src https: data:; frame-src https: http://*.twimg.com http://itunes.apple.com about: javascript:; frame-ancestors https:; img-src https: data:; media-src https:; object-src https:; script-src ‘unsafe-inline’ ‘unsafe-eval’ about: https:; style-src ‘unsafe-inline’ https:; report-uri;
Content-Type: text/html;charset=utf-8
Date: Thu, 09 Oct 2014 14:36:46 UTC
Expires: Tue, 31 Mar 1981 05:00:00 GMT
Last-Modified: Thu, 09 Oct 2014 14:36:46 GMT
ms: S
Pragma: no-cache
Server: tsa_a
Set-Cookie: _twitter_sess=example session cookie
status: 200 OK
The main thing to note here are the status codes. We can see that Twitter responds back with a 200 OK, which is a way of saying, “Hey – Everything is Awesome”. There are a whole range of status codes that exist to help facilitate communication between client and server. Here is a table of them.
HTTP Code Number |
HTTP Code Meaning |
---|---|
Messages in the 100 range are informational | |
100 | Continue |
101 | Switching Protocol |
Messages in the 200 range indicate success | |
200 | OK |
201 | Created |
202 | Accepted |
203 | Non-Authoritative Information |
204 | No Content |
205 | Reset Content |
206 | Partial Content |
Messages in the 300 range deal with redirection | |
300 | Multiple Choice |
301 | Moved Permanently |
302 | Found |
303 | See Other |
304 | Not Modified |
305 | Use Proxy |
306 | unused |
307 | Temporary Redirect |
308 | Permanent Redirect |
Messages in the 400 range indicate client errors | |
400 | Bad Request |
401 | Unauthorized |
402 | Payment Required |
403 | Forbidden |
404 | Not Found |
405 | Method Not Allowed |
406 | Not Acceptable |
407 | Proxy Authentication Required |
408 | Request Timeout |
409 | Conflict |
410 | Gone |
411 | Length Required |
412 | Precondition Failed |
413 | Request Entity Too Large |
414 | Request-URI Too Long |
415 | Unsupported Media Type |
416 | Requested Range Not Satisfiable |
417 | Expectation Failed |
Messages in the 500 range are server errors | |
500 | Internal Server Error |
501 | Not Implemented |
502 | Bad Gateway |
503 | Service Unavailable |
504 | Gateway Timeout |
505 | HTTP Version Not Supported |
header($string)
Your web server takes care of sending the proper headers to your website visitors depending on the situation. This is something we normally never even think about as it happens automatically and transparently in the background. There are occasions when you the developer may have a need to manually tweak how the headers are presented from your server and in this case, you can make use of the header()
function. Let’s look at some code that would modify the headers.
<?php
header('Content-Type: application/pdf');
header('HTTP/1.1 500 Internal Server Error');
header('HTTP/1.1 404 Not Found');
header('Content-Disposition: attachment; filename="awesome.docx"')
?>
The code above gives examples of how you would send headers for an Adobe PDF document, a Server Error, a not found page, and a downloadable attachment.
Headers Come First!
There is a really super important thing that you need to be aware of with regard to HTTP Headers and that is that they come before all page data. They are first. The reason for this is that the HTTP protocol is giving the users browser a heads up. It’s saying, “Hey, get ready, there is some HTML Data about to be sent your way”. It may be telling it something different, but the key point to know is that the HTTP Protocol enforces this, so we must be aware of it. Any modifications you would like to do to the headers must be made before anything else in your code. If the server begins to send anything, even one measly whitespace character, you will encounter the oh so familiar Warning: Cannot modify header information – headers already sent (output started at file:line).
Redirects In PHP
It is actually not all that common to be tinkering with headers in PHP, but there is a use case that is used all the time and has real value. That use case would be Page Redirection. Page Redirection is wonderful for instances such as when a user logs into your site, maybe you’d like them to be redirected right to a key piece of information on a given page. You can do that with Page Redirection. The popular PHP frameworks all have this functionality in some easy to use methods, but we can do this right in native PHP as well. Let’s see how.
302 Redirect
In the HTTP protocol we use a 302 Redirect to make a Page Redirect happen. There are two parts to this.
- HTTP 1.1/ 302 Found
- Location: path
The first part says, “Hey you found me” and the second part says, “but you need to go to this different location now”. Now when we do this in PHP it would look something like this. Let’s say we’re redirecting someone to the login page.
header('Location: login.php');
You may be wondering why we didn’t have to manually set the 302 portion of the redirect. This is because PHP is intelligent enough to do that automatically for you, so all you need to do is provide the location to redirect to, and bingo. Pay attention to the syntax when using this approach as it is notoriously finicky. The L in Location must be capitalized, followed by all lowercase. The double colon must be followed by exactly one whitespace character. Then you can provide the path to redirect to. What’s interesting is that the browser actually immediately makes a second GET request once it sees that 302 Redirect. One other point to keep in mind is that once the redirect happens in PHP, you really don’t want to send any other data so often you’ll see an exit statement right after the command.
<?php
header('Location: login.php');
exit;
?>
You could even put this in a dedicated redirect function if you like. This is what it might look like.
<?php
function redirect($new_page) {
header('Location: ' . $new_page);
exit;
}
?>
Now if you want to redirect somebody to Yahoo, you can just do this and send them on their way.
<?php
function redirect($new_page) {
header('Location: ' . $new_page);
exit;
}
redirect('http://yahoo.com');
?>
The HTTP Header Redirect Conclusion
In this episode of our PHP Tutorial Series we learned all about the HTTP Protocol and how it works with PHP. It may have started out scary, but now that we understand how it works, it’s not so scary after all. The takeaways are that HTTP Headers always come first in web based communications and each message has a status code associated with it. Our handy table of status codes gives us an idea of which ones are informational, success, redirects, client errors, or server errors. It will come in handy to at least know the basic associations of the 100s, 200s, 300s, 400s, and 500s.