A conditional request is an important feature of the HTTP protocol, as it allows the manipulation of the response that the server will send according to what the client wants. This means convenience and agility in HTTP communications. When this process is done at the edge, there is a significant improvement from an architectural point of view and, consequently, an increase in the scalability of services and in the companies' revenue.
HTTP Conditional Requests
Making processes more practical and improving product performance are two of the requirements for anyone working with technology, both from developers and business sides. It wouldn't be different when it comes to trying to optimize the basis of communication networks, the HTTP protocol – and one way to optimize the communication is using conditional requests.
With conditional requests it's possible to tell the server what you want to obtain in the response of an HTTP communication – which means saving time and bandwidth, practicality and agility.
Conditional requests are, therefore, a bit different from common requests, because they operate according to the value specified in certain headers. That is, this value defines the action that will be performed on the request.
Why Use a Conditional Request?
There are many reasons, but some of them are: to validate the contents of a cache, to check the integrity of a document, to resume a download, or to avoid missing updates when sending or modifying a document on the server.
What Happens In a Conditional Request?
What happens is that the result of a connection made with this type of request can be changed when comparing the resources being checked with the value of a validator.
How Does The Behavior That The Client Expects From The Server Is Met?
It will happen according to the method and the preconditional header used in the request.
Before we understand how a conditional request works, let's see what some of the elements that are part of this process are about.
The precondition of a request is defined by a header, and its result can be different depending on the validation or not of this precondition. The headers then give directives for this communication process, and some are used to check the cache update status, such as
, and others to specify preconditions for using cache, or for storing revalidation, as the
The preconditional directives can assign conditions only to the server, to the general state of the resource on the target, or to a group of resources. These preconditions are given by conditional requests, which are based on validators – metadata used by the client and the server to verify what is being requested.
The validation process happens as follows: the client sends the metadata to the server, and the server checks if what was requested by the client is valid or not. If the validation is inconsistent and the server is unable to select the appropriate representation, the precondition is evaluated as false without affecting the connection.
The preconditions are based on the general state of the destination resource (its current value), or on the state of the representation obtained previously (the previous value). Furthermore, a resource can have not just one, but several current representations, each one having a state of its own.
We've seen that the term resource is recurrent, and it's an important element of the conditional requests, but what is it exactly? First, it's important to know that the resource is the target of a conditional HTTP request – that is, the resource is the object to be searched, and it will give the information that this type of request wants.
In addition, a resource doesn't have a specific format – it can be an image, an electronic document, graphics, a source of information or anything you want to search on the internet – and its main purpose is to be used by the request as a type of interface, an element to allow interaction with representations of the resource through a network. Thus, the term resource is used in a general sense for anything that can be identified by a URI.
To identify a resource, the HTTP request uses a URI (Uniform Resource Identifier), a sequence of characters – a string – that names or identifies a resource. There are two types of URI: one of them can be classified as a locator (URL, acronym for Uniform Resource Locator) and the other as a name (URN, Uniform Resource Name), or both. Generally speaking, the URL is the address of a resource, while the URN defines its identity, it's a unique and never-changing name.
Examples of URIs:
When the client makes a request, it sends the destination URI, and when the server receives that request, it remakes a URI request that effectively meets the destination resource.
As we mentioned before, a conditional request is based on the state of a resource's representation. But what is a representation then? A representation is the information used to check the state of a particular resource, which can be current or past, in a format that can be readily communicated through the protocol, and consists of a set of representation metadata and a flow of potentially unlimited representational data.
In this process, an origin server may receive or be able to generate multiple representations that reflect the current state of a resource. In these cases, the origin server uses an algorithm to select one of these representations as most applicable to a given request, usually based on the content of the conditional request negotiation. The selected representation is used to provide data and metadata to evaluate conditional requests.
Validators: Checking the Resource
To check if the stored resource of a server is in line with the specific version that the client wants, conditional request headers will do this verification. To make it happen, the conditional request indicates the resource version through a value, also known as validator or metadata.
There are two types of validators: modification dates and opaque entity tag. More specifically, the Last Modified header indicates the date and time the resource was modified, and the ETag header, also known as opaque entity tag, represents the resource version.
The Last-Modified header is sent by the origin server and indicates, through a timestamp, the date and time when the selected resource was last modified. This allows a recipient to make an accurate assessment of the representation's modification time, especially if the representation changes around the time the response is generated. If there's no modification, the server sends a
response to the browser, and the cached resource is used.
304 Not Modified
The ETag header (short for entity tag) in a response shows the current ETag of the representation selected in the request. An ETag is an opaque validator – that is, validators in a proprietary format that typically contain some identifier to information in a server's persistent storage – to differentiate the different representations of the same resource.
An ETag represents a requested resource and is a string of ASCII characters enclosed in quotes, as in
. If you want to indicate that this is a weak validation, you must insert the prefix W/ before the characters, as in
Types of Validation
The validation is the return of a preconditional request, the way to know if what was requested for the server by the client is valid or not. The process of verifying versions of the same resource can occur in two ways:
The strong validation verifies if the identity of the compared resources is the same. It occurs when the client needs the resource identity (byte-to-byte identity).
The weak validation checks if the content of the compared resources is the same. It occurs when the client only needs to determine if two resources have the same content.
By default, the HTTP protocol uses strong validation, and specifies when to use weak validation.
Conditional Requests Headers
The headers used to define the conditions in a request are:
It's used to check if the ETag of the resources, of the client and the origin server, are the same. It's usually used with the GET method. The client using this precondition wants to prevent the method from being applied if there is any change in the representation data.
Note: An asterisk is used as a special value to represent any resource.
Example of a conditional request with an
It's used to check if there have been changes in the resource. It's normally used with GET method when the objective is to enable updates of information that are cached efficiently, in which transmission is minimally overloaded.
For example, when the client wants to update one or more stored resources that have ETags, it must make a request with the GET method and use an If-None-Match header that contains a list of these ETags. This allows the recipient servers to send a 304 response (Not Modified) to indicate when one of those stored resources matches the selected representation.
Example of a conditional request with an
It's used with GET or HEAD methods to allow updates of a representation that is cached but doesn't have an ETag. Another function of this header is to limit the scope of a web traversal to features that have recently changed. Thus, the If-Modified-Since header tells the server to send back the requested resource only if it was last modified after the given date. If the resource hasn't been modified since then, the response will be 304 with no response body. If the resource has been modified, the answer will be 200 OK with the new version of the resource.
Example of a conditional request with an
It's used when the client wants the server to send back the requested resource only if it was last modified on the given date or before it. The If-Unmodified-Since header is usually used with state change methods (such as POST, PUT, and DELETE) to avoid lost updates, that is, accidental replacements when multiple clients act at the same time on a resource that doesn't provide ETags with their representations. If the precondition fails, the request is restarted without the precondition. It can also be used to cancel an order if the selected representation doesn't match an already stored (or partially stored) one from a previous order.
Example of a conditional request with
It's used when a client has a partial copy of a representation and wants to have an up-to-date copy of the entire representation. It's usually used with the GET method and can be used with the If-Unmodified-Since and If-Match headers, one or both of them. For example, under normal conditions, if the representation was modified, the precondition fails and the client would have to make another request asking for the entire representation, and not just the requested range. With If-Range, if the representation hasn't been changed, the server sends the requested parts of the desired range, but if the representation has changed, the server sends the complete representation. Thus, the If-Range header allows a client to jump to the second request without having to make a new one.
Example of a conditional request with an
What Is The Best Way To Have Control and Agility In HTTP Requests?
At Azion clients can determine what they want from the server in a fast, practical, and agile way: with our Edge Functions.
Using our Edge Functions, you can create custom request and response rules or choose from pre-built functions, such as A/B tests, security tokens, or massive redirect. When triggered, the function runs in milliseconds on the edge node closest to the end user.
You can use functions to handle HTTP in the following request and response phases:
- as soon as a user’s requests are received in the edge node;
- before the edge node forwards the request to the origin;
- as soon as the edge node gets the response from the origin;
- before the edge node forwards the response to the user.
- inspect cookies to rewrite URLs to different versions of a site for A/B testing;
- send different objects to your users based on the user-agent header, which contains information about the device that submitted the request. For example, you can send images in different resolutions to users based on their devices;
- inspect headers or authorized tokens, inserting a corresponding header and allowing access control before forwarding a request to the origin;
- add, delete, and modify headers and rewrite the URL path to direct users to different cache objects;
- generate new HTTP responses to do things like redirect unauthenticated users to login pages, or create and deliver static web pages right from the edge.
As Edge Functions runs on our global edge network, it automatically scales without the need for management or provisioning resources. Instead, you only pay when the code runs, eliminating upfront costs and avoiding wasted resources from over-provisioned servers.
In other words, with Edge Functions you guarantee speed, practicality and agility, both for your developer and your client. And the result of all these benefits is the maximization of your revenue.
To learn more about this or other products, contact our sales team here.