aboutsummaryrefslogtreecommitdiff
path: root/files/uk/web/http/cors/index.html
blob: 80cb620485e695867ab37956cc32e3ae14620e1d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
---
title: Cross-Origin Resource Sharing (CORS)
slug: Web/HTTP/CORS
tags:
  - AJAX
  - CORS
  - HTTP
  - Безпека
translation_of: Web/HTTP/CORS
---
<div>{{HTTPSidebar}}</div>

<p><span class="seoSummary">Cross-Origin Resource Sharing ({{Glossary("CORS")}}, перехресний обмін ресурсами) — це механізм, що за допомогою {{Glossary("HTTP")}}-заголовків дає {{Glossary("Browser", "переглядачеві")}} дозвіл завантажувати ресурси з певного джерела на запит web-застосунка, отриманого з відмінного джерела.</span> Web-застосунок виконує <strong>перехресний HTTP-запит</strong> коли потребує ресурсів з джерела (домен, протокол чи порт), відмінного від його власного.</p>

<p>Приклад перехресного запиту: JavaScript-код web-застосунка, розміщеного на <code>http://domain-a.com</code>, намагається за допомогою {{domxref("XMLHttpRequest", "AJAX")}}-запиту отримати <code>http://api.domain-b.com/data.json</code>.</p>

<p>З міркувань безпеки, web-переглядачі припиняють всі перехресні HTTP-запити, здійснені кодом скриптів. Наприклад, <code>XMLHttpRequest</code> і <a href="/uk/docs/Web/API/Fetch_API">Fetch API</a> дотримуються <a href="/uk/docs/Web/Security/Same-origin_policy">правила одного джерела</a>. Це означає, що web-застосунок, отриманий з певного джерела, не може виконувати запити до HTTP-ресурсів з відмінного джерела (хіба якщо відповідь, що з нього надходить, міститиме належні CORS-заголовки).</p>

<p><img alt="Localized CORS request principle" src="https://mdn.mozillademos.org/files/16490/CORS_principle.png" style="height: 643px; width: 925px;"></p>

<p>Механізм CORS уможливлює безпечні перехресні запити та передання даних між web-переглядачами та web-серверами. Сучасні web-переглядачі запроваджують підтримку CORS до API, як-от <code>XMLHttpRequest</code> або <a href="/uk/docs/Web/API/Fetch_API">Fetch API</a>, щоб зробити виконання перехресних HTTP-запитів якнайбезпечнішим.</p>

<h2 id="Для_кого_ця_стаття">Для кого ця стаття?</h2>

<p>Для кожного, поза сумнівом.</p>

<p>А саме для web-адміністраторів, а також розробників серверних та клієнських застосунків. Сучасні переглядачі запроваджують підтримку CORS з клієнтського боку (зокрема, обробку заголовків та обмеження неправомірних запитів), проте цей новий стандарт потребує, щоб сервер обробляв нові запити й додавав належні заголовки до відповідей. Докладніше про це оповідає стаття «<a href="/uk/docs/Web/HTTP/Server-Side_Access_Control">перехресні запити з погляду сервера</a>» для серверних розробників (зі зразками PHP-коду).</p>

<h2 id="До_яких_запитів_стосується_CORS">До яких запитів стосується CORS?</h2>

<p><a href="https://fetch.spec.whatwg.org/#http-cors-protocol">Цей стандарт</a> покликаний дозволити міжсайтові HTTP-запити для:</p>

<ul>
 <li>Міжсайтового користування {{domxref("XMLHttpRequest")}} та <a href="/uk/docs/Web/API/Fetch_API">Fetch</a> API, як зазначено вище;</li>
 <li>Web-шрифтів (використання шрифтів з інших джерел за допомогою правила <code>@font-face</code> в CSS), тож <a href="https://www.w3.org/TR/css-fonts-3/#font-fetching-requirements">сервер, який розміщує TrueType-шрифти, надає обмежений доступ</a> на їх завантаження лише певній множині сайтів;</li>
 <li><a href="/uk/docs/Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL">Текстури WebGL</a>;</li>
 <li>Зображення чи кадри відео, намальовані на холсті за допомогою {{domxref("CanvasRenderingContext2D.drawImage()", "drawImage()")}}.</li>
</ul>

<p>Ця стаття описує перехресний обмін ресурсами взагалі та окремі HTTP-заголовки, що для цього необхідні.</p>

<h2 id="Функціональний_огляд">Функціональний огляд</h2>

