CORS, which stands for Cross-Origin Resource Sharing, has an impact on performance monitoring. The goal of this article is to explain what CORS consists in, why it is used, and how it impacts the way you can monitor digital services performance.
Modern web applications make extensive use of third-party resources. Examples are the use of CDNs to better deliver content like images and stylesheets, or third-party services resources that are called through APIs. So one webpage can be the result of a multitude of requests to different locations called origins. This is especially true for SPAs (Single Page Applications) that mainly rely on calls to API backends.
A web content origin is defined by the scheme (protocol), host (domain), and port of the URL used to access it.
So as soon as the browser performs requests to different origins, CORS comes into play.
Let’s discuss why CORS has an impact on performance monitoring.
What is CORS – Cross-Origin Resource Sharing?
CORS is a mechanism that allows a server to indicate any other origins than its own from which a browser should permit loading of resources.
Before the CORS standardization, all calls to external origins (fetch or ajax calls) were blocked by the Same-origin Policy.
The following picture shows a simple example of a webpage that contains two images and some styling.
The first HTTP GET request (
GET /) determines the content origin (domain-a.com).
Rendering the page correctly requires the download of a stylesheet (layout.css) that is located on a third-party service via a cross-origin request (domain-b.com).
Finally, one image (image-1) is stored on the origin server, while the second (image-2) is stored on a third domain (domain-c.com).
So in this small example, getting the stylesheet as well as the image-2 is performed through cross-origin requests.
How does CORS work?
But how does a server grant this permission to a browser?
It does this through specific HTTP headers.
CORS in HTTP responses
The server grants the browser permission to access resources from other origins. It does this by using the
Access-Control-Allow-Origin HTTP header.
For example, you can allow requesting resources from any origin as follows:
You can also narrow down to a specific origin:
CORS in HTTP requests
There are two types of HTTP requests in a CORS context: “simple” and “preflight”.
The “simple” request
In the following example, the client sends a
GET request to the home page of the website example2.com.
This request is coming from the https://example.com, which is specified by the
Origin request header.
In response, the server sends back an
Access-Control-Allow-Origin header with the value
*, meaning that the resource can be accessed by any origin.
The “preflight” request
You will often encounter the preflight type of request when the browser intends to use HTTP methods like
DELETE. These methods obviously represent a bigger security risk as they typically modify web content on the server.
Unlike “simple” requests, in “preflight” requests, the browser first sends an HTTP request using the
OPTION method to determine if the actual request is safe to send. In other worlds, this preflight request checks whether the main request will be allowed or not.
Seeing that the
OPTION method cannot modify the resource itself, this is a safe method to use.
This example shows the basic process:
- The client sends a first preflight request using the
POSTmethod. Among others, this request includes the following information:
- The origin of the request (https://example.com)
- The HTTP method the browser will use in the main request (
POSTas mentioned by the
- The HTTP header the browser will use in the main request (X-PINGOTHER as mentioned by the
- The server responses back to the browser, confirming that the main request will be allowed. For this, the response includes the following headers:
Access-Control-Allow-Originas previously explained
Access-Control-Allow-Methodsthat provides the types of HTTP methods that will be allowed
Access-Control-Allow-Headersthat provides the list of types of headers that will be accessible by the main request (X-PINGOTHER and Content-Type in this example)
- Based on the preflight response, the client performs the main request
- As the request allowance has been verified previously, the server sends a response to this main request. Note that the
Access-Control-Allow-Originheader is present in all server responses.
The following site provides codes to implement CORS on different platforms.
What does CORS mean for your performance monitoring?
Now that you know why CORS exists and how it works, let’s have a look at the way performance metrics are reported in this context.
Major Real User Monitoring solutions use the W3C Time Navigation API as a basis for collecting performance metrics:
The following article provides more details about the page load process.
The problem that cross-origin resources introduce here is that they only expose timestamps for the following attributes by default:
- startTime (will equal fetchStart)
This is to protect users’ privacy (so an attacker cannot load random URLs to see where you’ve been).
This means that all of the following attributes will be “Null” for cross-origin resources:
In addition, all size information will be “0” for cross-origin resources:
Last but not the least, cross-origin resources that are redirected will have a startTime that only reflects the final resource — startTime will equal fetchStart instead of redirectStart. This means the time of any redirect(s) will be hidden from the resource timing.
So as you can see, using CORS has an impact on performance monitoring!
The solution to monitor the performance of CORS resources: enabling TAO (Time-Allow-Origin)
Luckily, if you control the domains you are fetching other resources from, you can bypass the default protection mechanism by sending a
Timing-Allow-Origin header in HTTP responses, informing the browser that it is allowed to process performance metrics.
If you are serving any of your content from another domain, i.e. from a CDN, it is strongly recommended that you set this header for those responses. Thankfully, third-party libraries for widgets, ads, analytics etc, are starting to set this TAO header on their content.
In 2013, only about 1,2% of the total resources embedded on a few hundred thousand websites presented the Time Access Origin (TAO) header. In 2018, this represented about 15% of the total websites. So there is still a long way to go.
Finally, if you still want to get performance metrics from the W3C Time Navigation API, there are browser extensions out there that allow the browser to bypass any restriction. This is obviously to the detriment of security! So just consider this workaround as a temporary solution when you require specific degradations troubleshooting.
Your next steps on CORS performance monitoring
CORS is a security mechanism that is enforced at the browser level. If you control the different servers, make sure to allow cross-origins requests by adding the
Access-Control-Allow-Origin header in HTTP responses in order to avoid errors in fetching resources.
Using CORS has an impact on performance monitoring. Monitoring performances of cross-origins requests is a challenge because the metrics are not reported by default.
If you use third-party services like CDNs, make sure they allow you to activate the
Timing-Allow-Origin header in HTTP responses.
In case this is not possible but you really need to collect these performance metrics, temporarily enable specialized browser’s extensions that will disable this security protection.