Ionic-cli: new live reload ignores cross domain policy (CORS)

Created on 8 Sep 2014  路  32Comments  路  Source: ionic-team/ionic-cli

For some reason the content loaded by serve using the new live reload feature does not allow cross origin resource sharing(CORS). So it ignores the cross domain policy set inside the config.xml

Most helpful comment

I managed to find a working solution !
You need to proxy your api server into livereload so that your web app will think the api server is actually the same as your livereload server.
Proxy configuration specs are here : https://github.com/driftyco/ionic-cli#advanced-serve-options
For example, if your api server is on 192.168.0.1:8888, you need to add this to your ionic.project :
"proxies": [
{
"path": "/api",
"proxyUrl": "http://192.168.0.1:8888/api"
}
]
And then, inside your app, you have to make your api calls like if it was local, directly from /api.

All 32 comments

Would you be able to describe your config setting, what files you're requesting, and how you're requesting them? I want to make sure I'm testing it correctly so I can replicate the same issue and fix it. Thanks

I try to load my data with the standard $http service.

$http.get(myURL)
   .success(...)
   .error(...);

All config settings are the default ones.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<widget id="com.ionicframework....." version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
  <name>.....</name>
  <description>
        ...
    </description>
  <author email="info@..." href="http://www......com/">
     .....
    </author>
  <content src="index.html"/>
  <access origin="*"/>
  <preference name="webviewbounce" value="false"/>
  <preference name="UIWebViewBounce" value="false"/>
  <preference name="DisallowOverscroll" value="true"/>
  <preference name="BackupWebStorage" value="none"/>
  <feature name="StatusBar">
    <param name="ios-package" value="CDVStatusBar" onload="true"/>
  </feature>
</widget>

Ok, so this is for ionic serve and not ionic run --livereload correct? Does it work on with ionic run --livereload?

No I only tested it with this command:

ionic run -l -c -s

So for a normal, non live reload app build: ionic run, everything works fine? But when running with live reload: ionic run -l, it no longer works? And the response from the http request does have the correct headers?

thats right, by the way. I'm on windows 8, runnning a android app (of course) and I tried it in genymotion

I think I have similar issue.
when running usual ionic run my cross domain request for data works fine, when doing ionic run -l -c -s it throws an error

[INFO:CONSOLE(0)] "XMLHttpRequest cannot load http://my-wordpress-blog.com/wp-json/posts?filter[posts_per_page]=2. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://192.168.2.137:8100' is therefore not allowed access.", source: http://192.168.2.137:8100/#/app/latest

Thanks for reporting this, I'll research this more and work on a solution. Thanks

I'm experiencing this issue too

i'm experiencing this too on OS X using safari for live reload

Same here. Using OS X, Live Reload in iOS Simulator.

Same issue here, on Ubuntu 14.04, using Genymotion and Ionic CLI 1.2.5.

Same issue with: ionic run -l -c -s android

same here on Windows, looks like it doesn't really depend on the OS

Hi,

any status on the source of the problem? I am facing this problem as well when emulating ios using OS X

Hi, I'm having the same problem. Running with ionic emulate -lcs throws CORS errors, whereas running just ionic emulate doesn't.

So basically with livereload ionic seems to be sending a different Origin header, which triggers CORS.

Here are the detailed errors/requests (with edited sensitive info).

with livereload

js error

OPTIONS http://myapi.com/endpoint Origin http://192.168.1.67:8100 is not allowed by Access-Control-Allow-Origin. ionic.bundle.js:16185
XMLHttpRequest cannot load http://myapi.com/endpoint. Origin http://192.168.1.67:8100 is not allowed by Access-Control-Allow-Origin. (index):1

request

Request URL:http://myapi.com/endpoint
Request Method:OPTIONS
Status Code:200 OK
Request Headers
  Access-Control-Request-Headers:accept, content-type
  Access-Control-Request-Method:POST
  Origin:http://192.168.1.67:8100
  Referer:http://192.168.1.67:8100/
  User-Agent:Mozilla/5.0 (Linux; Android 4.4.2; Android SDK built for x86 Build/KK) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36
