Javascript Cross-Origins CORS Fetch (Simple Example)

Welcome to a quick tutorial and example of how to perform a cross-origin fetch request in Javascript. Are you trying to do a fetch request to a different domain? Only to be denied with a “no Access-Control-Allow-Origin header is present” error?

To perform a cross-origin fetch call:

  1. On the first site, do a fetch call to the second site – fetch("http://second.com/page.php", { mode : "cors" });
  2. Allow cross-origin on the second site.
    • header("Access-Control-Allow-Origin: http://first.com");
    • // SCRIPT AS USUAL

Yes, it’s that simple. But let us walk through more details on CORS and how to set up virtual hosts on localhost (with XAMPP) for testing – Read on!

 

 

TLDR – QUICK SLIDES

[web_stories_embed url=”https://code-boxx.com/web-stories/javascript-cors-fetch/” title=”Javascript CORS Fetch With XAMPP” poster=”https://code-boxx.com/wp-content/uploads/2021/11/STORY-JS-20230518.webp” width=”360″ height=”600″ align=”center”]

Fullscreen Mode – Click Here

 

TABLE OF CONTENTS

 

 

WHAT IS CORS?

Before we get into the code example, let us answer the million-dollar question – What the heck is “CORS”?

 

CROSS-ORIGIN RESOURCE SHARING

Cross-Origin Resource Sharing (CORS) is an HTTP-header based mechanism that allows a server to indicate any origins (domain, scheme, or port) other than its own from which a browser should permit loading resources. MDN

In simple terms, making a request from your website http://first.com to another website http://second.com.

 

WHY IS CROSS-ORIGIN NOT ALLOWED BY DEFAULT!?

One word – Security. Imagine a world with no restrictions.

  • Anyone can submit forms to whatever site they please. Send data to whoever they like. There is no control, no verification.
  • Anyone can masquerade a request to delete accounts on other websites. Or even process transactions on another website.

Yep, it’s pure chaos. So the “default rule” is that http://second.com will only accept and process requests from http://second.com; All requests from http://first.com to http://second.com will be ignored.

 

ALLOW ORIGIN & CREDENTIALS

  • When we fire fetch("http://second.com") on http://first.com, this will send a HTTP header of Origin: http://first.com.
  • To accept the cross-origin call, http://second.com needs to respond with the HTTP header – Access-Control-Allow-Origin: http://first.com.
  • That pretty much seals the deal. If you want to also send cookies and credentials from first.com to second.com – Access-Control-Allow-Credentials: true.

P.S. For the “exact mechanics”, this post on Javascript.info gives a good breakdown of the exchange.

 

 

CORS FETCH WITH XAMPP

With that, let us now get into the example of setting up virtual hosts and running a CORS fetch. All on a local machine.

 

STEP 1) UPDATE THE HOSTS FILE

C:\Windows\System32\drivers\etc\hosts
127.0.0.1 site-a.com
127.0.0.1 site-b.com

For the uninitiated – Don’t need to panic, all that is happening here is a manual DNS override. That is, http://site-a.com and http://site-b.com will now resolve to localhost 127.0.0.1. If you are using IPV6, change it to ::1 instead.

P.S. Mac and Linux users, your hosts file is probably located at /etc/hosts. Although that may differ for different builds and versions.

 

STEP 2) APACHE VIRTUAL HOST

xampp\apache\conf\extra\httpd-vhosts.conf
# SITE-A.COM
<VirtualHost *>
  DocumentRoot "C:/sitea/"
  ServerName site-a.com
  <Directory "C:/sitea/">
    Options Indexes FollowSymLinks Includes ExecCGI
    AllowOverride All
    Require all granted
  </Directory>
</VirtualHost>
 
# SITE-B.COM
<VirtualHost *>
  DocumentRoot "C:/siteb/"
  ServerName site-b.com
  <Directory "C:/siteb/">
    Options Indexes FollowSymLinks Includes ExecCGI
    AllowOverride All
    Require all granted
  </Directory>
