visit
Summary: I provide a practical solution for solving CORS issue in in Ionic and Cordova. The solution works both for iOS and Android.
Image credit: If you code with Ionic or Cordova and use a REST API, you probably have seen an error like this:XMLHttpRequest cannot load No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘//localhost:8100' is therefore not allowed access.
What is CORS?CORS stands for Cross Origin Resource Sharing. In short, CORS is a method to prevent a client to request a display a service from a host other than the one that is currently showing. This is done for security reasons.The ProblemIn order for an external API server to work in the presence of CORS, it should include something like this in its header:Access-Control-Allow-Origin: *The problem however is that some API providers do not include this and since we don’t have any control over the server, we cannot add this to the response header.This is a huge problem specially in iOS where Ionic and Cordova run in , which enforces CORS.SolutionsIonic’s blog has an . Unfortunately, the solution that they provide is only suitable when you are running the app using ionic serve or ionic run -l. That solution will not work on the production release!The good news is that you can still solve the problem by doing a tiny little bit of work. I list a couple of solutions:
Using a proxy (Not a good solution): the idea is simple: create your OWN server in the middle of your client and the main API server. Your client request goes to your own server, which support CORS. Your server sends the request to the API server, gets the results, and sends it back to you.
Your server can be as simple as reading requests from specific node like /requests from a database server like Google Firebase, and then write the results in another node called /replies.
While this is doable, I don’t like this solution cause you will need to create a new server and maintain it.2. Use Native HTTP (My favorite): Fortunately Cordova’s comes to rescue. Since this plugin’s HTTP requests don’t go through WKWebView, it does not have CORS issues. This is awesome!
So the solution is to send the HTTP requests for the given API through native HTTP plugin rather than NodeJS’s requests. Therefore:Solution: Instead of using npm’s Request or Fetch packages, use Cordova’s plugin.
Here is an example usage for using Cordova’s native HTTP:declare var cordova: any;
let url = '//api.binance.com/api/v1/exchangeInfo';
let params = {};
let headers = {};
cordova.plugin.http.get(url,
params, headers, (response) => {
console.log(response.status);
}, function(response) {
console.error(response.error);
});
//First overload fetchImplementation in the constructor
let exchange = new ccxt["poloniex"]({
enableRateLimit: true,
apiKey:apiKey,
secret: secret,
//Overloaded function that uses Native http calls
fetchImplementation: ccxtFetchImplementation // ------> My wrapper function
});
//Define ccxtFetchImplementation definition in your IONIC program:
ccxtFetchImplementation(url, options) {
let headers = options.headers || undefined;
return new Promise(async (resolve, reject) => {
//Cordova native http get request
cordova.plugin.http.get(url, {}, headers, function (response) {
//CCXT needs this function to match npm Fetch
response.text = () => {
return new Promise((resolve, reject) => {
resolve(response.data);
})
}
//Use Map to mimic npm Fetch that is used by ccxt
response.headers = new Map(Object.entries(response.headers));
response.statusText = response.statusMessage;
resolve(response);
}, function (response) {
console.log('response.error: ', response.error);
reject(response);
});
})
}
const binanceRest = new binanceApi.BinanceRest({
key: apiKeySecret.apiKey, // Get this from your account on binance.com
secret: apiKeySecret.secret, // Same for this
timeout: 15000, // Optional, defaults to 15000, is the request time out in milliseconds
recvWindow: 10000, // Optional, defaults to 5000, increase if you're getting timestamp errors
disableBeautification: false,
/*
* Optional, default is false. Binance's API returns objects with lots of one letter keys. By
* default those keys will be replaced with more descriptive, longer ones.
*/
handleDrift: false,
requestFunction: cordova.plugin.http.get // ----------> Added by me!
/* Optional, default is false. If turned on, the library will attempt to handle any drift of
* your clock on it's own. If a request fails due to drift, it'll attempt a fix by requesting
* binance's server time, calculating the difference with your own clock, and then reattempting
* the request.
*/
});