<p>Стандарт перехресного обміну ресурсами працює за допомогою додавання нових HTTP заголовків, що дозволять серверу описати набір витоків, які мають дозвіл на читання інформації використовуючи веб-браузер. На додаток, для HTTP методів запиту, що можуть спричини  побічний еффект на серверні дані (в особливості, для HTTP методів, окрім {{HTTPMethod("GET")}}, або для {{HTTPMethod("POST")}} використання із певним <a href="/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types">MIME types</a>), специфікація передбачає, що браузерам "попередньо переглядають" запити, вимагають підтримуваних методів з сервера за допомогою HTTP {{HTTPMethod("OPTIONS")}} методів запиту, а потім після "схвалення" з сервера, надсилає фактичний запит методом фактичного запиту HTTP. Сервер також може повідомляти клієнтів чи "credentials" (включаючи Куки і HTTP Аутентифікаційні дані) повинні бути відправлені із запитом.</p>

<p>У наступних розділах обговорюються сценарії, а також надається розбивка використовуваних заголовків HTTP.</p>

<h2 id="Приклади_сценаріїв_контролю_доступу">Приклади сценаріїв контролю доступу</h2>

<p>Тут ми представляємо три сценарії, які ілюструють, як працює перехресне походження ресурсів. У всіх цих прикладах використовується об’єкт {{domxref ("XMLHttpRequest")}}, який можна використовувати для виклику між сайтів у будь-якому підтримуваному браузері.</p>

<p>Фрагменти JavaScript, що містяться в цих розділах (і запущені екземпляри серверного коду, який правильно обробляє ці запити на різних веб-сайтах), можна знайти "в дії" за адресою http://arunranga.com/examples/access-control/, і буде робота в браузерах, які підтримують крос-сайт {{domxref ("XMLHttpRequest")}}.</p>

<p>Обговорення міжпохідного обміну ресурсами з точки зору сервера (включаючи фрагменти коду PHP) можна знайти в статті управління доступом на стороні сервера (CORS).</p>

<h3 id="Прості_запити">Прості запити</h3>

<p>Some requests don’t trigger a <a href="/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests">CORS preflight</a>. Those are called “simple requests” in this article, though the {{SpecName('Fetch')}} spec (which defines CORS) doesn’t use that term. A request that doesn’t trigger a <a href="/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests">CORS preflight</a>—a so-called “simple request”—is one that meets all the following conditions:</p>

<ul>
 <li>The only allowed methods are:
  <ul>
   <li>{{HTTPMethod("GET")}}</li>
   <li>{{HTTPMethod("HEAD")}}</li>
   <li>{{HTTPMethod("POST")}}</li>
  </ul>
 </li>
 <li>Apart from the headers set automatically by the user agent (for example, {{HTTPHeader("Connection")}}, {{HTTPHeader("User-Agent")}}, or <a href="https://fetch.spec.whatwg.org/#forbidden-header-name">any of the other headers with names defined in the Fetch spec as a “forbidden header name”</a>), the only headers which are allowed to be manually set are <a href="https://fetch.spec.whatwg.org/#cors-safelisted-request-header">those which the Fetch spec defines as being a “CORS-safelisted request-header”</a>, which are:
  <ul>
   <li>{{HTTPHeader("Accept")}}</li>
   <li>{{HTTPHeader("Accept-Language")}}</li>
   <li>{{HTTPHeader("Content-Language")}}</li>
   <li>{{HTTPHeader("Content-Type")}} (but note the additional requirements below)</li>
   <li>{{HTTPHeader("Last-Event-ID")}}</li>
   <li><code><a href="http://httpwg.org/http-extensions/client-hints.html#dpr">DPR</a></code></li>
   <li><code><a href="http://httpwg.org/http-extensions/client-hints.html#save-data">Save-Data</a></code></li>
   <li><code><a href="http://httpwg.org/http-extensions/client-hints.html#viewport-width">Viewport-Width</a></code></li>
   <li><code><a href="http://httpwg.org/http-extensions/client-hints.html#width">Width</a></code></li>
  </ul>
 </li>
 <li>The only allowed values for the {{HTTPHeader("Content-Type")}} header are:
  <ul>
   <li><code>application/x-www-form-urlencoded</code></li>
   <li><code>multipart/form-data</code></li>
   <li><code>text/plain</code></li>
  </ul>
 </li>
 <li>No event listeners are registered on any {{domxref("XMLHttpRequestUpload")}} object used in the request; these are accessed using the {{domxref("XMLHttpRequest.upload")}} property.</li>
 <li>No {{domxref("ReadableStream")}} object is used in the request.</li>
</ul>

<div class="note"><strong>Note:</strong> These are the same kinds of cross-site requests that web content can already issue, and no response data is released to the requester unless the server sends an appropriate header. Therefore, sites that prevent cross-site request forgery have nothing new to fear from HTTP access control.</div>

