Please note, this is a STATIC archive of website developer.mozilla.org from 03 Nov 2016, cach3.com does not collect or store any user information, there is no "phishing" involved.

Revision 1130805 of Server-Side Access Control (CORS)

  • Revision slug: Web/HTTP/Server-Side_Access_Control
  • Revision title: Server-Side Access Control (CORS)
  • Revision id: 1130805
  • Created:
  • Creator: fscholz
  • Is current revision? No
  • Comment update
Tags: 

Revision Content

{{HTTPSidebar}}

Browsers send specific HTTP headers for cross-site requests initiated from within {{domxref("XMLHttpRequest")}} or the Fetch API. It also expects to see specific HTTP headers sent back with cross-site responses. An overview of these headers, including sample JavaScript code that initiates requests and processes responses from the server, as well as a discussion of each header, can be found in the HTTP Access Control (CORS) article and should be read as a companion article to this one. This article covers processing Access Control Requests and formulating Access Control Responses in PHP. The target audience for this article are server programmers or administrators. Although the code samples shown here are in PHP, similar concepts apply for ASP.net, Perl, Python, Java, etc.; in general, these concepts can be applied to any server-side programming environment that processes HTTP requests and dynamically formulates HTTP responses.

Discussion of HTTP headers

The article covering the HTTP headers used by both clients and servers is here, and should be considered prerequisite reading.

Working code samples

The PHP snippets (and the JavaScript invocations to the server) in subsequent sections are taken from the working code samples posted here. These will work in browsers that implement cross-site {{domxref("XMLHttpRequest")}}.

Simple cross-site requests

Simple Access Control Requests are initiated when:

  • An HTTP/1.1 {{HTTPMethod("GET")}} or a {{HTTPMethod("POST")}} is used as request method. In the case of a POST, the {{HTTPHeader("Content-Type")}} of the request body is one of application/x-www-form-urlencoded, multipart/form-data, or text/plain.
  • No custom headers are sent with the HTTP request (such as X-Modified, etc.)

