The Official Ionic Blog

Build amazing native and progressive web apps with HTML5

If you’ve used ionic serve or ionic run with live reload and accessing external API endpoints, chances are you’ve run into some CORS
issues. They usually look something like this:

XMLHttpRequest cannot load http://api.ionic.com/endpoint.
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://localhost:8100' is therefore not allowed access.

So what is CORS, and why is it a problem?

What is CORS?

CORS = Cross origin resource sharing.

The origin is the host you are currently viewing.
Since you’re at http://ionicframework.com/blog/handling-cors-issues-in-ionic, the origin is ionicframework.com.

Say we send an AJAX request to http://cors.api.com/api, your host origin will be specified by the Origin header that is automatically included for CORS requests by the browser. Since ionicframework.com does not match the host of api.com, our request from ionicframework.com must ask the server for approval before we can access the resource, in the form of an HTTP OPTIONS request header.

If we get the error above, then we may not access the resource from the server.

Let’s take a look what your origin will be when you’re running your app via ionic serve, ionic run, or ionic run -l.

Running in the browser

What happens when you run ionic serve?

  • A local web server is started up.
  • Your browser is opened to point at the local server address.

This starts you off looking at your app loaded in a browser on your computer with the address http://localhost:8100 (if you chose localhost).

Your origin will be localhost:8100.

Any AJAX request sent out to a host other than localhost:8100 will have localhost:8100 as its origin and thus will require a CORS preflight request to see if it can access the resource.

Running on a device

What happens when you run ionic run?

  • Your files for the app are copied to the device (or simulator).
  • The app runs, thus firing a browser on the phone/simulator to run the files that were copied over, something like: file://some/path/www/index.html.

Your origin will not exist, since you are running off of a file:// URI; therefore, any request outwards will not require a CORS request.

Running on a device with livereload

What happens when you run ionic run -l?

  • A local web server is started up.
  • The app runs, thus firing a browser on the phone/simulator to run the files from the server http://192.168.1.1:8100 (or whatever your local IP address is).

Your origin will be 192.168.1.1:8100.

Any AJAX request sent out to a host other than 192.168.1.1:8100 will require a CORS preflight request to see if it can access the resource.

Dealing with CORS in Ionic

CORS is only an issue when we are running or testing our app when running ionic serve or ionic run -l.

There are two ways to solve the issue: The first, and easier, solution is to just allow all origins from your API endpoint. However, we can’t always control the endpoint we are accessing. What we need, then, is a request that does not specify an origin.

We can do this by using a proxy server. Let’s look how the Ionic CLI provides
an easily configurable proxy server.

The Ionic CLI proxy server

A quick definition about proxies:

In computer networks, a proxy server is a server (a computer system or an application) that acts as an intermediary for requests from clients seeking resources from other servers.

What we’d need to do to get around these CORS issues is have a proxy server that
will take our requests, issue a new request to the API endpoint, receive the response, and forward it back to our app so we can get around CORS issues.

The Ionic CLI introduced the ability to have a proxy server issue requests for you to get around any CORS issues you may have.

Since the server is sending a fresh request to your destination, there will be no origin and therefore, no CORS needed. It is important to note that the browser adds in the Origin header.

Setting up the proxy server

Please note, these are only needed for ionic serve and ionic run -l.

First we will need to set up the proxies in our ionic.project file. This will tell our Ionic server to listen to those paths and forward those requests on to the destination url.

In our app, we will need to replace our endpoint URLS to be set to the proxy server address for when we are running serve or run -l.

We can make this a bit easier by using some gulp tasks using the replace module to swap out the URLs.

The suggested method is to set up an Angular Constant to point at the API we’re trying to proxy out.

This is the approach we will take below. We will also set up an Angular Service to use that API Endpoint to get data.

Setting up the proxy urls

Let’s say we want to access http://cors.api.com/api, which is not allowing our origin from localhost.