<div class="note"><strong>Note:</strong> WebKit Nightly and Safari Technology Preview place additional restrictions on the values allowed in the {{HTTPHeader("Accept")}}, {{HTTPHeader("Accept-Language")}}, and {{HTTPHeader("Content-Language")}} headers. If any of those headers have ”non-standard” values, WebKit/Safari does not consider the request to meet the conditions for a “simple request”. What WebKit/Safari considers “non-standard” values for those headers is not documented except in the following WebKit bugs: <a href="https://bugs.webkit.org/show_bug.cgi?id=165178" rel="nofollow noreferrer">Require preflight for non-standard CORS-safelisted request headers Accept, Accept-Language, and Content-Language</a>, <a href="https://bugs.webkit.org/show_bug.cgi?id=165566" rel="nofollow noreferrer">Allow commas in Accept, Accept-Language, and Content-Language request headers for simple CORS</a>, and <a href="https://bugs.webkit.org/show_bug.cgi?id=166363" rel="nofollow noreferrer">Switch to a blacklist model for restricted Accept headers in simple CORS requests</a>. No other browsers implement those extra restrictions, because they’re not part of the spec.</div>

<p>For example, suppose web content on domain <code class="plain">http://foo.example</code> wishes to invoke content on domain <code class="plain">http://bar.other</code>. Code of this sort might be used within JavaScript deployed on foo.example:</p>

<pre class="brush: js notranslate" id="line1">var invocation = new XMLHttpRequest();
var url = 'http://bar.other/resources/public-data/';

function callOtherDomain() {
  if(invocation) {
    invocation.open('GET', url, true);
    invocation.onreadystatechange = handler;
    invocation.send();
  }
}
</pre>

<p>This will lead to a simple exchange between the client and the server, using CORS headers to handle the privileges:</p>

<p><img alt="" src="https://mdn.mozillademos.org/files/14293/simple_req.png" style="height: 224px; width: 521px;"></p>

<p>Let us look at what the browser will send to the server in this case, and let's see how the server responds:</p>

<pre class="brush: shell;highlight:[10,16] notranslate">GET /resources/public-data/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Referer: http://foo.example/examples/access-control/simpleXSInvocation.html
Origin: http://foo.example


HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 00:23:53 GMT
Server: Apache/2.0.61
Access-Control-Allow-Origin: *
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/xml

[XML Data]
</pre>

<p>Lines 1 - 10 are headers sent. The main HTTP request header of note here is the {{HTTPHeader("Origin")}} header on line 10 above, which shows that the invocation is coming from content on the domain <code class="plain">http://foo.example</code>.</p>

<p>Lines 13 - 22 show the HTTP response from the server on domain <code class="plain">http://bar.other</code>. In response, the server sends back an {{HTTPHeader("Access-Control-Allow-Origin")}} header, shown above in line 16. The use of the {{HTTPHeader("Origin")}} header and of {{HTTPHeader("Access-Control-Allow-Origin")}} show the access control protocol in its simplest use. In this case, the server responds with a <code>Access-Control-Allow-Origin: *</code> which means that the resource can be accessed by <strong>any</strong> domain in a cross-site manner. If the resource owners at <code class="plain">http://bar.other</code> wished to restrict access to the resource to requests only from <code class="plain">http://foo.example</code>, they would send back:</p>

<p><code class="plain">Access-Control-Allow-Origin: http://foo.example</code></p>

<p>Note that now, no domain other than <code class="plain">http://foo.example</code> (identified by the ORIGIN: header in the request, as in line 10 above) can access the resource in a cross-site manner. The <code>Access-Control-Allow-Origin</code> header should contain the value that was sent in the request's <code>Origin</code> header.</p>

<h3 id="Preflighted_requests">Preflighted requests</h3>

<p>Unlike <a href="/en-US/docs/Web/HTTP/Access_control_CORS#Simple_requests">“simple requests” (discussed above)</a>, "preflighted" requests first send an HTTP request by the {{HTTPMethod("OPTIONS")}} method to the resource on the other domain, in order to determine whether the actual request is safe to send. Cross-site requests are preflighted like this since they may have implications to user data.</p>

<p>In particular, a request is preflighted if <strong>any of the following conditions</strong> is true:</p>

