2

I am new to IONIC-2 and want to connect my mobile app to Odoo - open source ecommerce.. this connection involves some JSONP request.. I have done the same through jQuery previously.. its working properly in phonegap app.. but while I am doing the same thing with IONIC-2 it gives me CORS and JSONP errors..

can someone help me in this..

my previous jQuery code is..

/******  index.js ******/

function json(url, params) {
   var deferred = jQuery.Deferred();

   uniq_id_counter += 1;
   var payload = {
      'jsonrpc': '2.0',
      'method': 'call',
      'params': params,
      'id': ("r" + uniq_id_counter)
   };

   rpc_jsonp(url, payload).then(function (data, textStatus, jqXHR) {
      if (data.error) {
          deferred.reject(data.error);
      }
      deferred.resolve(data.result, textStatus, jqXHR);
   });

   return deferred;
 }


function rpc_jsonp(url, payload) {

   // extracted from payload to set on the url
   var data = {
      session_id: window.localStorage.getItem("session_id"),
      id: payload.id
   };

   var ajax = {
     type: "POST",
     dataType: 'jsonp',
     jsonp: 'jsonp',
     cache: false,
     data: data,
     url: url
  };

  var payload_str = JSON.stringify(payload);
  var payload_url = jQuery.param({r: payload_str});
  if (payload_url.length < 2000) {
       //  throw new Error("Payload is too big.");
  }

  console.log(ajax);
  ajax.data.r = payload_str;
  console.log(ajax);
  return jQuery.ajax(ajax);

}
/******  index.js ******/

I am calling above custom json function Login.html file..

 /******  login.html ******/

 function login(){

   var base_url = 'MY_SERVER_URL';
   json(base_url+'web/session/authenticate', {
      'base_location': base_url,
      'db':'myDB',
      'login': 'admin',
      'password':'admin'
   }).done(function (data) {

   if(data.uid != false){
       alert(data);
   }
   else{
       alert('Invalid Username or Password.');
   }

   deferred.resolve();
 }).fail(function(data){
     alert('Invalid Username or Password.');
 });

  return deferred;
}
/******  login.html ******/

I tried followed code in IONIC 2 while creating service

/****** OdooJsonService.ts ******/
import { Injectable } from '@angular/core';
import { Http, Jsonp, JSONP_PROVIDERS, Headers, RequestOptions } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/Rx';

@Injectable()
export class OdooJsonService {
//data: any;
uniq_id_counter: number;
payload: any;
result_rpc: any;

constructor(private http: Http, private jsonp: Jsonp) {
  this.http = http;
  //this.data = null;
}

json(url, params) {

    this.uniq_id_counter = this.uniq_id_counter + 1;

    this.payload = JSON.stringify({
        'jsonrpc': '2.0',
        'method': 'call',
        'params': params,
        'id': ("r" + this.uniq_id_counter)
    });

    return this.rpc_jsonp(url, this.payload)
                    .map(res => res.json())
                    .catch(this.handleErrorOne);
}

rpc_jsonp(url, payload) {

    let data = JSON.stringify({
        //session_id: window.localStorage.getItem("session_id"),
        id: payload.id
    });

    let ajax = JSON.stringify({
        type: 'POST',
        dataType: 'jsonp',
        jsonp: 'jsonp',
        cache: false,
        data: data,
        url: url
    });

    let headers = new Headers({ 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*',
                                'Access-Control-Allow-Methods': 'PUT, GET, POST',
                                'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept'});
    let options = new RequestOptions({ headers: headers });

    return this.http.post(url, ajax, options)
        .map(res => res.json())
        .catch(this.handleErrorTwo);
}

handleErrorOne(error) {
    console.error(error);
    return Observable.throw(error.json().error || 'Server error');
}

handleErrorTwo(error) {
    console.error(error);
    return Observable.throw(error.json().error || 'Server error');
}

 }       // End of OdooJsonService
 /****** OdooJsonService.ts ******/

and I am using above service in Login.ts

/****** login.ts ******/
import { Component } from '@angular/core';
import { App, NavController, MenuController, ViewController } from 'ionic-angular';
import { TaskListPage } from '../task-list/task-list';

import { Http, Jsonp, JSONP_PROVIDERS } from '@angular/http';
import { OdooJsonService } from '../../providers/odoo-json-service/odoo-json-service';