The proxies settings contain two things: the path you use to access them on your local Ionic server, and the proxyUrl you’d ultimately like to reach from the API call.

Set up your ionic.project file to be something like:

{
  "name": "proxy-example",
  "app_id": "",
  "proxies": [
    {
      "path": "/api",
      "proxyUrl": "http://cors.api.com/api"
    }
  ]
}

Run your server with ionic serve.

As we specified above, when you access the ionic server at the path http://localhost:8100/api, it will proxy requests out to http://cors.api.com/api on your behalf.

Thus, no CORS is required.

Set up Angular Constant

It’s quite easy to set up your API endpoints as Angular Constants.

Below, we’ve specified the ApiEndpoint to be our proxied URL right now.

Later, we can use our production url as a constant.

angular.module('starter', ['ionic', 'starter.controllers', 'starter.services'])
.constant('ApiEndpoint', {
  url: 'http://localhost:8100/api'
})
// For the real endpoint, we'd use this
// .constant('ApiEndpoint', {
//  url: 'http://cors.api.com/api'
// })

Once this is done, you can use the constant anywhere in your app, by including
ApiEndpoint as a dependency, as shown below in the service.

Setting up Angular Service

angular.module('starter.services', [])

//NOTE: We are including the constant `ApiEndpoint` to be used here.
.factory('Api', function($http, ApiEndpoint) {
  console.log('ApiEndpoint', ApiEndpoint)

  var getApiData = function() {
    return $http.get(ApiEndpoint.url + '/tasks')
      .then(function(data) {
        console.log('Got some data: ', data);
        return data;
      });
  };

  return {
    getApiData: getApiData
  };
})

Automating URL switches with Gulp

For this process, we’ll need to modify our gulpfile.js to add in two tasks to add our proxy url or remove our proxy url.

Start by first installing the replace module – npm install --save replace.

// `npm install --save replace`
var replace = require('replace');
var replaceFiles = ['./www/js/app.js'];

gulp.task('add-proxy', function() {
  return replace({
    regex: "http://cors.api.com/api",
    replacement: "http://localhost:8100/api",
    paths: replaceFiles,
    recursive: false,
    silent: false,
  });
})

gulp.task('remove-proxy', function() {
  return replace({
    regex: "http://localhost:8100/api",
    replacement: "http://cors.api.com/api",
    paths: replaceFiles,
    recursive: false,
    silent: false,
  });
})

Final Words

This tutorial showed you one way to handle your CORS issues when running ionic serve or ionic run -l.

We know that it can be a hassle to swap out your API url endpoints when switching between ionic serve and ionic run -l. One thing that could be suggested is to have a gulp startup process.

The easiest way to handle the CORS problem is to ultimately ask your API provider to allow all hosts. However, this isn’t always an option.

Using the Angular constant and the replace module will give us a happy medium, in which we can work around CORS.

If you need a solid example, take a look at this sample project.

This is everything you’d need to access an API server that restricts CORS.

