How to Optimize CORS Preflight Requests?
Cross-origin resource sharing (CORS) is a mechanism that allows web applications to access resources from other domains. However, CORS can add latency to requests, especially if the preflight request is required.
The preflight request is an OPTIONS request that is imposed by the browser to the server to check if the request is allowed. This request can add latency because it is an extra round-trip between the browser and the server.
CORS preflight requests can add latency to your API calls, especially for API-heavy applications.
Broadly speaking, CORS preflight requests occur when:
The HTTP request method is not a simple GET, HEAD, or POST request
Custom headers are used
Non-simple content types are used
In these cases, the browser will first send an OPTIONS
request to check if the actual request is allowed. Only if the preflight OPTIONS
request is successful, will the actual request be sent. To know more about Preflight requests, check here.
Why should we focus on optimizing and reducing the time for preflight calls?
The Preflight (OPTIONS) request is often the slowest step in a CORS call because it is an extra round-trip between the browser and the server.
The server has to check the preflight request headers and construct the preflight response, which takes additional server processing. The browser also has to wait for and process, the preflight response before making the actual request.
Preflight responses are not cached by default, so each preflight request has to go through the full roundtrip. Caching preflight responses can significantly improve performance.
Servers typically may be optimized more for actual requests rather than preflight requests, so preflight requests can take longer to handle.
The actual request, once allowed by the preflight, tends to be faster since it does not have to go through as much processing on the server side.
Various ways to avoid or speed up CORS preflight requests
1.Cache preflight responses
The browser can cache preflight responses based on the Access-Control-Max-Age
header sent by the server. This is the most effective way to reduce preflight times. The header specifies the number of seconds that the preflight result can be cached.
For example:
Access-Control-Max-Age: 600
This would cache the preflight results for 10 minutes (600 seconds). This means that subsequent preflight requests within that time window will not need to be sent, saving roundtrip times.
The specific value that you choose will depend on how often your CORS configuration changes and how sensitive your exposed resources are. A higher value means fewer preflight requests but potentially stale configuration. A lower value ensures more up-to-date configuration but at the cost of more preflight requests.
Caching preflight responses can significantly reduce latency by eliminating the need to send a separate preflight request for each request and thus reducing the number of network requests that need to be made.
Note:
The maximum cache time is capped by the browser (Firefox - 24 hours, Chrome - 2 hours)
Setting Access-Control-Max-Age to
-1
disables caching.If no Access-Control-Max-Age header is sent, browsers will use a default value of 5 seconds.Use Access-Control-Max-Age header
Browsers use this header to determine how long the preflight requests can be cached. This is sufficient if you are caching at the browser level but not optimal when considering edge caching.
2.Reduce the number of custom headers
Custom headers are headers that are not defined in the CORS specification. For example, the X-Requested-With
header is a custom header that is often used to track cross-origin requests.
Sending unnecessary custom headers can trigger a preflight request, which can slow down your application. To avoid this, only send headers that are actually needed.
This will improve the performance of your application by reducing the likelihood of a preflight request being triggered.
3.Use simple request types
Simple requests do not trigger preflight requests, so you can avoid the latency overhead of preflight requests by using them instead of other request types.
To be considered simple, a request must meet the following conditions:
The request method must be GET, POST, or HEAD.
The only headers allowed are Accept, Accept-Language, Content-Language, Content-Type, DPR, Downlink, Save-Data, Viewport-Width, and Width.
The Content-Type header must only have the following values: application/x-www-form-urlencoded, multipart/form-data, or text/plain.
If you can make your requests simple, you can avoid preflight requests and improve the performance of your application.
Note: Simple requests may not always be suitable for most web applications, as they do not allow authorization headers which are used in almost all HTTP requests.
4.Server-Side Caching using Proxies, Gateways, or CDNs
Server-side caching involves caching the preflight response in a proxy, gateway, or CDN so that it doesn't have to hit the origin server every time.
The preflight response can be cached for a specified amount of time, after which it will expire and the browser will make a new request to the origin server.
The caching mechanism can be configured to cache preflight responses based on a variety of factors, such as the URL of the request, the headers of the request, or the IP address of the client.
This can reduce the number of times the browser has to make a roundtrip to the origin server, which can improve the performance of the application and reduce the load on the origin server.
5.Making Requests Same-Origin
Another way to avoid Preflight requests is to make the requests same-origin. This can be done by proxying the requests through the same domain. For eg, if the frontend is running on http://localhost:4200
, a proxy could be configured to forward all requests to http://localhost:4200
. This would make all requests same-origin, and the browser would not need to send a Preflight request.
This approach might not be suitable for all applications. For instance, if the frontend and backend are hosted on different servers, it may not be possible to proxy all requests through the same domain. Additionally, proxying requests can add some latency, which may not be desirable for some applications.
6.Using CORS headers to optimize preflight requests
Use the
Access-Control-Allow-Headers
header to specify the headers that are allowed in the preflight request. This can help to reduce the size of the preflight request.Use the
Access-Control-Allow-Methods
header to specify the methods that are allowed in the preflight request. This can help to reduce the number of preflight requests that are sent.Use the
Access-Control-Allow-Credentials
header to allow the browser to send cookies with the preflight request. This can be useful if you need to access resources that are protected by cookies.
Conclusion
CORS preflight requests can add latency to your application. However, by using a few techniques to reduce or speed up these requests, you can optimize CORS preflight requests and improve the speed and performance of your web application. This will allow you to get the most out of CORS preflight requests.
Subscribe to my newsletter
Read articles from Aanchal directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by