Because HTTP is a client-server protocol, an HTTP session consists of three phases:
- The client establishes a TCP connection (or the appropriate connection if the transport layer is not TCP).
- The client sends its request and then waits for the answer.
- The server processes the request and sends back its answer, containing a status code and the appropriate data.
Starting with HTTP/1.1, the connection is no longer closed after the third phase, as the client is allowed to issue another request at this point: the second and third phases can therefore be done several times.
Establishing a connection
Because HTTP is a client-server protocol, it always is the client that establishes the connection. Opening a connection in HTTP really is establishing a connection in the underlying transport layer, usually TCP.
With TCP, the default port for an HTTP server on a computer is port 80, though others are often used, like 8000 or 8080. The URL of a page to fetch contains both the domain name and the port number, though the latter can be omitted if it is 80.
Sending a client request
Once the connection is established, the user-agent can send its request. (A user-agent is typically a web browser, but need not be.) A client request consists of text directives, separated by CRLF (carriage return, followed by line feed), divided in three blocks:
- The first line contains a request method followed by its parameters:
- the path of the document, i.e., an absolute URL without the protocol and the domain name
- the HTTP protocol version used
- The subsequent lines each represent a specific HTTP header, giving the server some information about what kind of data is appropriate (e.g., what language, what MIME types) or some data altering its behavior (e.g., not sending an answer if it is already cached). These HTTP headers form a block that ends with an empty line.
- The final block is the optional data block, which contains further data and is mainly used by the POST method.
Example requests
Fetching the root page of developer.mozilla.org, i.e. https://developer.mozilla.org/, and telling the server that the user-agent would prefer the page in French, if possible:
GET / HTTP/1.1 Host: developer.mozilla.org Accept-Language: fr
Note the final empty line, separating the data block from the headers block. As there is no Content-Length:
HTTP header, the data block is empty and the server can process the request as soon as it receives the empty line marking the end of the headers.
Sending the result of a form:
POST /contact_form.php HTTP/1.1 Host: developer.mozilla.org Content-Length: 64 Content-Type: application/x-www-form-urlencoded name=Joe%20User&request=Send%20me%20one%20of%20your%20catalogue
Structure of a server response
After the connected agent has sent its request, the web server handles it, and finally sends a response back. Similarly to a client request, a server response is formed of text directives, separated by CRLF, though divided in three different blocks:
- The first line, the status line, consists of an acknowledgment of the HTTP version used followed by a status request (and its meaning in human-readable text).
- The subsequent lines each represent a specific HTTP header giving the client some information about the data sent (e.g., type, data size, compression algorithm used, hints about caching). Similarly to the block of HTTP headers for a client request, these HTTP headers form a block that ends with an empty line.
- The final block is the data block, which contains the data (if any).
Example responses
Successful reception of a web page
HTTP/1.1 200 OK Date: Sat, 09 Oct 2010 14:28:02 GMT Server: Apache Last-Modified: Tue, 01 Dec 2009 20:18:22 GMT ETag: "51142bc1-7449-479b075b2891b" Accept-Ranges: bytes Content-Length: 29769 Content-Type: text/html <!DOCTYPE html... (here comes the 29769 bytes of the requested web page)
Notification that the requested resource has been permanently moved
HTTP/1.1 301 Moved Permanently Server: Apache/2.2.3 (Red Hat) Content-Type: text/html; charset=iso-8859-1 Date: Sat, 09 Oct 2010 14:30:24 GMT Location: https://developer.mozilla.org/ (this is the new link to the resource; it is expected that the user-agent will fetch it) Keep-Alive: timeout=15, max=98 Accept-Ranges: bytes Via: Moz-Cache-zlb05 Connection: Keep-Alive X-Cache-Info: caching X-Cache-Info: caching Content-Length: 325 (the content contains a default page to display if the user-agent is not able to follow the link) <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>301 Moved Permanently</title> </head><body> <h1>Moved Permanently</h1> <p>The document has moved <a href="https://developer.mozilla.org/">here</a>.</p> <hr> <address>Apache/2.2.3 (Red Hat) Server at developer.mozilla.org Port 80</address> </body></html>
Notification that the requested resource doesn't exist
HTTP/1.1 404 Not Found Date: Sat, 09 Oct 2010 14:33:02 GMT Server: Apache Last-Modified: Tue, 01 May 2007 14:24:39 GMT ETag: "499fd34e-29ec-42f695ca96761;48fe7523cfcc1" Accept-Ranges: bytes Content-Length: 10732 Content-Type: text/html <!DOCTYPE html... (contains a site-customized page helping the user to find the missing resource)
Persistent connections
Persistent connections were introduced in HTTP/1.1. They allow transmitting several requests on the same TCP connection (or on the specific connected transport layer if the HTTP is not built upon TCP/IP). This has several advantages:
- Because the connection can be reused, requests can be pipelined to save part of the connection latency.
- By opening and closing fewer TCP connections, CPU time is saved.
- Network congestion is diminished by lowering the total amount of TCP packets (fewer opening and closing TCP packets).
- The TCP stack has more time to detect network congestion and to adapt its sending and receiving windows.
- HTTP is more adaptive: the cost for trying a feature is considerably lowered as an error response no longer leads to closing the connection.