If you have any questions, issues, or ideas, please leave a comment below or contact us on twitter or github.

  • Bhavik

    I need to call a Js file that returns a JS function like DoSomething(JsonData). I’m planning to get this file using $http.get on my /#/tab/home page,
    I’ve configured my project file as below. however, i’m still getting Cors error when I try ionic serve.
    would someone please help me to resolve this issue. Also I’m wondering about the easiest way to handle the JS function (only content in the file is a JS function(that has JSON data as argument) that returns from the $http.get to get the JSON data from JS function.
    “proxies”: [

    {

    “path”: “/tab/home”,

    “proxyUrl”: “http://otherdomain/api/”

    }

    like JS file returns doSomething(JSONDATALoad);

  • http://www.madeinace.com Ace Han

    Hi, this article addresses the situation about developing a hybrid app on CORS issue. What if it comes to releasing a hybrid app to apk/dmg?

    Let’s say I do have control on the server side. I don’t want ACCESS-CONTROL-ALLOW-ORIGIN set to *
    and from stackoverflow like http://stackoverflow.com/questions/14003332/access-control-allow-origin-wildcard-subdomains-ports-and-protocols#comment-33591614, it suggests set ACCESS-CONTROL-ALLOW-ORIGIN to null to address scheme with file:// situation

    Won’t that be equal to * on server side if any other hybrid app developer knows about your endpoint uri?

    I’ve been googling around and get no where, all the existing answers are suggesting *

    As this article addresses CORS issue, any suggestion on this particular situation?

  • Nabi

    Josh – this works like a charm!!! Thank you so much for your effort!
    However, there is one issue which we are facing for our development on localhost: redirecting to https with self signed or untrusted certificates fail with the following error message on the cli output:

    ✗ Error: self signed certificate
    at Error (native)
    at TLSSocket. (_tls_wrap.js:927:36)
    at TLSSocket.emit (events.js:104:17)
    at TLSSocket._finishInit (_tls_wrap.js:458:8)

    That means we currently have no chance to connect to any https server via the proxy because it has an invalid certificate. I believe there is a good reason to add some configuration that allows accepting even invalid certs, here is our use case:

    1. we use ionic serve

    2. we use this config:

    {
    “name”: “proxy-example”,
    “app_id”: “”,
    “proxies”: [
    {
    “path”: “/api”,
    “proxyUrl”: “https://localhost:8181/api”
    }
    ]
    }

    The requests shall be redirected to a local Tomcat server and we need to connect via https.

    3. The Tomcat server that runs on localhost port 8181 is the real backend. We access it only during development.

    4. In future we might even want to use a server not on localhost (i.e. the integration/test server) server during development, however, again only https is possible

    In a Java environment I would simply write my own ProxyServlet. Unfortunately, I have no idea how to handle this with Ionic now, any help? There is no support for this as of now, correct?

    • Nabi

      Ok, it really seems that ionic currently has no support for this. This is how you have to modify Ionic to make things work:

      1. find the Ionic serve.js file, i.e. /usr/share/nodejs/node-v0.12.0/lib/node_modules/ionic/lib/serve.js

      2. search for this code:
      var opts = url.parse(proxy.proxyUrl);
      if(proxy.proxyNoAgent)
      opts.agent = false;

      3. Add this line after the if statement:

      opts.rejectUnauthorized = proxy.rejectUnauthorized === true;

      4. Add rejectUnauthorized = false to your proxy configuration:

      {
      “name”: “proxy-example”,
      “app_id”: “”,
      “proxies”: [
      {
      “path”: “/api”,
      “proxyUrl”: “https://localhost:8181/api”,
      “rejectUnauthorized” : false
      }
      ]
      }

      This works just fine, because Ionic uses internally proxy-middleware (see https://www.npmjs.com/package/proxy-middleware). proxy-middleware supports any of the https request options, for more information see https://nodejs.org/api/https.html#https_https_request_options_callback
      rejectUnauthorized is a setting from proxy-middleware 🙂

      That works like a charm. I hope the Ionic guys will merge the one line of code into their distribution so that everyone can use this 🙂

      -Nabi

    • pliablepixels

      Nabi, did you find a workaround for this?

  • Andrea

    its doesn’t works for my app project: I’m trying to call a webservice to create a ion list.

    I followed the tutorial and this are my setting:
    ionic.project:
    {
    “name”: “lego”,
    “app_id”: “”,
    “proxies”: [
    {
    “path”: “/api”,
    “proxyUrl”: “http://brickset.com/webservices/brickset.asmx”
    }
    ]

    gulpfile.js:
    var replace = require(‘replace’);
    var replaceFiles = [‘./www/js/app.js’];

    gulp.task(‘add-proxy’, function() {
    return replace({
    regex: “http://brickset.com/webservices/brickset.asmx”,
    replacement: “http://192.168.1.82:8100/”,
    paths: replaceFiles,
    recursive: false,
    silent: false,
    });
    });
    gulp.task(‘remove-proxy’, function() {
    return replace({
    regex: “http://192.168.1.82:8100/”,
    replacement: “http://brickset.com/webservices/brickset.asmx”,
    paths: replaceFiles,
    recursive: false,
    silent: false,
    });
    })

    service.js:

    angular.module(‘starter.services’, [])
    .factory(‘Api’, function($http, $q, ApiEndpoint) {
    console.log(‘ApiEndpoint’, ApiEndpoint)
    var getApiData = function() {
    var q = $q.defer();
    $http.get(ApiEndpoint.url)
    .success(function(data) {
    console.log(‘Got some data: ‘, data)
    q.resolve(data);
    })
    .error(function(error){
    console.log(‘Had an error’)
    q.reject(error);
    })
    return q.promise;
    }
    return {
    getApiData: getApiData
    };
    })

    controller.js:

    angular.module(‘starter.controllers’, [])
    .controller(‘DashCtrl’, function($scope, Api) {
    $scope.data = null;
    Api.getApiData()
    .then(function(result) {
    $scope.data = result.data;
    })
    })

    Can you help me please?

  • Rob_McB

    Thanks for this solution I was able to get it working with either my web browser on my machine while going through the proxy OR via a mobile when removing the proxy.

    I have added the Gulp tasks to replace the proxy. I assume when I now serve my Ionic app I have to specify the add-proxy task somehow and then when I build to iOS or Android then I have to run the remove-proxy task?

    Are you able to clarify if this is required and if so how to do it?

    Thanks

  • Mirko Nasato

    Since CORS is only an issue when running your app in development mode with ionic serve, and not when running as a mobile app packaged with Cordova, a simpler option is to just disable CORS altogether for local development. For Chrome for example there’s a plugin called “Allow-Control-Allow-Origin: *” that lets you disable CORS.

    • Mejd Nuaman

      Hi Mirko,

      Thanks for your suggestion. Could elaborate on your solution for the noobs among us (me!).

      Mejd

      • Mirko Nasato

        Here’s a step-by-step guide:

        1. Install this Chrome plugin: https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi
        2. There is not step 2.

        🙂

        • Julien Monty

          You saved my day 🙂

        • Ank

          This plugin doesn’t seem to work anymore. I have installed it, still continue to get the CORS error. Is it outdated?

        • http://www.tgerm.com/ Abhinav Gupta

          Sweet and simple, I was trying to find a way to disable this thing via chrome://flags but this plugin is way easier to pass along my dev team. Thanks @mirkonasato:disqus !

        • http://www.jiggmedia.com RJ Johnston

          AWESOME!! This should be at the top of this tutorial!!!!!!

    • david lyons

      Amazing!! thank you very much! I was getting crazy with proxies, hosts files, dns. And that’s it! easy peasy!!!

    • anjanigupta12

      Not working

    • http://dianariyanto.com/ Dian Ariyanto

      Thanksss….. work perfectly!

    • Dayan Lemos

      It didn’t work to me. I’m trying to access a redmine application.

  • fabioi

    I think there is an error

    var replaceFiles = [‘./www/js/app.js’];
    should be
    var replaceFiles = [‘./ionic.project’];

  • Nicolás Schürmann Lindemann

    great!, what happen if the url doesn’t have a prefix?, IE i want to make requests to http://www.bla.com and the url that i want to query is http://www.bla.com/here ???

  • Nicolás Schürmann Lindemann

    Works great the proxies. But at least for me is not true that is not needed when emulated. My app is throwing an error when i try to makes API calls from the emulator.

  • Jinett Andrea Morales Rivera

    Hello and tried this configuration did not work me. Someone tried it and it worked? Please

  • Chris Tiearney

    I’m having a problem with this setup. I’ve setup my .project file’s proxy with path “/api” and proxyUrl “http://localhost:8000/api” which is a Laravel app we are using for JWT authentication. When I try to make a POST request to “/api/authenticate” I get the following error in my ionic serve console output:

    ? Error: connect ECONNREFUSED
    at exports._errnoException (util.js:746:11)
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1010:19)

    Any ideas?

    • Lucas Cardoso Zago

      Same problem here, did you solve it?

      • Chris Tiearney

        ended up using a google chrome extension. its been mentioned a lot in the comments here. see @mirkonasato:disqus’s comment

  • KB

    Hello there, I am new to Ionic and the whole development. I have this error, can you explain what is it please?

    WebSocket connection to ‘ws://localhost:35729/livereload’ failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED

    Also thank you, this is really useful. Now I start to understand a little more of what is going.

  • Douglass Hock

    I am attempting to use Amazon AWS Javascript for Browser SDK. When running my ionic app in the browser my calls to AWS work. When I load the app in either the emulator/simulator or on the device I get a 403 response when attempting to call the Amazon AWS functions. The on difference I see on the request header is the Origin. On the desktop browser it is set to http://localhost:8100, but on the request sent from the emulators or devices that Origin is set to file://. Everything I have read so far would suggest that I would be having 403 issues with the desktop browser and not the app running on the device.

    • Douglass Hock

      Ok. Here is another update. I wrote a small test html page that just includes the Amazon SDK and was able to run this file both in the desktop browser and on the browser on my Android and iPhone devices. So, now I am wondering if the issue I am having is related to either ionic framework or more specifically AngularJS.

      • Slash

        I am having the same issue. Unfortunately, I am not finding supports or answers to solve this. did you manage to solve it?

        • Douglass Hock

          I am in the same situation… not finding support or answers. Thanks for sharing your feedback.

    • Douglass Hock

      Too make it easier for someone to assist, I have setup a github repository (https://github.com/doughock/aws_ec2_test ). This is a simple ionic blank app with the Amazon EC2 call in the index.html file.

      Synopsis

      This project is to help demonstrate a 403 Forbidden response when attempting to call describeInstances() from within an Ionic app on either an Android or iOS device (or in emulators). This same application, when run from a desktop browser, works and returns the expected results.

    • Slash

      I would appreciate if you had the solution for this to share it here. I have the same exact problem!

  • http://www.blacklime.co.uk/ Ken Whipday

    Also, you can disable CORS in Safari by enabling Develop (Preferences -> Advanced) then on the menu selecting Develop; Disable Cross-Origin Restrictions – courtesy of Nic Raboy, there are examples for other browsers on his blog https://blog.nraboy.com/2014/08/bypass-cors-errors-testing-apis-locally/

  • Luc BONNIN

    Thanks a lot, you saved my day.

    I’ve not used the gulp way. i’ve use window.cordova in an if and it is working for both dev and prod. See the forum topic here :
    http://forum.ionicframework.com/t/http-doesnt-work-on-ionic-serve-due-to-cors/36456

  • Sebastián Rojas Ricaurte

    I used replacement: “file://” in the gulp tasks because that was the origin I saw in request on the app when I use the chrome debbuger for the app runing in the device

  • Slash

    Unfortunately this methods don’t work with Angular routing feature. Still ionic has a lot to do in regards to local views. Notting that not all apps are server hosted or located. I have a nested app with hundreds of views routed through angular ui-inlcude so imagine…

  • Jonathan

    Thanks a lot! you saved my day

  • http://acom.com/ Paul Lang

    In Ionic2 you would set the proxies in ionic.config.js instead of ionic.project

  • Shashank Rao

    XMLHttpRequest cannot load

    https://accounts.google.com/o/oauth2/auth?access_type=offline&client_id=599…com/auth/userinfo.email%20https://www.googleapis.com/auth/userinfo.profile.

    No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘null’ is therefore not allowed access.

    I’am getting the response from the server..i.c google redirection…but at the same time its giving the error..Any idea..?

  • Shashank Rao

    i’am using rails server..and installed cors gems in the rails 4 server…Still getting the same….

  • kojilab

    I’m trying this but it seems like cookies are not carried along the way. And so subsequent calls to an API requiring cookies for auth fail. Any idea how to work around this? Thanks

  • Alan Barboza

    That’s saved my day, thanks!

  • dellagustin

    Hello, I solved this problem putting an apache server between my ionic app and my server where I was consuming services with cross domain requests.

    The important part of the apache config file looked like:

    # Redirec the rest requests
    ProxyPass /rest http://localhost:8080/MyApp/rest

    # Adjusts the cookies path
    ProxyPassReverseCookiePath /MyApp /

    # >>> CORS Headers for testing mobile app in the browser
    # >>>> Copy information from request to response

    ## Must accept “allow credentials” so that the cookies are passed
    ## When performing a cross domain request.
    ## see http://stackoverflow.com/questions/16882245/http-request-doesnt-send-cookies-cross-domain-in-angular-cors
    Header set Access-Control-Allow-Credentials “true”

    ## Cannot set to “*” when using withCredentials in HTTP Request
    SetEnvIf Origin “.*” allow_origin=$0
    Header set Access-Control-Allow-Origin “%{allow_origin}e”

    SetEnvIf Access-Control-Request-Method “.*” allow_method=$0
    Header set Access-Control-Allow-Methods “%{allow_method}e”

    SetEnvIf Access-Control-Request-Headers “.*” allow_headers=$0
    Header set Access-Control-Allow-Headers “%{allow_headers}e”

    # <<<<
    # <<< CORS Headers for testing mobile app in the browser

  • Chirag thaker

    work like charm !!

  • Chirag thaker

    proxyUrl tag in ionic.project working in “ionic serve” browser but when trying “ionic run -lc android” not working.

  • Prashant Mittal

    ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://localhost:8100’ is therefore not allowed access. If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.

    I have configured my .htaccess file using :

    Header add Access-Control-Allow-Origin “*”
    Header add Access-Control-Allow-Methods: “GET,POST,OPTIONS,DELETE,PUT”

    Once I was testing the application it runs fine on the browser but after sometime it start showing the same CORS error.

    can any suggest me the solution for this ?

  • hugo blanc

    Is it working with ionic V2 ?

  • Davo

    With WKWebView, CORS is also an issue while running the application on devices. Any chance you will extend the fantastic use of your proxy to let us include it in our built applications?

  • Kieran Desmond

    Hi, great resources and tips. Just wondering how I could apply the above when accessing google api”s. They accept localhost though not any up Base. For example, if I use ionic run android -l it uses the phones up – 192.168.x.0.1 as an example. This is rejected by Google except in ionic serve on my laptop as it’s localhost. Can I somehow redirect to localhost on the phone without an ip? Really appreciate any help. Relatively new to ionic.

    I’ve tried creating a proxy on one of my servers though I’d prefer to use ionic proxy if I can! Thanks all!

  • Andreas Pfr

    Thank you for the article. I followed the steps you provided but I still have a CORS issue:
    XMLHttpRequest cannot load file:///…/www/modules/home/view/home.html. Cross origin requests are only supported for HTTP.

  • Ntando Masondo

    you saved my day Mirko Nasato.this has been my problem for a few months

  • http://iocare.in Rajendra Khope

    What if Ive multiple endpoint server. As I work with WiFi sensors, I need to control all from one app. How to add multiple endpoint proxyUrl?

  • Wesley Pimentel

    Well, for one proxy it works fine.
    I think I’ve found a bug, when I put 2 proxies on ionic.config.json, it doesn’t work.

  • Alessandro Trebbi

    I have problems with credentials , after login the server ( via proxy ) does not recognize that user is logged ( i’m passing { withCredentials: true } with the post request , but it seems the credential do not arrive to server ; this works without proxy ). How can i fix ?