In this case, responses can be sent back based on some considerations.

  • If the resource in question is meant to be widely accessed (just like any HTTP resource accessed by GET), than sending back the {{HTTPHeader("Access-Control-Allow-Origin")}}: * header will be sufficient, unless the resource needs credentials such as Cookies and HTTP Authentication information.
  • If the resource should be kept restricted based on requester domain, OR if the resource needs to be accessed with credentials (or sets credentials), then filtering by the request's {{HTTPHeader("Origin")}} header may be necessary, or at least echoing back the requester's Origin (e.g. {{HTTPHeader("Access-Control-Allow-Origin")}}: https://arunranga.com).  Additionally, the {{HTTPHeader("Access-Control-Allow-Credentials")}}: true header will have to be sent. This is discussed in a subsequent section.

The section on Simple Access Control Requests shows you the header exchanges between client and server. Here is a PHP code segment that handles a Simple Request:

<?php

// We'll be granting access to only the arunranga.com domain 
// which we think is safe to access this resource as application/xml

if($_SERVER['HTTP_ORIGIN'] == "https://arunranga.com") {
    header('Access-Control-Allow-Origin: https://arunranga.com');
    header('Content-type: application/xml');
    readfile('arunerDotNetResource.xml');
} else {    
  header('Content-Type: text/html');
  echo "<html>";
  echo "<head>";
  echo "   <title>Another Resource</title>";
  echo "</head>";
  echo "<body>",
       "<p>This resource behaves two-fold:";
  echo "<ul>",
         "<li>If accessed from <code>https://arunranga.com</code> it returns an XML document</li>";
  echo   "<li>If accessed from any other origin including from simply typing in the URL into the browser's address bar,";
  echo   "you get this HTML document</li>", 
       "</ul>",
     "</body>",
   "</html>";
}
?>

The above checks to see if the {{HTTPHeader("Origin")}} header sent by the browser (obtained through $_SERVER['HTTP_ORIGIN']) matches 'https://arunranga.com'. If yes, it returns {{HTTPHeader("Access-Control-Allow-Origin")}}: https://arunranga.com. This example can be seen running here.

Preflighted requests

Preflighted Access Control Requests occur when:

  • A method other than {{HTTPMethod("GET")}} or {{HTTPMethod("POST")}} is used, or if {{HTTPMethod("POST")}} is used with a {{HTTPHeader("Content-Type")}} other than one of application/x-www-form-urlencoded, multipart/form-data, or text/plain. For instance, if the Content-Type of the POST body is application/xml, a request is preflighted.
  • A custom header (such as X-PINGARUNER) is sent with the request.

The section on Preflighted Access Control Requests shows a header exchange between client and server. A server resource responding to a preflight requests needs to be able to make the following determinations:

  • Filtration based on {{HTTPHeader("Origin")}}, if any at all.
  • Response to an {{HTTPMethod("OPTIONS")}} request (which is the preflight request), including sending necessary values with {{HTTPHeader("Access-Control-Allow-Methods")}}, {{HTTPHeader("Access-Control-Allow-Headers")}} (if any additional headers are needed in order for the application to work), and, if credentials are necessary for this resource, {{HTTPHeader("Access-Control-Allow-Credentials")}}.
  • Response to the actual request, including handling POST data, etc.

Here is an example in PHP of handling a preflighted request:

<?php 

if($_SERVER['REQUEST_METHOD'] == "GET") {

  header('Content-Type: text/plain');
  echo "This HTTP resource is designed to handle POSTed XML input";
  echo "from arunranga.com and not be retrieved with GET"; 

} elseif($_SERVER['REQUEST_METHOD'] == "OPTIONS") {
  // Tell the Client we support invocations from arunranga.com and 
  // that this preflight holds good for only 20 days

  if($_SERVER['HTTP_ORIGIN'] == "https://arunranga.com") {
    header('Access-Control-Allow-Origin: https://arunranga.com');
    header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
    header('Access-Control-Allow-Headers: X-PINGARUNER');
    header('Access-Control-Max-Age: 1728000');
    header("Content-Length: 0");
    header("Content-Type: text/plain");
    //exit(0);
  } else {
    header("HTTP/1.1 403 Access Forbidden");
    header("Content-Type: text/plain");
    echo "You cannot repeat this request";
  }

} elseif($_SERVER['REQUEST_METHOD'] == "POST") {
  // Handle POST by first getting the XML POST blob, 
  // and then doing something to it, and then sending results to the client
 
  if($_SERVER['HTTP_ORIGIN'] == "https://arunranga.com") {
    $postData = file_get_contents('php://input');
    $document = simplexml_load_string($postData);
    
    // do something with POST data

    $ping = $_SERVER['HTTP_X_PINGARUNER'];
         
    header('Access-Control-Allow-Origin: https://arunranga.com');
    header('Content-Type: text/plain');
    echo // some string response after processing
  } else {
    die("POSTing Only Allowed from arunranga.com");
  }
} else {
    die("No Other Methods Allowed");
}
?>

Note the appropriate headers being sent back in response to the {{HTTPMethod("OPTIONS")}} preflight as well as to the {{HTTPMethod("POST")}} data. One resource thus handles the preflight as well as the actual request. In the response to the OPTIONS request, the server notifies the client that the actual request can indeed be made with the POST method, and header fields such as X-PINGARUNER can be sent with the actual request. This example can be seen running here.

Credentialed requests

Credentialed Access Control Requests – that is, requests that are accompanied by Cookies or HTTP Authentication information (and which expect Cookies to be sent with responses) – can be either Simple or Preflighted, depending on the request methods used.

In a Simple Request scenario, the request will be sent with Cookies (e.g. if the withCredentials flag is set on {{domxref("XMLHttpRequest")}}). If the server responds with {{HTTPHeader("Access-Control-Allow-Credentials")}}: true attached to the credentialed response, then the response is accepted by the client and exposed to web content. In a Preflighted Request, the server can respond with Access-Control-Allow-Credentials: true to the OPTIONS request.

Here is some PHP that handles credentialed requests:

<?php

if($_SERVER['REQUEST_METHOD'] == "GET") {
  header('Access-Control-Allow-Origin: https://arunranga.com');
  header('Access-Control-Allow-Credentials: true');
  header('Cache-Control: no-cache');
  header('Pragma: no-cache');
  header('Content-Type: text/plain');

  // First See if There Is a Cookie   
  if (!isset($_COOKIE["pageAccess"])) {
    setcookie("pageAccess", 1, time()+2592000);
    echo 'I do not know you or anyone like you so I am going to';
    echo 'mark you with a Cookie :-)';    
  } else {
    $accesses = $_COOKIE['pageAccess'];
    setcookie('pageAccess', ++$accesses, time()+2592000);
    echo 'Hello -- I know you or something a lot like you!';
    echo 'You have been to ', $_SERVER['SERVER_NAME'], ';
    echo 'at least ', $accesses-1, ' time(s) before!';
  }  
} elseif($_SERVER['REQUEST_METHOD'] == "OPTIONS") {
  // Tell the Client this preflight holds good for only 20 days
  if($_SERVER['HTTP_ORIGIN'] == "https://arunranga.com") {
    header('Access-Control-Allow-Origin: https://arunranga.com');
    header('Access-Control-Allow-Methods: GET, OPTIONS');
    header('Access-Control-Allow-Credentials: true');
    header('Access-Control-Max-Age: 1728000');
    header("Content-Length: 0");
    header("Content-Type: text/plain");
  } else {
    header("HTTP/1.1 403 Access Forbidden");
    header("Content-Type: text/plain");
    echo "You cannot repeat this request";
  }
} else {
  die("This HTTP Resource can ONLY be accessed with GET or OPTIONS");
}
?>

Note that in the case of credentialed requests, the Access-Control-Allow-Origin: header must not have a wildcard value of "*".   It must mention a valid origin domain. The example above can be seen running here.

Apache examples

Restrict access to certain URIs

One helpful trick is to use an Apache rewrite, environment variable, and headers to apply Access-Control-Allow-* to certain URIs. This is useful, for example, to constrain cross-origin requests to GET /api(.*).json requests without credentials:

RewriteRule ^/api(.*)\.json$ /api$1.json [CORS=True]
Header set Access-Control-Allow-Origin "*" env=CORS
Header set Access-Control-Allow-Methods "GET" env=CORS
Header set Access-Control-Allow-Credentials "false" env=CORS

See also

Revision Source

<div>{{HTTPSidebar}}
<p>Browsers send specific <a href="/en-US/docs/Web/HTTP/Headers">HTTP headers</a> for cross-site requests initiated from within {{domxref("XMLHttpRequest")}} or the <a href="/en-US/docs/Web/API/Fetch_API">Fetch API</a>. It also expects to see specific HTTP headers sent back with cross-site responses. An overview of these headers, including sample JavaScript code that initiates requests and processes responses from the server, as well as a discussion of each header, <a class="internal" href="/en-US/docs/Web/HTTP/Access_control_CORS">can be found in the HTTP&nbsp;Access Control (CORS) article</a> and should be read as a companion article to this one. This article covers processing <strong>Access Control Requests</strong> and formulating <strong>Access Control Responses</strong> in PHP. The target audience for this article are server programmers or administrators. Although the code samples shown here are in PHP, similar concepts apply for ASP.net, Perl, Python, Java, etc.; in general, these concepts can be applied to any server-side programming environment that processes HTTP&nbsp;requests and dynamically formulates HTTP responses.</p>

<h3 id="Discussion_of_HTTP_headers">Discussion of HTTP headers</h3>

<p>The article <a class="internal" href="/en-US/docs/Web/HTTP/Access_control_CORS">covering the HTTP&nbsp;headers used by both clients and servers is here</a>, and should be considered prerequisite reading.</p>

<h3 id="Working_code_samples">Working code samples</h3>

<p>The PHP snippets (and the JavaScript invocations to the server)&nbsp;in subsequent sections are taken from <a class="external" href="https://arunranga.com/examples/access-control/">the working code samples posted here.</a> These will work in browsers that implement cross-site {{domxref("XMLHttpRequest")}}.</p>

<h3 id="Simple_cross-site_requests">Simple cross-site requests</h3>

<p><a class="internal" href="/en-US/docs/Web/HTTP/Access_control_CORS#Simple_requests">Simple Access Control Requests</a> are initiated when:</p>

<ul>
 <li>An HTTP/1.1 {{HTTPMethod("GET")}} or a {{HTTPMethod("POST")}} is used as request method. In the case of a POST, the {{HTTPHeader("Content-Type")}} of the request body is one of <code>application/x-www-form-urlencoded</code>, <code>multipart/form-data</code>, or <code>text/plain.</code></li>
 <li>No custom headers are sent with the HTTP request (such as <code>X-Modified</code>, etc.)</li>
</ul>

<p>In this case, responses can be sent back based on some considerations.</p>

<ul>
 <li>If the resource in question is meant to be widely accessed (just like any HTTP resource accessed by GET), than sending back the {{HTTPHeader("Access-Control-Allow-Origin")}}<code>: *</code> header will be sufficient, <strong>unless</strong> the resource needs credentials such as <a href="/en-US/docs/Web/HTTP/Cookies">Cookies</a> and HTTP Authentication information.</li>
 <li>If the resource should be kept restricted based on requester domain, <strong>OR</strong> if the resource needs to be accessed with credentials (or sets credentials), then filtering by the request's {{HTTPHeader("Origin")}} header may be necessary, or at least echoing back the requester's <code>Origin</code> (e.g. {{HTTPHeader("Access-Control-Allow-Origin")}}<code>: <a class="external" href="https://arunranga.com" rel="freelink">https://arunranga.com</a></code>).&nbsp; Additionally, the {{HTTPHeader("Access-Control-Allow-Credentials")}}<code>: true</code> header will have to be sent. This is discussed in a <a class="internal" href="#Credentialed_Requests">subsequent section</a>.</li>
</ul>

<p>The section on <a class="internal" href="/en-US/docs/Web/HTTP/Access_control_CORS#Simple_requests">Simple Access Control Requests</a> shows you the header exchanges between client and server. Here is a PHP code segment that handles a Simple Request:</p>

<pre class="brush: php">
&lt;?php

// We'll be granting access to only the arunranga.com domain 
// which we think is safe to access this resource as application/xml

if($_SERVER['HTTP_ORIGIN'] == "https://arunranga.com") {
    header('Access-Control-Allow-Origin: https://arunranga.com');
    header('Content-type: application/xml');
    readfile('arunerDotNetResource.xml');
} else {    
  header('Content-Type: text/html');
  echo "&lt;html&gt;";
  echo "&lt;head&gt;";
  echo "   &lt;title&gt;Another Resource&lt;/title&gt;";
  echo "&lt;/head&gt;";
  echo "&lt;body&gt;",
       "&lt;p&gt;This resource behaves two-fold:";
  echo "&lt;ul&gt;",
         "&lt;li&gt;If accessed from &lt;code&gt;https://arunranga.com&lt;/code&gt; it returns an XML document&lt;/li&gt;";
  echo   "&lt;li&gt;If accessed from any other origin including from simply typing in the URL into the browser's address bar,";
  echo   "you get this HTML document&lt;/li&gt;", 
       "&lt;/ul&gt;",
     "&lt;/body&gt;",
   "&lt;/html&gt;";
}
?&gt;
</pre>

<p>The above checks to see if the {{HTTPHeader("Origin")}} header sent by the browser (obtained through $_SERVER['HTTP_ORIGIN']) matches '<a class="external" href="https://arunranga.com" rel="freelink">https://arunranga.com</a>'. If yes, it returns {{HTTPHeader("Access-Control-Allow-Origin")}}<code>: <a class="external" href="https://arunranga.com" rel="freelink">https://arunranga.com</a></code>. This example can be <a class="external" href="https://arunranga.com/examples/access-control/">seen running here</a>.</p>

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

<p><a class="internal" href="/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests">Preflighted Access Control Requests</a> occur when:</p>

<ul>
 <li>A method other than {{HTTPMethod("GET")}} or {{HTTPMethod("POST")}} is used, or if {{HTTPMethod("POST")}} is used with a {{HTTPHeader("Content-Type")}} <strong>other than</strong> one of <code>application/x-www-form-urlencoded</code>, <code>multipart/form-data</code>, or <code>text/plain</code>. For instance, if the <code>Content-Type</code> of the <code>POST</code> body is <code>application/xml</code>, a request is preflighted.</li>
 <li>A custom header (such as <code>X-PINGARUNER</code>) is sent with the request.</li>
</ul>

<p>The section on <a class="internal" href="/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests">Preflighted Access Control Requests</a> shows a header exchange between client and server. A server resource responding to a preflight requests needs to be able to make the following determinations:</p>

<ul>
 <li>Filtration based on {{HTTPHeader("Origin")}}, if any at all.</li>
 <li>Response to an {{HTTPMethod("OPTIONS")}} request (which is the preflight request), including sending necessary values with {{HTTPHeader("Access-Control-Allow-Methods")}}, {{HTTPHeader("Access-Control-Allow-Headers")}} (if any additional headers are needed in order for the application to work), and, if credentials are necessary for this resource, {{HTTPHeader("Access-Control-Allow-Credentials")}}.</li>
 <li>Response to the actual request, including handling <code>POST</code> data, etc.</li>
</ul>

<p>Here is an example in PHP of handling a <a class="internal" href="/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests">preflighted request</a>:</p>

<pre class="brush: php">
&lt;?php 

if($_SERVER['REQUEST_METHOD'] == "GET") {

  header('Content-Type: text/plain');
&nbsp; echo "This HTTP resource is designed to handle POSTed XML input";
  echo "from arunranga.com and not be retrieved with GET";&nbsp;

} elseif($_SERVER['REQUEST_METHOD'] == "OPTIONS") {
  // Tell the Client we support invocations from arunranga.com and 
  // that this preflight holds good for only 20 days

&nbsp; if($_SERVER['HTTP_ORIGIN'] == "https://arunranga.com") {
&nbsp;&nbsp;&nbsp; header('Access-Control-Allow-Origin: https://arunranga.com');
&nbsp;&nbsp;&nbsp; header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
&nbsp;&nbsp;&nbsp; header('Access-Control-Allow-Headers: X-PINGARUNER');
&nbsp;&nbsp;&nbsp; header('Access-Control-Max-Age: 1728000');
&nbsp;&nbsp;&nbsp; header("Content-Length: 0");
&nbsp;&nbsp;&nbsp; header("Content-Type: text/plain");
&nbsp;&nbsp;&nbsp; //exit(0);
&nbsp; } else {
&nbsp;&nbsp;&nbsp; header("HTTP/1.1 403 Access Forbidden");
&nbsp;&nbsp;&nbsp; header("Content-Type: text/plain");
&nbsp;&nbsp;&nbsp; echo "You cannot repeat this request";
  }

} elseif($_SERVER['REQUEST_METHOD'] == "POST") {
  // Handle POST by first getting the XML POST blob, 
  // and then doing something to it, and then sending results to the client
 
  if($_SERVER['HTTP_ORIGIN'] == "https://arunranga.com") {
    $postData = file_get_contents('php://input');
&nbsp;&nbsp;&nbsp; $document = simplexml_load_string($postData);
&nbsp;&nbsp;&nbsp; 
    // do something with POST data

&nbsp;&nbsp;&nbsp; $ping = $_SERVER['HTTP_X_PINGARUNER'];
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; header('Access-Control-Allow-Origin: https://arunranga.com');
&nbsp;&nbsp;&nbsp; header('Content-Type: text/plain');
&nbsp;&nbsp;&nbsp; echo // some string response after processing
&nbsp; } else {
&nbsp;   die("POSTing Only Allowed from arunranga.com");
  }
} else {
&nbsp;&nbsp;&nbsp; die("No Other Methods Allowed");
}
?&gt;
</pre>

<p>Note the appropriate headers being sent back in response to the {{HTTPMethod("OPTIONS")}} preflight as well as to the {{HTTPMethod("POST")}} data. One resource thus handles the preflight as well as the actual request. In the response to the <code>OPTIONS</code> request, the server notifies the client that the actual request can indeed be made with the <code>POST</code> method, and header fields such as <code>X-PINGARUNER</code> can be sent with the actual request. This example can be <a class="external" href="https://arunranga.com/examples/access-control/">seen running here</a>.</p>

<h3 id="Credentialed_requests">Credentialed requests</h3>

<p><a class="internal" href="/en-US/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials">Credentialed Access Control&nbsp;Requests</a> – that is, requests that are accompanied by <a href="/en-US/docs/Web/HTTP/Cookies">Cookies</a> or HTTP Authentication information (and which expect Cookies to be sent with responses) – can be either <a class="internal" href="/en-US/docs/Web/HTTP/Access_control_CORS#Simple_requests">Simple</a> or <a class="internal" href="/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests">Preflighted</a>, depending on the request methods used.</p>

<p>In a <a class="internal" href="/en-US/docs/Web/HTTP/Access_control_CORS#Simple_requests">Simple Request</a> scenario, the request will be sent with Cookies (e.g. if the <code><a href="/en-US/docs/Web/API/XMLHttpRequest/withCredentials">withCredentials</a></code> flag is set on {{domxref("XMLHttpRequest")}}). If the server responds with {{HTTPHeader("Access-Control-Allow-Credentials<code>")}}: true</code> attached to the credentialed response, then the response is accepted by the client and exposed to web content. In a <a class="internal" href="/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests">Preflighted Request</a>, the server can respond with <code>Access-Control-Allow-Credentials: true</code> to the <code>OPTIONS</code> request.</p>

<p>Here is some PHP that handles credentialed requests:</p>

<pre class="brush: php">
&lt;?php

if($_SERVER['REQUEST_METHOD'] == "GET") {
  header('Access-Control-Allow-Origin: https://arunranga.com');
  header('Access-Control-Allow-Credentials: true');
  header('Cache-Control: no-cache');
  header('Pragma: no-cache');
  header('Content-Type: text/plain');

  // First See if There Is a Cookie   
  if (!isset($_COOKIE["pageAccess"])) {
    setcookie("pageAccess", 1, time()+2592000);
    echo 'I do not know you or anyone like you so I am going to';
    echo 'mark you with a Cookie :-)';    
  } else {
    $accesses = $_COOKIE['pageAccess'];
    setcookie('pageAccess', ++$accesses, time()+2592000);
    echo 'Hello -- I know you or something a lot like you!';
    echo 'You have been to ', $_SERVER['SERVER_NAME'], ';
    echo 'at least ', $accesses-1, ' time(s) before!';
  }  
} elseif($_SERVER['REQUEST_METHOD'] == "OPTIONS") {
  // Tell the Client this preflight holds good for only 20 days
  if($_SERVER['HTTP_ORIGIN'] == "https://arunranga.com") {
    header('Access-Control-Allow-Origin: https://arunranga.com');
    header('Access-Control-Allow-Methods: GET, OPTIONS');
    header('Access-Control-Allow-Credentials: true');
    header('Access-Control-Max-Age: 1728000');
    header("Content-Length: 0");
    header("Content-Type: text/plain");
  } else {
    header("HTTP/1.1 403 Access Forbidden");
    header("Content-Type: text/plain");
    echo "You cannot repeat this request";
  }
} else {
  die("This HTTP Resource can ONLY be accessed with GET or OPTIONS");
}
?&gt;
</pre>

<p>Note that in the case of credentialed requests, the <code>Access-Control-Allow-Origin:</code> header <strong>must not</strong> have a wildcard value of "*".&nbsp;&nbsp; It <strong>must</strong> mention a valid origin domain. The example above can be seen <a class="external" href="https://arunranga.com/examples/access-control/">running here</a>.</p>

<h3 id="Apache_examples">Apache examples</h3>

<h4 id="Restrict_access_to_certain_URIs">Restrict access to certain URIs</h4>

<p>One helpful trick is to use an Apache rewrite, environment variable, and headers to apply <code>Access-Control-Allow-*</code> to certain URIs. This is useful, for example, to constrain cross-origin requests to <code>GET /api(.*).json</code> requests without credentials:</p>

<pre>
RewriteRule ^/api(.*)\.json$ /api$1.json [CORS=True]
Header set Access-Control-Allow-Origin "*" env=CORS
Header set Access-Control-Allow-Methods "GET" env=CORS
Header set Access-Control-Allow-Credentials "false" env=CORS
</pre>

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

<ul>
 <li><a class="external" href="https://arunranga.com/examples/access-control/">Examples of Access Control in Action</a></li>
 <li><a class="internal" href="/en-US/docs/Web/HTTP/Access_control_CORS">HTTP Access Control covering the HTTP headers</a></li>
 <li>{{domxref("XMLHttpRequest")}}</li>
 <li><a href="/en-US/docs/Web/API/Fetch_API">Fetch API</a></li>
</ul>
</div>
Revert to this revision