Chapter 4. Cookies

The HTTP protocol is stateless. This means that every request made must include all the information needed in order for the web server to serve the correct responses (at least, in theory!). In practice, that isn’t how we experience the Web as users. As we browse around a shopping site, the website “remembers” which products we already viewed and which we placed in our basket—we experience our journeys on the Web as connected experiences.

So how does this work? Additional information is being saved and sent with our web requests through the use of cookies. Cookies are just key/value pairs: simple variables that can be stored on the client and sent back to us with future requests. A user’s choice of theme or accessibility settings could be stored, or a cookie could be dropped to record something as simple as whether the user has visited the site before, or dismissed a particular alert message that was shown.

In this chapter we’ll look at how cookies work and how they fit into our existing knowledge of HTTP, then discuss how cookies are used in API design (spoiler alert: they’re not).

Reading and Writing Cookies

Cookies are key/value pairs, as I’ve mentioned, that are sent to the browser along with some other information, such as which paths the cookie is valid for and when it expires. Since PHP is designed to solve “the Web problem,” it has some great features for working with cookies. To set a cookie, use a function helpfully called setcookie():

<?php

setcookie("visited", true);

We can use this approach to show a welcome message to a visitor when he first comes to the site—because without any previous cookies, he won’t have the “visited” cookie set. Once he has received one response from this server, his “visited” cookie will be seen on future requests. In PHP, cookies that arrived with a request can be found in the $_COOKIE superglobal variable. It is an array containing the keys and values of the cookies that were sent with the request. Following the preceding example we could read the cookie and the code would look something like this:

<?php

var_dump($_COOKIE);

// 1st request: array(0) { }

// later requests: array(1) { ["visited"]=> string(1) "1" }

When working with APIs, the same facilities are available to us. When PHP is a server, the techniques of using setcookie and checking for values in $_COOKIE are all that are needed, exactly like when we are working with a standard web application. When consuming external services in PHP, it is possible to send cookie headers with our requests in the usual way.

Making Requests with Cookies

There’s some nice support for sending cookies in PHP’s cURL extension, which has a specific flag for setting cookies rather than just adding headers. With PHP’s cURL extension, it is possible to do something like this:

<?php

$url = "http://requestb.in/example";

$ch = curl_init($url);

curl_setopt($ch, CURLOPT_COOKIE, "visited=true");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
curl_close($ch);

A selection of other options can be set using cookies, as seen when we discussed capturing them into the cookie jar in the code examples in “Cookie Mechanics”. The expiry date is probably the most-used setting. The expiry information is used to let the client know how long this cookie is valid for. After this time, the cookie will expire and not be sent with any later requests. This relies on the client and server clocks being vaguely in sync, which is often not the case. Having exactly matching clocks is rare, and in some cases clients can have their clocks set incorrectly by a number of years, so beware.

The expiry can be set in the past to delete a cookie that is no longer needed. If an expiry has not been set for a cookie, it becomes a “session cookie,” which means that it is valid until the user closes the browser. This is why you should always close your browser on any machine or device that is used by others, even after logging out of your accounts.

Note

Don’t confuse the “session cookie” with the cookies PHP uses to track user sessions within a web application.

Cookies and APIs

It’s very unusual to see a cookie used in APIs, and the reason for this is fundamental to APIs: they are stateless, as was already mentioned. Stateless means that they don’t rely on information that is not part of this request; we don’t follow on from information that went before or rely on a particular setting being in a particular state.

A stateless API cannot, by definition, use sessions either. These rely on information already having been exchanged and stored for a particular journey. Many PHP installations turn on sessions by default but this isn’t appropriate for an API.

Tip

Having a stateless API also enables it to be “idempotent.” Idempotency is the idea that you can repeat a request and achieve the same outcome each time.

One of the big side benefits of writing stateless services is that they scale horizontally really well. If you need more capacity on your API, you can deploy it to more servers, which all sit alongside one another with a load balancer in front to share the traffic between them. Since each incoming request contains all the information needed to process it, it doesn’t matter which server it gets routed to and scaling up becomes easily achievable.

Designing a service this way does mean that we need to find alternative ways to implement some of the patterns we use sessions for in our other PHP applications. This could be:

  • Using an access token or credentials to identify a user and looking up their details on every request rather than storing those in a session.

  • The client needs to send information such as filtering and ordering preferences along with each request rather than expecting the information to already exist.

By making each request self-sufficient, we can scale up our services very flexibly since we don’t rely on other resources.

Get PHP Web Services, 2nd Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.