<ul>
 <li><strong>If</strong> the request uses any of the following methods:

  <ul>
   <li>{{HTTPMethod("PUT")}}</li>
   <li>{{HTTPMethod("DELETE")}}</li>
   <li>{{HTTPMethod("CONNECT")}}</li>
   <li>{{HTTPMethod("OPTIONS")}}</li>
   <li>{{HTTPMethod("TRACE")}}</li>
   <li>{{HTTPMethod("PATCH")}}</li>
  </ul>
 </li>
 <li><strong>Or if</strong>, apart from the headers set automatically by the user agent (for example, {{HTTPHeader("Connection")}}, {{HTTPHeader("User-Agent")}}, or <a href="https://fetch.spec.whatwg.org/#forbidden-header-name">any of the other header with a name defined in the Fetch spec as a “forbidden header name”</a>), the request includes any headers other than <a href="https://fetch.spec.whatwg.org/#cors-safelisted-request-header">those which the Fetch spec defines as being a “CORS-safelisted request-header”</a>, which are the following:
  <ul>
   <li>{{HTTPHeader("Accept")}}</li>
   <li>{{HTTPHeader("Accept-Language")}}</li>
   <li>{{HTTPHeader("Content-Language")}}</li>
   <li>{{HTTPHeader("Content-Type")}} (but note the additional requirements below)</li>
   <li>{{HTTPHeader("Last-Event-ID")}}</li>
   <li><code><a href="http://httpwg.org/http-extensions/client-hints.html#dpr">DPR</a></code></li>
   <li><code><a href="http://httpwg.org/http-extensions/client-hints.html#save-data">Save-Data</a></code></li>
   <li><code><a href="http://httpwg.org/http-extensions/client-hints.html#viewport-width">Viewport-Width</a></code></li>
   <li><code><a href="http://httpwg.org/http-extensions/client-hints.html#width">Width</a></code></li>
  </ul>
 </li>
 <li><strong>Or if</strong> the {{HTTPHeader("Content-Type")}} header has a value other than the following:
  <ul>
   <li><code>application/x-www-form-urlencoded</code></li>
   <li><code>multipart/form-data</code></li>
   <li><code>text/plain</code></li>
  </ul>
 </li>
 <li><strong>Or if</strong> one or more event listeners are registered on an {{domxref("XMLHttpRequestUpload")}} object used in the request.</li>
 <li><strong>Or if</strong> a {{domxref("ReadableStream")}} object is used in the request.</li>
</ul>

<div class="note"><strong>Note:</strong> WebKit Nightly and Safari Technology Preview place additional restrictions on the values allowed in the {{HTTPHeader("Accept")}}, {{HTTPHeader("Accept-Language")}}, and {{HTTPHeader("Content-Language")}} headers. If any of those headers have ”non-standard” values, WebKit/Safari preflights the request. What WebKit/Safari considers “non-standard” values for those headers is not documented except in the following WebKit bugs: <a href="https://bugs.webkit.org/show_bug.cgi?id=165178" rel="nofollow noreferrer">Require preflight for non-standard CORS-safelisted request headers Accept, Accept-Language, and Content-Language</a>, <a href="https://bugs.webkit.org/show_bug.cgi?id=165566" rel="nofollow noreferrer">Allow commas in Accept, Accept-Language, and Content-Language request headers for simple CORS</a>, and <a href="https://bugs.webkit.org/show_bug.cgi?id=166363" rel="nofollow noreferrer">Switch to a blacklist model for restricted Accept headers in simple CORS requests</a>. No other browsers implement those extra restrictions, because they’re not part of the spec.</div>

<p>The following is an example of a request that will be preflighted.</p>

<pre class="brush: js notranslate" id="line1">var invocation = new XMLHttpRequest();
var url = 'http://bar.other/resources/post-here/';
var body = '&lt;?xml version="1.0"?&gt;&lt;person&gt;&lt;name&gt;Arun&lt;/name&gt;&lt;/person&gt;';

function callOtherDomain(){
  if(invocation)
    {
      invocation.open('POST', url, true);
      invocation.setRequestHeader('X-PINGOTHER', 'pingpong');
      invocation.setRequestHeader('Content-Type', 'application/xml');
      invocation.onreadystatechange = handler;
      invocation.send(body);
    }
}

......
</pre>

<p>In the example above, line 3 creates an XML body to send with the <code>POST</code> request in line 8. Also, on line 9, a "customized" (non-standard) HTTP request header is set (<code>X-PINGOTHER: pingpong</code>). Such headers are not part of the HTTP/1.1 protocol, but are generally useful to web applications. Since the request uses a Content-Type of <code>application/xml</code>, and since a custom header is set, this request is preflighted.</p>

<p><img alt="" src="https://mdn.mozillademos.org/files/14289/prelight.png"></p>

<p>(Note: as described below, the actual POST request does not include the Access-Control-Request-* headers; they are needed only for the OPTIONS request.)</p>

