When a site makes a request to a resource from a different origin, that request is known as a cross-origin request (COR); for example, when the page at https://www.gothamimperial.com/ attempts to load a stylesheet from https://maxcdn.bootstrapcdn.com/, or Analytics code from https://www.google-analytics.com/.
For security reasons, browsers allow pages to embed resources from a different origin, but they do not allow a script to read the content of a resource from another origin. This is known as the same-origin policy. An embed, such as when the Gotham Imperial Hotel uses a <link>
tag to load a stylesheet from a CDN, is allowed, but making an Ajax request to read a JSON file from a different domain will be blocked.
Developers have often bypassed some of these limitations by embedding resources instead of accessing them directly (e.g., by using JSONP), but these were partial solutions that only worked in some cases and re-exposed their users to the security issues that the browsers attempted to solve (mainly cross-site scripting attacks).
Clearly, a better solution was needed.
Cross-origin resource sharing (CORS) is a new (less than a decade old) W3C standard used to define these interactions between the server and browser. Both the browser making the request as well as the server responding to it can determine how requests are handled. For example, a script can configure a request so that it can come from a different origin. But for the request to succeed, the server will also need to be configured to respond to cross-origin requests. The server can even be configured to only accept requests from certain origins (e.g., www.pwabookcdn.com can be configured to only respond to cross-origin requests from www.pwabook.com).
When creating new requests in your script, you can set their mode to one of several values:
cors
Allow cross-origin requests. This is the default value for new requests.
no-cors
The confusingly named no-cors
actually allows cross-origin requests, but these no-cors
requests are more limited than cors
requests. Their method can only be HEAD, GET, or POST. If a service worker intercepts this request, it can only modify a limited set of its headers. Finally, no JavaScript code can access the response’s properties.
same-origin
Completely disallow cross-origin requests.
In Chapter 5, we had to fetch a script from a server that only accepts no-cors
requests. If we hadn’t configured the request to https://maps.googleapis.com to no-cors
mode, that request would have been rejected by the server. By only allowing no-cors
requests, that server can ensure third-party sites are free to read data from it, but are limited in their ability to modify the requests:
if
(
requestURL
.
href
===
googleMapsAPIJS
)
{
event
.
respondWith
(
fetch
(
googleMapsAPIJS
+
"&"
+
Date
.
now
(),
{
mode
:
"no-cors"
,
cache
:
"no-store"
}
).
catch
(
function
()
{
return
caches
.
match
(
"/js/offline-map.js"
);
})
);
}