Response Headers
  Cache-Control:max-age=-3000000
  Connection:close
  Content-Encoding:gzip
  Content-Length:26
  Content-Type:text/html
  Date:Wed, 22 Oct 2014 12:17:27 GMT
  Expires:Wed, 27 Aug 2014 18:59:14 GMT
  Server:Apache/2.2.3 (CentOS)
  Vary:Accept-Encoding
  X-Powered-By:PHP/5.5.17

no livereload

no js error

request

Request URL:http://myapi.com/endpoint
Request Method:POST
Status Code:200 OK
Request Headers
  Accept:application/json, text/plain, */*
  Content-Type:application/json;charset=UTF-8
  Origin:file://
  User-Agent:Mozilla/5.0 (Linux; Android 4.4.2; Android SDK built for x86 Build/KK) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36
Request Payload
  some: "data"
Response Headers
  Cache-Control:max-age=-3000000
  Connection:close
  Content-Encoding:gzip
  Content-Length:115
  Content-Type:text/html
  Date:Wed, 22 Oct 2014 12:20:14 GMT
  Expires:Wed, 27 Aug 2014 18:59:14 GMT
  Server:Apache/2.2.3 (CentOS)
  Vary:Accept-Encoding
  X-Powered-By:PHP/5.5.17

Upon further investigation, it seems that the livereload command actually edits your config for that build, and then edits it back. The <content> tag gets changed to

<content src="http://192.168.1.67:8100" original-src="index.html"/>

Thus, it seems that the ionic app displaying what it gets from the local server? I tested doing ionic serve and ran into CORS issues also. So right now the way around this seems to be to configure your (dev) API for CORS

http://www.mooreds.com/wordpress/archives/1216

I did fool around a bit more with this, by going into ionics source and removing the line that would change the content source, and injecting the livereload.js manually, but although the app did refresh, it still reloaded the file:///android_asset/www files.

So I guess the way to permanently fix this issue is to keep the local android index.html (so CORS won't mind), but serving/loading everything else from the livereload server?

I tried adding a <base href="http://192.168.1.67:8100/"> tag to the start of the document (for which I still feel dirty), and it seems that solved both CORS and livereload... but something eventually reloaded index.html from the dev server and this CORS broke again.

So yeah, configuring CORS on the server for now.

This is still a problem in the current ionic cli (1.3.10), this issue should not be closed.

Although this is not a fix per se, the workaround can be found in https://github.com/driftyco/ionic-cli#testing-in-a-browser, subsection Service Proxies.

It's not perfect (you still need to change code from 'local' urls to real environment urls) but I haven't found any better alternative so far.

I agree that this likely shouldn't be closed, or at least closed without a bit more info... A quick Google or two shows that this is an often shared sticking point for Ionic developers... It's very easy to find a lot of discussions where people are having CORS related issues when using "ionic run -l", yet it's very difficult/impossible to find an official solution...

For me, developing my API local to the same machine that I am using live reload and debugging via adb on, I am unable to find a working workaround... I've yet to find a magical combination of proxy settings and Windows host file entries that will get around CORS issues... Additionally, overriding $http defaults, as suggested elsewhere has proven similarly ineffective in working around this.

Were we imagining things? Is this how live reload has been from the start, or was it previously 'just working' without CORS issues as many seem to believe?

Is there a simple and official way to configure a project so that CORS issues don't arise when using 'run -l' on the same development server as the API is running other than configuring the server as such? If this is just something that has to be handled server side, so be it - but I think it def merits a note as it's not the expected behavior when considering the pre-livereload development flow.

Same problems for a salesforce integration:

 [Error] Failed to load resource: Origin http://10.1.1.171:8100 is not allowed by Access-Control-Allow-            Origin. (describe, line 0)
 [Error] XMLHttpRequest cannot load   https:/asdf.cs18.my.salesforce.com/services/data/v29.0/sobjects/App_Settings__c/describe/?_=1424263174184. 
 Origin http://10.1.1.171:8100 is not allowed by Access-Control-Allow-Origin. (10.1.1.171, line 0)

http://10.1.1.171 is my local IP

Same problem with iOS 8 and OSX Yosemite, with everything up to date including all dependencies - run works but run -l hits CORS problems. Ditto emulate.

Here's an alternative use until this is fixed: https://gist.github.com/tobbbe/3fd51f9537e645c73fb9

Thanks, but run -l takes place on a real device so I don't see how Chrome enters into it (I have Safari set in the same way, anyway). The CORS issue is between the ionic server and iOS, somehow.

Is there a way of triggering the respective webview to ignore CORS policies?

Joseph Finlayson

+44 796 796 5870
+49 162 395 0220

On 24 February 2015 at 11:17, kwoxford [email protected] wrote:

Thanks, but run -l takes place on a real device so I don't see how Chrome
enters into it (I have Safari set in the same way, anyway). The CORS issue
is between the ionic server and iOS, somehow.

Reply to this email directly or view it on GitHub
https://github.com/driftyco/ionic-cli/issues/89#issuecomment-75739010.

Bumping this, working on a project and serve works fine but emulate dies with cors issues

Yes, just adding -l to the emulate command kills it. Note that this isn't a matter of CORS with external urls, it kills internal urls so the emulated app can't access its own assets with $http.

I think this issue is causing my 'Unexpected connection failure' with Azure Mobile Services as well in case somebody runs into that.
Was there a workaround for running on the device? It looked like the one workaround was for browsers and the proxy workaround was for -serve..

I managed to find a working solution !
You need to proxy your api server into livereload so that your web app will think the api server is actually the same as your livereload server.
Proxy configuration specs are here : https://github.com/driftyco/ionic-cli#advanced-serve-options
For example, if your api server is on 192.168.0.1:8888, you need to add this to your ionic.project :
"proxies": [
{
"path": "/api",
"proxyUrl": "http://192.168.0.1:8888/api"
}
]
And then, inside your app, you have to make your api calls like if it was local, directly from /api.

Thanks for breaking this down using crayon typeset for me @Yonn-Trimoreau :) This is definitely the easiest workaround presented thus far.. I know it's not a 'new' one, as it's been documented, but for some reason my previous attempts to use this approach had failed.. Up and running against my test APIs without issue now! Thanks again!

@kwoxford have you found a solution to your local assets access via $http with livereload activated? we are hit by the same problem :(

This issue greatly affects my app as well. Our production environment utilizes a universal login call but that returns a specific rest url for that customer to utilize. I cannot use the proxy as suggested in https://forum.ionicframework.com/t/proxy-problems-with-ionic/43354. Specifically because my proxy array would have to end up looking something like

proxies: [
  {
    path: "/login",
    proxyUrl: "http://the-universal-login"
  },
  {
    path: "/api1",
    proxyUrl: "http://rest1"
  },
  {
    path: "/api2",
    proxyUrl: "http://rest2"
  },
  {
    path: "/api3",
    proxyUrl: "http://rest-west"
  },
  {
    path: "/apidev",
    proxyUrl: "this url can be injected by the build process to support all our dev environments"
  }
]

my login call would have to look like

http.get('/login').subscribe((resp) => {
  //resp.restUrl = http://dataCenterRestUrl/corporationToken/
  // dataCenterRestUrl can take the form of any of the following formats (http://dev-backend/1sd/, http://rest1/1sd/, http://rest-west/1sd/)
  this.DataCenter = // parse resp.restUrl to determine what "api" endpoint to now hit
  this.token = //parse resp.restUrl to get the corporationToken
  //currently we just say this.restUrl = resp.restUrl which is clean and easy to read
});

and then every single http call would have to look something like this
http.get('/api${DataCenter}/${tokenForCorporation}/restOfUrlPath')
compared to our current implementation of
http.get('${restUrl}/restOfUrlPath')
IMO, having to implement code like this to support the proxies fix suggestion is hacky, wrong and defeats the purpose of that proxy config. It also defeats the purpose of our universal login as we add new datacenters often and would have to update this config to support these new datacenters whenever they are added.

At our company, we have decided that this is extremely hacky and hard to read so we are not implementing a fix like this. We have just decided to not use the ionic run -l command.

It should be noted that when running locally in a development environment, we use a hostfile hack to ignore the cors issue

Was this page helpful?
0 / 5 - 0 ratings