<p>Let's take a look at the full exchange between client and server. The first exchange is the <em>preflight request/response</em>:</p>

<pre class="brush: none notranslate">OPTIONS /resources/post-here/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Origin: http://foo.example
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type


HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Methods: POST, GET
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain
</pre>

<p>Once the preflight request is complete, the real request is sent:</p>

<pre class="brush: none notranslate">POST /resources/post-here/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
X-PINGOTHER: pingpong
Content-Type: text/xml; charset=UTF-8
Referer: http://foo.example/examples/preflightInvocation.html
Content-Length: 55
Origin: http://foo.example
Pragma: no-cache
Cache-Control: no-cache

&lt;?xml version="1.0"?&gt;&lt;person&gt;&lt;name&gt;Arun&lt;/name&gt;&lt;/person&gt;


HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:40 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://foo.example
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 235
Keep-Alive: timeout=2, max=99
Connection: Keep-Alive
Content-Type: text/plain

[Some GZIP'd payload]
</pre>

<p>Lines 1 - 12 above represent the preflight request with the {{HTTPMethod("OPTIONS")}} method. The browser determines that it needs to send this based on the request parameters that the JavaScript code snippet above was using, so that the server can respond whether it is acceptable to send the request with the actual request parameters. OPTIONS is an HTTP/1.1 method that is used to determine further information from servers, and is a {{Glossary("safe")}} method, meaning that it can't be used to change the resource. Note that along with the OPTIONS request, two other request headers are sent (lines 10 and 11 respectively):</p>

<pre class="brush: none notranslate">Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type
</pre>

<p>The {{HTTPHeader("Access-Control-Request-Method")}} header notifies the server as part of a preflight request that when the actual request is sent, it will be sent with a <code>POST</code> request method. The {{HTTPHeader("Access-Control-Request-Headers")}} header notifies the server that when the actual request is sent, it will be sent with a <code>X-PINGOTHER</code> and Content-Type custom headers. The server now has an opportunity to determine whether it wishes to accept a request under these circumstances.</p>

<p>Lines 14 - 26 above are the response that the server sends back indicating that the request method (<code>POST</code>) and request headers (<code>X-PINGOTHER</code>) are acceptable. In particular, let's look at lines 17-20:</p>

<pre class="brush: none notranslate">Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Methods: POST, GET
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400</pre>

<p>The server responds with <code>Access-Control-Allow-Methods</code> and says that <code>POST</code> and <code>GET</code> are viable methods to query the resource in question. Note that this header is similar to the {{HTTPHeader("Allow")}} response header, but used strictly within the context of access control.</p>

<p>The server also sends <code>Access-Control-Allow-Headers</code> with a value of "<code>X-PINGOTHER, Content-Type</code>", confirming that these are permitted headers to be used with the actual request. Like <code>Access-Control-Allow-Methods</code>, <code>Access-Control-Allow-Headers</code> is a comma separated list of acceptable headers.</p>

<p>Finally, {{HTTPHeader("Access-Control-Max-Age")}} gives the value in seconds for how long the response to the preflight request can be cached for without sending another preflight request. In this case, 86400 seconds is 24 hours. Note that each browser has a<a href="/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age"> maximum internal value</a> that takes precedence when the <code>Access-Control-Max-Age</code> is greater.</p>

<h4 id="Preflighted_requests_and_redirects">Preflighted requests and redirects</h4>

<p>Most browsers currently don’t support following redirects for preflighted requests. If a redirect occurs for a preflighted request, most current browsers will report an error message such as the following.</p>

<blockquote>
<p>The request was redirected to 'https://example.com/foo', which is disallowed for cross-origin requests that require preflight</p>
</blockquote>

<blockquote>
<p>Request requires preflight, which is disallowed to follow cross-origin redirect</p>
</blockquote>

<p>The CORS protocol originally required that behavior but <a href="https://github.com/whatwg/fetch/commit/0d9a4db8bc02251cc9e391543bb3c1322fb882f2">was subsquently changed to no longer require it</a>. However, most browsers have not yet implemented the change and still exhibit the behavior that was originally required.</p>

<p>So until browsers catch up with the spec, you may be able to work around this limitation by doing one or both of the following:</p>

<ul>
 <li>change the server-side behavior to avoid the preflight and/or to avoid the redirect—if you have control over the server the request is being made to</li>
 <li>change the request such that it is a <a href="#Simple_requests">simple request</a> that doesn’t cause a preflight</li>
</ul>

<p>But if it’s not possible to make those changes, then another way that may be possible is to this:</p>

<ol>
 <li>Make a <a href="/en-US/docs/Web/HTTP/Access_control_CORS#Simple_requests">simple request</a> (using <a href="/en-US/docs/Web/API/Response/url">Response.url</a> for the Fetch API, or <a href="/en-US/docs/Web/API/XMLHttpRequest/responseURL">XHR.responseURL</a>) to determine what URL the real preflighted request would end up at.</li>
 <li>Make another request (the “real” request) using the URL you obtained from <a href="/en-US/docs/Web/API/Response/url">Response.url</a> or <a href="/en-US/docs/Web/API/XMLHttpRequest/responseURL">XMLHttpRequest.responseURL</a> in the first step.</li>
</ol>

<p>However, if the request is one that triggers a preflight due to the presence of the `Authorization` header in the request, you won’t be able to work around the limitation using the steps above. And you won’t be able to work around it at all unless you have control over the server the request is being made to.</p>

<h3 id="Requests_with_credentials">Requests with credentials</h3>

<p>The most interesting capability exposed by both {{domxref("XMLHttpRequest")}} or <a href="/en-US/docs/Web/API/Fetch_API">Fetch</a> and CORS is the ability to make "credentialed" requests that are aware of <a href="/en-US/docs/Web/HTTP/Cookies">HTTP cookies</a> and HTTP Authentication information. By default, in cross-site {{domxref("XMLHttpRequest")}} or <a href="/en-US/docs/Web/API/Fetch_API">Fetch</a> invocations, browsers will <strong>not</strong> send credentials. A specific flag has to be set on the {{domxref("XMLHttpRequest")}} object or the {{domxref("Request")}} constructor when it is invoked.</p>

<p>In this example, content originally loaded from <code class="plain">http://foo.example</code> makes a simple GET request to a resource on <code class="plain">http://bar.other</code> which sets Cookies. Content on foo.example might contain JavaScript like this:</p>

<pre class="brush: js notranslate" id="line1">var invocation = new XMLHttpRequest();
var url = 'http://bar.other/resources/credentialed-content/';

function callOtherDomain(){
  if(invocation) {
    invocation.open('GET', url, true);
    invocation.withCredentials = true;
    invocation.onreadystatechange = handler;
    invocation.send();
  }
}</pre>

<p>Line 7 shows the flag on {{domxref("XMLHttpRequest")}} that has to be set in order to make the invocation with Cookies, namely the <code>withCredentials</code> boolean value. By default, the invocation is made without Cookies. Since this is a simple <code>GET</code> request, it is not preflighted, but the browser will <strong>reject</strong> any response that does not have the {{HTTPHeader("Access-Control-Allow-Credentials")}}<code>: true</code> header, and <strong>not</strong> make the response available to the invoking web content.</p>

<p><img alt="" src="https://mdn.mozillademos.org/files/14291/cred-req.png" style="height: 223px; width: 521px;"></p>

<p>Here is a sample exchange between client and server:</p>

<pre class="brush: none notranslate">GET /resources/access-control-with-credentials/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Referer: http://foo.example/examples/credential.html
Origin: http://foo.example
Cookie: pageAccess=2


HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:34:52 GMT
Server: Apache/2.0.61 (Unix) PHP/4.4.7 mod_ssl/2.0.61 OpenSSL/0.9.7e mod_fastcgi/2.4.2 DAV/2 SVN/1.4.2
X-Powered-By: PHP/5.2.6
Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Credentials: true
Cache-Control: no-cache
Pragma: no-cache
Set-Cookie: pageAccess=3; expires=Wed, 31-Dec-2008 01:34:53 GMT
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 106
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain


[text/plain payload]
</pre>

<p>Although line 11 contains the Cookie destined for the content on <code class="plain">http://bar.other</code>, if bar.other did not respond with an {{HTTPHeader("Access-Control-Allow-Credentials")}}<code>: true</code> (line 19) the response would be ignored and not made available to web content.</p>

<h4 id="Credentialed_requests_and_wildcards">Credentialed requests and wildcards</h4>

<p>When responding to a credentialed request, the server <strong>must</strong> specify an origin in the value of the <code>Access-Control-Allow-Origin</code> header, instead of specifying the "<code>*</code>" wildcard.</p>

<p>Because the request headers in the above example include a <code>Cookie</code> header, the request would fail if the value of the <code>Access-Control-Allow-Origin</code> header were "*". But it does not fail: Because the value of the <code>Access-Control-Allow-Origin</code> header is "<code class="plain">http://foo.example</code>" (an actual origin) rather than the "<code>*</code>" wildcard, the credential-cognizant content is returned to the invoking web content.</p>

<p>Note that the <code>Set-Cookie</code> response header in the example above also sets a further cookie. In case of failure, an exception—depending on the API used—is raised.</p>

<h4 id="Third-party_cookies">Third-party cookies</h4>

<p>Note that cookies set in CORS responses are subject to normal third-party cookie policies. In the example above, the page is loaded from <code>foo.example</code>, but the cookie on line 22 is sent by <code>bar.other</code>, and would thus not be saved if the user has configured their browser to reject all third-party cookies.</p>

<h2 id="The_HTTP_response_headers">The HTTP response headers</h2>

<p>This section lists the HTTP response headers that servers send back for access control requests as defined by the Cross-Origin Resource Sharing specification. The previous section gives an overview of these in action.</p>

<h3 id="Access-Control-Allow-Origin">Access-Control-Allow-Origin</h3>

<p>A returned resource may have one {{HTTPHeader("Access-Control-Allow-Origin")}} header, with the following syntax:</p>

<pre class="brush: none notranslate">Access-Control-Allow-Origin: &lt;origin&gt; | *
</pre>

<p>The <code>origin</code> parameter specifies a URI that may access the resource. The browser must enforce this. For requests <strong>without</strong> credentials, the server may specify "*" as a wildcard, thereby allowing any origin to access the resource.</p>

<p>For example, to allow http://mozilla.org to access the resource, you can specify:</p>

<pre class="brush: none notranslate">Access-Control-Allow-Origin: http://mozilla.org</pre>

<p>If the server specifies an origin host rather than "*", then it could also include Origin in the Vary response header to indicate to clients that server responses will differ based on the value of the Origin request header.</p>

<h3 id="Access-Control-Expose-Headers">Access-Control-Expose-Headers</h3>

<p>The {{HTTPHeader("Access-Control-Expose-Headers")}} header lets a server whitelist headers that browsers are allowed to access. For example:</p>

<pre class="brush: none notranslate">Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header
</pre>

<p>This allows the <code>X-My-Custom-Header</code> and <code>X-Another-Custom-Header</code> headers to be exposed to the browser.</p>

<h3 id="Access-Control-Max-Age">Access-Control-Max-Age</h3>

<p>The {{HTTPHeader("Access-Control-Max-Age")}} header indicates how long the results of a preflight request can be cached. For an example of a preflight request, see the above examples.</p>

<pre class="brush: none notranslate">Access-Control-Max-Age: &lt;delta-seconds&gt;
</pre>

<p>The <code>delta-seconds</code> parameter indicates the number of seconds the results can be cached.</p>

<h3 id="Access-Control-Allow-Credentials">Access-Control-Allow-Credentials</h3>

<p>The {{HTTPHeader("Access-Control-Allow-Credentials")}} header Indicates whether or not the response to the request can be exposed when the <code>credentials</code> flag is true. When used as part of a response to a preflight request, this indicates whether or not the actual request can be made using credentials. Note that simple <code>GET</code> requests are not preflighted, and so if a request is made for a resource with credentials, if this header is not returned with the resource, the response is ignored by the browser and not returned to web content.</p>

<pre class="brush: none notranslate">Access-Control-Allow-Credentials: true
</pre>

<p><a class="internal" href="#Requests_with_credentials">Credentialed requests</a> are discussed above.</p>

<h3 id="Access-Control-Allow-Methods">Access-Control-Allow-Methods</h3>

<p>The {{HTTPHeader("Access-Control-Allow-Methods")}} header specifies the method or methods allowed when accessing the resource. This is used in response to a preflight request. The conditions under which a request is preflighted are discussed above.</p>

<pre class="brush: none notranslate">Access-Control-Allow-Methods: &lt;method&gt;[, &lt;method&gt;]*
</pre>

<p>An example of a <a class="internal" href="#Preflighted_requests">preflight request is given above</a>, including an example which sends this header to the browser.</p>

<h3 id="Access-Control-Allow-Headers">Access-Control-Allow-Headers</h3>

<p>The {{HTTPHeader("Access-Control-Allow-Headers")}} header is used in response to a <a class="internal" href="#Preflighted_requests">preflight request</a> to indicate which HTTP headers can be used when making the actual request.</p>

<pre class="brush: none notranslate">Access-Control-Allow-Headers: &lt;field-name&gt;[, &lt;field-name&gt;]*
</pre>

<h2 id="The_HTTP_request_headers">The HTTP request headers</h2>

<p>This section lists headers that clients may use when issuing HTTP requests in order to make use of the cross-origin sharing feature. Note that these headers are set for you when making invocations to servers. Developers using cross-site {{domxref("XMLHttpRequest")}} capability do not have to set any cross-origin sharing request headers programmatically.</p>

<h3 id="Origin">Origin</h3>

<p>The {{HTTPHeader("Origin")}} header indicates the origin of the cross-site access request or preflight request.</p>

<pre class="brush: none notranslate">Origin: &lt;origin&gt;
</pre>

<p>The origin is a URI indicating the server from which the request initiated. It does not include any path information, but only the server name.</p>

<div class="note"><strong>Note:</strong> The <code>origin</code> can be the empty string; this is useful, for example, if the source is a <code>data</code> URL.</div>

<p>Note that in any access control request, the {{HTTPHeader("Origin")}} header is <strong>always</strong> sent.</p>

<h3 id="Access-Control-Request-Method">Access-Control-Request-Method</h3>

<p>The {{HTTPHeader("Access-Control-Request-Method")}} is used when issuing a preflight request to let the server know what HTTP method will be used when the actual request is made.</p>

<pre class="brush: none notranslate">Access-Control-Request-Method: &lt;method&gt;
</pre>

<p>Examples of this usage can be <a class="internal" href="#Preflighted_requests">found above.</a></p>

<h3 id="Access-Control-Request-Headers">Access-Control-Request-Headers</h3>

<p>The {{HTTPHeader("Access-Control-Request-Headers")}} header is used when issuing a preflight request to let the server know what HTTP headers will be used when the actual request is made.</p>

<pre class="brush: none notranslate">Access-Control-Request-Headers: &lt;field-name&gt;[, &lt;field-name&gt;]*
</pre>

<p>Examples of this usage can be <a class="internal" href="#Preflighted_requests">found above</a>.</p>

<h2 id="Specifications">Specifications</h2>

<table class="standard-table">
 <tbody>
  <tr>
   <th scope="col">Specification</th>
   <th scope="col">Status</th>
   <th scope="col">Comment</th>
  </tr>
  <tr>
   <td>{{SpecName('Fetch', '#cors-protocol', 'CORS')}}</td>
   <td>{{Spec2('Fetch')}}</td>
   <td>New definition; supplants <a href="https://www.w3.org/TR/cors/">W3C CORS</a> specification.</td>
  </tr>
 </tbody>
</table>

<h2 id="Browser_compatibility">Browser compatibility</h2>

<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>

<p>{{Compat("http.headers.Access-Control-Allow-Origin")}}</p>

<h3 id="Compatibility_notes">Compatibility notes</h3>

<ul>
 <li>Internet Explorer 8 and 9 expose CORS via the <code>XDomainRequest</code> object, but have a full implementation in IE 10.</li>
 <li>While Firefox 3.5 introduced support for cross-site XMLHttpRequests and Web Fonts, certain requests were limited until later versions. Specifically, Firefox 7 introduced the ability for cross-site HTTP requests for WebGL Textures, and Firefox 9 added support for Images drawn on a canvas using <code>drawImage</code>.</li>
</ul>

<h2 id="See_also">See also</h2>

<ul>
 <li><a class="external" href="https://arunranga.com/examples/access-control/">Code Samples Showing <code>XMLHttpRequest</code> and Cross-Origin Resource Sharing</a></li>
 <li><a href="https://github.com/jackblackevo/cors-jsonp-sample">Client-Side &amp; Server-Side (Java) sample for Cross-Origin Resource Sharing (CORS)</a></li>
 <li><a class="internal" href="/en-US/docs/Web/HTTP/Server-Side_Access_Control">Cross-Origin Resource Sharing From a Server-Side Perspective (PHP, etc.)</a></li>
 <li><a class="external" href="http://www.w3.org/TR/cors/">Cross-Origin Resource Sharing specification</a></li>
 <li>{{domxref("XMLHttpRequest")}}</li>
 <li><a href="/en-US/docs/Web/API/Fetch_API">Fetch API</a></li>
 <li><a class="external" href="http://www.kendoui.com/blogs/teamblog/posts/11-10-03/using_cors_with_all_modern_browsers.aspx">Using CORS with All (Modern) Browsers</a></li>
 <li><a href="http://www.html5rocks.com/en/tutorials/cors/">Using CORS - HTML5 Rocks</a></li>
 <li><a href="https://stackoverflow.com/questions/43871637/no-access-control-allow-origin-header-is-present-on-the-requested-resource-whe/43881141#43881141">Stack Overflow answer with “how to” info for dealing with common problems</a>:
  <ul>
   <li>How to avoid the CORS preflight</li>
   <li>How to use a CORS proxy to get around <em>“No Access-Control-Allow-Origin header”</em></li>
   <li>How to fix <em>“Access-Control-Allow-Origin header must not be the wildcard”</em></li>
  </ul>
 </li>
</ul>