Skip to content

Instantly share code, notes, and snippets.

@kirilkirkov
Created August 27, 2015 13:44
Show Gist options
  • Save kirilkirkov/e134198d0493dd0bc69a to your computer and use it in GitHub Desktop.
Save kirilkirkov/e134198d0493dd0bc69a to your computer and use it in GitHub Desktop.
CORS (Cross-Origin Resource Sharing) - Ajax Request to another domain
<h2>CORS (Cross-Origin Resource Sharing)</h2>
<p>When you do a cross-origin request, the browser sends <code>Origin</code> header with the current domain value.</p>
<pre>
Origin: http://zinoui.com</pre>
<p>When the server receives the request, check whether the origin header is within the allowed list, and sends a response with <code>Access-Control-Allow-Origin</code></p>
<pre>
Access-Control-Allow-Origin: http://zinoui.com</pre>
<p>If you want to allow access for all, use a wildcard &#39;*&#39;</p>
<pre>
Access-Control-Allow-Origin: *</pre>
<p>Simple request<br />
A simple cross-domain request is one that:</p>
<ul>
<li>Does not send custom headers (such as X-PINGOTHER, etc.)</li>
<li>Only uses GET, POST or HEAD request methods</li>
</ul>
<p>This is how the simple <strong>cross domain ajax request</strong> should looks like:</p>
<pre>
&lt;script type=&quot;text/javascript&quot;&gt;
// Using jQuery
$.get(&quot;http://www.example.org/ajax.php&quot;).done(function (data) {
console.log(data);
});
// Using XMLHttpRequest
var xhr = new XMLHttpRequest();
xhr.open(&quot;GET&quot;, &quot;http://www.example.org/ajax.php&quot;, true);
xhr.onload = function () {
console.log(xhr.responseText);
};
xhr.send();
&lt;/script&gt;</pre>
<p>Preflighted requests<br />
Setting custom headers to XHR triggers a preflight request. With simple words this mean that preflight request first send an HTTP request by the OPTIONS method to the resource on the remote domain, in order to ensure that the request is safe to send. According W3C for non same origin requests using the HTTP GET method a preflight request is made when headers other than <code>Accept</code> and <code>Accept-Language</code> are set.</p>
<pre>
&lt;script type=&quot;text/javascript&quot;&gt;
// Using jQuery
$.ajax({
type: &quot;GET&quot;,
headers: {&quot;X-My-Custom-Header&quot;: &quot;some value&quot;},
url: &quot;http://www.example.org/ajax.php&quot;
}).done(function (data) {
console.log(data);
});
// Using XMLHttpRequest
var xhr = new XMLHttpRequest();
xhr.open(&quot;GET&quot;, &quot;http://www.example.org/ajax.php&quot;, true);
xhr.setRequestHeader(&quot;X-My-Custom-Header&quot;, &quot;some value&quot;);
xhr.onload = function () {
console.log(xhr.responseText);
};
xhr.send();
&lt;/script&gt;</pre>
<p>Request with credentials<br />
By default, for non same origin request, browsers will not send credentials (such a HTTP Cookies, HTTP Authentication and client-side SSL certificates). A specific attribute has to be set on the XMLHttpRequest object when it is invoked.</p>
<pre>
&lt;script type=&quot;text/javascript&quot;&gt;
// Using jQuery
$.ajax({
xhrFields: {
withCredentials: true
},
type: &quot;GET&quot;,
url: &quot;http://www.example.org/ajax.php&quot;
}).done(function (data) {
console.log(data);
});
// Using XMLHttpRequest
var xhr = new XMLHttpRequest();
xhr.open(&quot;GET&quot;, &quot;http://www.example.org/ajax.php&quot;, true);
xhr.withCredentials = true;
xhr.onload = function () {
console.log(xhr.responseText);
};
xhr.send();
&lt;/script&gt;</pre>
<p>The Response<br />
Let&#39;s see how the server response should looks like</p>
<pre>
&lt;?php
// http://www.example.org/ajax.php
if (!isset($_SERVER[&#39;HTTP_ORIGIN&#39;])) {
// This is not cross-domain request
exit;
}
$wildcard = FALSE; // Set $wildcard to TRUE if you do not plan to check or limit the domains
$credentials = FALSE; // Set $credentials to TRUE if expects credential requests (Cookies, Authentication, SSL certificates)
$allowedOrigins = array(&#39;http://zinoui.com&#39;, &#39;http://jsfiddle.net&#39;);
if (!in_array($_SERVER[&#39;HTTP_ORIGIN&#39;], $allowedOrigins) &amp;&amp; !$wildcard) {
// Origin is not allowed
exit;
}
$origin = $wildcard &amp;&amp; !$credentials ? &#39;*&#39; : $_SERVER[&#39;HTTP_ORIGIN&#39;];
header(&quot;Access-Control-Allow-Origin: &quot; . $origin);
if ($credentials) {
header(&quot;Access-Control-Allow-Credentials: true&quot;);
}
header(&quot;Access-Control-Allow-Methods: POST, GET, OPTIONS&quot;);
header(&quot;Access-Control-Allow-Headers: Origin&quot;);
header(&#39;P3P: CP=&quot;CAO PSA OUR&quot;&#39;); // Makes IE to support cookies
// Handling the Preflight
if ($_SERVER[&#39;REQUEST_METHOD&#39;] == &#39;OPTIONS&#39;) {
exit;
}
// Response
header(&quot;Content-Type: application/json; charset=utf-8&quot;);
echo json_encode(array(&#39;status&#39; =&gt; &#39;OK&#39;));
?&gt;</pre>
<p>Few notes:</p>
<ul>
<li>A wildcard &#39;*&#39; cannot be used in the &#39;Access-Control-Allow-Origin&#39; header when the credentials flag is <code>true</code>.</li>
<li>Gecko 11.0 (Firefox 11.0 / Thunderbird 11.0 / SeaMonkey 2.8) removed support for using the <code>withCredentials</code> attributes when performing synchronous requests.</li>
</ul>
<h3>Browser support</h3>
<p>Chrome 3+, Firefox 3.5+, IE 10+, Opera 12+, Safari 4+</p>
@kirilkirkov
Copy link
Author

Interested website: http://enable-cors.org

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment