Get over CORS error when developing locally


Why you're here?

You are developing a frontend and running a development server, your server is running on your localhost interface on port 8080. In order to develop the frontend app you need the api from localhost running on port 8000.

You write your frontend code and an set the api endpoint to http://localhost:8000/api/v1 and you access you frontend dev server http://localhost:8080/. Notice that the difference in ports.

When you visit the frontend you get an CORS error. Your browser protects you agains yourself.

Why does this happen?

Browsers block accessing resources from JavaScript are limited to the same origin. CORS stands for cross-origin resource sharing, it enables us to define the exception to the rule.

How to solve this?

There are ~~2 elegant ways~~ 4 elegant ways to solve this.

Use a browser plugin

Firefox: Corser plugin

For firefox there is CORS Everywhere, but it has a problem. If you enable that plugin you will have to be carefull when you will have it enabled or disabled. You can use Corser that has domain rules where you whitelist the domains you want to use https://addons.mozilla.org/en-US/firefox/addon/corser/

Chrome: Allow-Control-Allow-Origin: * plugin

For Chrome there is Allow-Control-Allow-Origin: * plugin.

Add a header to the API

In your framework for every API response add a header Allow-Control-Allow-Origin: * .

Configure the development tools to proxy the API calls

Depending on your stack you can configure the frontend development server to proxy the /api requests to another server.

This depends on your frontend stack. If you use webpack as packaging, you can use webpack-dev-server.

But what to do if your development server does not support this?

Use traefik as a proxy

I recently discovered a Golang reverse proxy called Traefik. It has some neat features:

  • it's distributed as staticaly compiled ELF
  • it can be dynamicaly configured with common container orchestrators (Kubernetes, Swarm ...), api and files
  • simple TLS/SSL certificates with ACME (Let's encrypt)

You need to do 3 steps:

  1. Download traefik from https://github.com/containous/traefik/releases

  2. Create configuration file traefik.toml

    Create the folowing configuration:

    [entryPoints]
      [entryPoints.http]
      address = ":9000"
    
    [file]
    
    [frontends]
      [frontends.spa]
      entryPoints = ["http"]
      backend = "dev_server"
      [frontends.api]
      entryPoints = ["http"]
      backend = "django"
        [frontends.api.routes.api]
        rule = "PathPrefix: /api/"
    
    [backends]
      [backends.dev_server]
        [backends.dev_server.servers]
          [backends.dev_server.servers.elmreactor]
          url = "http://localhost:8080"
    
      [backends.django]
        [backends.django.servers]
          [backends.django.servers.server1]
          url = "http://localhost:8000"
    

    You will be able to connect to http://localhost:9000 all the ali calls to /api/ will go to localhost:8000 and all other request will go to localhost:8080 .

  3. Start traefik with ./traefik -c traefik.toml

Access the proxy on http://localhost:9000

Updates

Update 1: 2018-02-26

Updated the number of solutions from 2 to 4. Thanks to Andraž Bajt - edific for recomending a simple add on and Marko Mrdjenovič - friedcell for adding the correct headers to the API itself (not the proxy). For more information see bellow.

If you have any questions or suggestions contact me on twitter @brodul :)