You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 5-network/05-fetch-crossorigin/article.md
+25-25
Original file line number
Diff line number
Diff line change
@@ -28,7 +28,7 @@ Seriously. Let's make a very brief historical digression.
28
28
29
29
**For many years a script from one site could not access the content of another site.**
30
30
31
-
That simple, yet powerful rule was a foundation of the internet security. E.g. an evil script from website `hacker.com` could not access user's mailbox at website `gmail.com`. People felt safe.
31
+
That simple, yet powerful rule was a foundation of the internet security. E.g. an evil script from website `hacker.com` could not access the user's mailbox at website `gmail.com`. People felt safe.
32
32
33
33
JavaScript also did not have any special methods to perform network requests at that time. It was a toy language to decorate a web page.
34
34
@@ -125,15 +125,15 @@ Contrary to that, requests with non-standard headers or e.g. method `DELETE` can
125
125
126
126
When we try to make a unsafe request, the browser sends a special "preflight" request that asks the server -- does it agree to accept such cross-origin requests, or not?
127
127
128
-
And, unless the server explicitly confirms that with headers, a unsafe request is not sent.
128
+
And, unless the server explicitly confirms that with headers, an unsafe request is not sent.
129
129
130
130
Now we'll go into details.
131
131
132
132
## CORSfor safe requests
133
133
134
-
If a request is cross-origin, the browser always adds `Origin` header to it.
134
+
If a request is cross-origin, the browser always adds the `Origin` header to it.
135
135
136
-
For instance, if we request `https://anywhere.com/request` from `https://javascript.info/page`, the headers will be like:
136
+
For instance, if we request `https://anywhere.com/request` from `https://javascript.info/page`, the headers will look like:
As you can see, `Origin` header contains exactly the origin (domain/protocol/port), without a path.
147
+
As you can see, the `Origin` header contains exactly the origin (domain/protocol/port), without a path.
148
148
149
-
The server can inspect the `Origin` and, if it agrees to accept such a request, adds a special header `Access-Control-Allow-Origin` to the response. That header should contain the allowed origin (in our case `https://javascript.info`), or a star `*`. Then the response is successful, otherwise an error.
149
+
The server can inspect the `Origin` and, if it agrees to accept such a request, add a special header `Access-Control-Allow-Origin` to the response. That header should contain the allowed origin (in our case `https://javascript.info`), or a star `*`. Then the response is successful, otherwise it's an error.
150
150
151
151
The browser plays the role of a trusted mediator here:
152
152
1. It ensures that the correct `Origin` is sent with a cross-origin request.
@@ -182,7 +182,7 @@ There's no `Content-Length` header in the list!
182
182
This header contains the full response length. So, if we're downloading something and would like to track the percentage of progress, then an additional permission is required to access that header (see below).
183
183
```
184
184
185
-
To grant JavaScript access to any other response header, the server must send `Access-Control-Expose-Headers` header. It contains a comma-separated list of unsafe header names that should be made accessible.
185
+
To grant JavaScript access to any other response header, the server must send the`Access-Control-Expose-Headers`header. It contains a comma-separated list of unsafe header names that should be made accessible.
With such `Access-Control-Expose-Headers` header, the script is allowed to read `Content-Length` and `API-Key` headers of the response.
200
+
With such an `Access-Control-Expose-Headers` header, the script is allowed to read the`Content-Length` and `API-Key` headers of the response.
201
201
202
202
## "Unsafe" requests
203
203
204
204
We can use any HTTP-method: not just `GET/POST`, but also `PATCH`, `DELETE` and others.
205
205
206
206
Some time ago no one could even imagine that a webpage could make such requests. So there may still exist webservices that treat a non-standard method as a signal:"That's not a browser". They can take it into account when checking access rights.
207
207
208
-
So, to avoid misunderstandings, any "unsafe" request -- that couldn't be done in the old times, the browser does not make such requests right away. Before it sends a preliminary, so-called "preflight" request, asking for permission.
208
+
So, to avoid misunderstandings, any "unsafe" request -- that couldn't be done in the old times, the browser does not make such requests right away. First, it sends a preliminary, so-called "preflight" request, to ask for permission.
209
209
210
-
A preflight request uses method `OPTIONS`, no body and two headers:
210
+
A preflight request uses the method `OPTIONS`, no body and two headers:
211
211
212
212
- `Access-Control-Request-Method` header has the method of the unsafe request.
213
213
- `Access-Control-Request-Headers` header provides a comma-separated list of its unsafe HTTP-headers.
@@ -221,7 +221,7 @@ If the server agrees to serve the requests, then it should respond with empty bo
221
221
222
222

223
223
224
-
Let's see how it works step-by-step on example, for a cross-origin `PATCH` request (this method is often used to update data):
224
+
Let's see how it works step-by-step on the example of a cross-origin `PATCH` request (this method is often used to update data):
225
225
226
226
```js
227
227
let response = await fetch('https://site.com/service.json', {
@@ -240,7 +240,7 @@ There are three reasons why the request is unsafe (one is enough):
240
240
241
241
### Step 1 (preflight request)
242
242
243
-
Prior to sending such request, the browser, on its own, sends a preflight request that looks like this:
243
+
Prior to sending such a request, the browser, on its own, sends a preflight request that looks like this:
Now the browser can see that `PATCH` is in`Access-Control-Allow-Methods` and `Content-Type,API-Key` are in the list `Access-Control-Allow-Headers`, so it sends out the main request.
282
282
283
-
If there's header `Access-Control-Max-Age` with a number of seconds, then the preflight permissions are cached for the given time. The response above will be cached for 86400 seconds (one day). Within this timeframe, subsequent requests will not cause a preflight. Assuming that they fit the cached allowances, they will be sent directly.
283
+
If there's the header `Access-Control-Max-Age` with a number of seconds, then the preflight permissions are cached for the given time. The response above will be cached for 86400 seconds (one day). Within this timeframe, subsequent requests will not cause a preflight. Assuming that they fit the cached allowances, they will be sent directly.
284
284
285
285
### Step 3 (actual request)
286
286
287
-
When the preflight is successful, the browser now makes the main request. The algorithm here is the same as for safe requests.
287
+
When the preflight is successful, the browser now makes the main request. The process here is the same as for safe requests.
288
288
289
-
The main request has `Origin` header (because it's cross-origin):
289
+
The main request has the `Origin` header (because it's cross-origin):
290
290
291
291
```http
292
292
PATCH /service.json
@@ -316,7 +316,7 @@ JavaScript only gets the response to the main request or an error if there's no
316
316
317
317
A cross-origin request initiated by JavaScript code by default does not bring any credentials (cookies or HTTP authentication).
318
318
319
-
That's uncommon for HTTP-requests. Usually, a request to `http://site.com` is accompanied by all cookies from that domain. But cross-origin requests made by JavaScript methods are an exception.
319
+
That's uncommon for HTTP-requests. Usually, a request to `http://site.com` is accompanied by all cookies from that domain. Cross-origin requests made by JavaScript methods on the other hand are an exception.
320
320
321
321
For example, `fetch('http://another.com')` does not send any cookies, even those (!) that belong to `another.com` domain.
322
322
@@ -362,12 +362,12 @@ From the browser point of view, there are two kinds of cross-origin requests: "s
362
362
363
363
The essential difference is that safe requests were doable since ancient times using `<form>` or `<script>` tags, while unsafe were impossible for browsers for a long time.
364
364
365
-
So, the practical difference is that safe requests are sent right away, with `Origin` header, while for the other ones the browser makes a preliminary "preflight" request, asking for permission.
365
+
So, the practical difference is that safe requests are sent right away, with the `Origin` header, while for the other ones the browser makes a preliminary "preflight" request, asking for permission.
366
366
367
367
**For safe requests:**
368
368
369
-
- → The browser sends `Origin` header with the origin.
370
-
- ← For requests without credentials (not sent default), the server should set:
369
+
- → The browser sends the `Origin` header with the origin.
370
+
- ← For requests without credentials (not sent by default), the server should set:
371
371
-`Access-Control-Allow-Origin` to `*` or same value as `Origin`
372
372
- ← For requests with credentials, the server should set:
373
373
-`Access-Control-Allow-Origin` to same value as `Origin`
@@ -377,11 +377,11 @@ Additionally, to grant JavaScript access to any response headers except `Cache-C
377
377
378
378
**For unsafe requests, a preliminary "preflight" request is issued before the requested one:**
379
379
380
-
- → The browser sends `OPTIONS` request to the same URL, with headers:
380
+
- → The browser sends an `OPTIONS` request to the same URL, with the headers:
381
381
-`Access-Control-Request-Method` has requested method.
0 commit comments