</VirtualHost>
  • Next, we need to create 2 folders – sitea/ and siteb/.
  • Edit httpd-vhosts.conf, create two virtual hosts for site-a.com and site-b.com – Map them to the respective sitea/ and siteb/ folder.

 

 

STEP 3) CROSS-ORIGIN FETCH REQUEST

sitea/3-fetch.html
<script>
function fetchCORS () {
  fetch("http://site-b.com/4-cors.php", {
    mode : "cors",
    credentials : "include"
  })
  .then(res => res.text())
  .then(txt => console.log(txt))
  .catch(err => console.error(err));
}
</script>
<input type="button" value="Fetch Request" onclick="fetchCORS()">

Now that the virtual hosts are ready, let us create a simple HTML page to fire a cross-origin fetch request.

P.S. It is already mode : "cors" by default in modern browsers. This is probably “extra”, but we still define it as “to be safe”.

P.P.S. With credentials : "include", the fetch request will also send cookies and credentials. If you don’t want this to happen, set credentials : "omit" instead.

 

STEP 4) CROSS-ORIGIN ALLOW

4A) LAZY CROSS-ORIGIN ALLOW

siteb/4-cors.php
<?php
// (A) THE LAZY WAY
header("Access-Control-Allow-Origin: *");
echo "It works!";

The lazy way to respond to cross-origin calls is to reply with Access-Control-Allow-Origin: *. Yes, this works, but take note:

  • Any website can call this script, it is more vulnerable to attacks.
  • With Allow-Origin: *, we cannot set Allow-Credentials: true; We cannot send cookies and credentials this way.

 

4B) BETTER CROSS-ORIGIN ALLOW

siteb/4-cors.php
<?php
// (B) SMARTER WAY
// (B1) GET REQUEST ORIGIN
if (array_key_exists("HTTP_ORIGIN", $_SERVER)) {
  $origin = $_SERVER["HTTP_ORIGIN"];
} else if (array_key_exists("HTTP_REFERER", $_SERVER)) {
  $origin = $_SERVER["HTTP_REFERER"];
} else {
  $origin = $_SERVER["REMOTE_ADDR"];
}
 
// (B2) ALLOWED DOMAINS
if (!in_array(
  parse_url($origin, PHP_URL_HOST),
  ["localhost", "site-a.com", "site-b.com"]
)) {
  http_response_code(403);
  exit("$origin not allowed");
}
 
// (B3) PROCEED
header("Access-Control-Allow-Origin: $origin");
header("Access-Control-Allow-Credentials: true");
echo "It works!";

This is a slightly smarter and safer way to deal with cross-domain calls. We counter-check the origin of the request, and respond only if it is an “allowed domain”. While this is not 100% foolproof, it will not respond to everyone at the very least.

 

 

DOWNLOAD & NOTES

Here is the download link to the example code, so you don’t have to copy-paste everything.

 

SORRY FOR THE ADS...

But someone has to pay the bills, and sponsors are paying for it. I insist on not turning Code Boxx into a "paid scripts" business, and I don't "block people with Adblock". Every little bit of support helps.

Buy Me A Coffee Code Boxx eBooks

 

EXAMPLE CODE DOWNLOAD

Click here for the source code on GitHub gist, just click on “download zip” or do a git clone. I have released it under the MIT license, so feel free to build on top of it or use it in your own project.

 

EXTRA BITS & LINKS

That’s all for the tutorial, and here is a small section on some extras and links that may be useful to you.

 

COMPATIBILITY CHECKS

Fetch is already well-supported across all modern browsers at the time of writing. But if you have to support legacy browsers – It is also possible to set CORS in XMLHttpRequest.

 

LINKS & REFERENCES

 

INFOGRAPHIC CHEATSHEET

CORS Fetch With XAMPP (Click To Enlarge)

 

THE END

Thank you for reading, and we have come to the end. I hope that it has helped you to better understand, and if you want to share anything with this guide, please feel free to comment below. Good luck and happy coding!