@Component({
  templateUrl: 'build/pages/login/login.html',
  providers: [OdooJsonService, JSONP_PROVIDERS]
})
export class LoginPage {
   public data: any;

   constructor(private nav: NavController, public odooJsonService: OdooJsonService) {
     this.odooMethod();
   }

   odooMethod() {
      this.odooJsonService
            .json('MY_SERVER_URL/web/session/authenticate', {'base_location': 'MY_SERVER_URL',
                    'db':'myDB', 'login': 'admin', 'password':'admin'})
            .subscribe(odooData => {
                this.data = odooData;
                console.log(JSON.stringify(this.data));
            });
     }

}
/****** login.ts ******/

error in console : (chrome)

XMLHttpRequest cannot load https://MY_SERVER_URL/web/session/authenticate. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8100' is therefore not allowed access. The response had HTTP status code 500.

error in console : (firefox)

/web/session/authenticate: Function declared as capable of handling request of type 'json' but called with a request of type 'http'

I am not sure whether this is right approach.. Can anyone guide to do this in right order..

how can I achieve the same in IONIC 2??

Thanks in advance.

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
VaibsVB
  • 835
  • 7
  • 9

4 Answers4

5

You can disable same origin policy in Chrome.

  1. Create a separate chrome icon on your desktop.

Dual Chrome

  1. Rename that icon to chrome (x-domain) so you know which is which.

Chrome rename

  1. Right click on your new icon and click properties.

Properties

  1. Change the target field to "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security --user-agent="Android" --user-data-dir="C:/temp-chrome-eng"

Target Field

  1. Click Ok.

The magic happens here:

--disable-web-security

When you open your browser it will look like this:

Finished

WARNING: ONLY USE FOR TESTING PURPOSES AS THIS BROWSER HAS SECURITY DISABLED.

MasterProgrammer200
  • 1,021
  • 2
  • 17
  • 29
0

The error you're receiving is because your browser is blocking the cross-origin AJAX requests (the domain doesn't respond with the required headers). However if you execute the application on a mobile device, it should work, because the application will execute the request directly. You can read more here. Does it work if you launch the app on a mobile device?

Community
  • 1
  • 1
Kuba Beránek
  • 458
  • 9
  • 19
  • 1
    Kuba is correct. It should work when running your app on an android or ios device. However for testing in the browser see my answer below. – MasterProgrammer200 Jul 21 '16 at 17:32
  • On device there is no success or error log. I'm not getting whether my code is wrong or something else that matters. – VaibsVB Jul 22 '16 at 13:45
  • I've had problems with HTTPS using this, does the API site have correct certiticate accepted by Android? If it's possible, try using HTTP first. And put a breakpoint in the code so that you see that whether it actually executes. – Kuba Beránek Jul 23 '16 at 07:35
0

I am running on browser using CORS extensions and plugins on both chrome and mozilla. still there is no success.

I'm not getting whether my code is wrong or something else that matters.

EDIT: Follow below two comments to disable web security of chrome on MAC machine.

VaibsVB
  • 835
  • 7
  • 9
  • I resolved CORS issue on browser by disabling web security of chrome temporarily for development purpose only.. and changed my JSONService code.. – VaibsVB Aug 01 '16 at 09:47
  • disable web security of chrome on mac machine using following command. `open -n -a "Google Chrome" --args --user-data-dir=/tmp/temp_chrome_user_data_dir_for_cordova http://localhost:8100/index.html --disable-web-security` This creates another instance of chrome with security is disabled. – VaibsVB Aug 05 '16 at 10:02
0

i had problem to use ionic and iis on same url ( localhost:8100 ) this chrome extension help me to solve cors issue: [enter link description here]

https://chrome.google.com/webstore/detail/moesif-origin-cors-change/digfbfaphojjndkpccljibejjbppifbc

also for web api you can put this peace of code inside system.webServer tag in your web.config file

<system.webServer> 
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Headers" value="*" />
        <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, 
DELETE, OPTIONS" />
      </customHeaders>
    </httpProtocol>
...
</system.webServer>

make sure your header is correct:

let headers = new HttpHeaders();
headers = headers.set('Content-Type', 'application/x-www-form-urlencoded');
headers.append('Access-Control-Allow-Origin','*');
headers.append('Access-Control-Allow-Methods','GET,PUT,POST,DELETE');
headers.append('Access-Control-Allow-Headers','Content-Type');
Mohammad Reza Mrg
  • 1,552
  • 15
  • 30