Closed FranGhe closed 1 year ago
[Error] Origin app://localhost is not allowed by Access-Control-Allow-Origin. Status code: 200
This indicates that your server is not returning app://localhost
in it's Access-Control-Allow-Origin
response.
<preference name="scheme" value="https" />
This is an invalid configuration for iOS, although it's valid for Android. Android scheme must be either http
or https
, whereas iOS can be anything that isn't a "well-known scheme". Apple doesn't explicitly declare what that means, but virtually any standardized protocol is an illegal scheme. This means that you can't have a consistent origin cross-platform, since the two platforms have conflicting requirements. When iOS encounters an illegal scheme, it fallsback to app
, which is why you're origin becomes app://localhost
despite the scheme
being set to https
. Leaving it as is ok, but just explaining why your origin is app://localhost
instead of https://localhost
.
You haven't told us what you have your Access-Control-Allow-Origin
to, so for the moment I'm going to assume it's not app://localhost
... more on this later...
On the server side, because you support both Android and iOS also means you need to be flexible and return a different value depending on the Origin
request header. Any CORS request will have a Origin
header on the request, which you can pass back as the Access-Control-Allow-Origin
to make it act as a wildcard. Additionally you could check to see if Origin
is what you expect, if you like. The Access-Control-Allow-Origin
only accepts 1 value, but that value can be a *
for a wildcard. I've had issues with this method on older iOS devices however (pre iOS 10). I haven't actually tested if it works properly on iOS 11+.
You haven't told us what you have your
Access-Control-Allow-Origin
to, so for the moment I'm going to assume it's notapp://localhost
... more on this later...
If your GET
request is returning Access-Control-Allow-Origin
response header with the value of app://localhost
, then you might be triggering a preflight CORS request, which may happen if certain conditions are met. MDN goes into more detail on these conditions.
If your request requires a preflight request, then your server must respond to the OPTIONS
request in addition to the GET
(or whatever HTTP Method your main API endpoint is)
The OPTIONS
request shall respond with:
Access-Control
response headers as appropriate. At minimum, Access-Control-Allow-Origin
is required. Access-Control-Allow-Headers
may be required if you use custom headers.Content-Length
0 (has no body content).You can test your endpoints to confirm if the server is responding properly with the proper response headers using a non-browser based HTTP client. Personally I use Postman for this.
I have a blog post that goes into much more detail on how to handle CORs, with NGINX config examples, but the general concept should be able to be applied to any webserver technology.
Thanks for your support... talking about the request from my app to my server to a file php there isn't problem because this is my php code:
<?php
header('Access-Control-Allow-Origin: *');
...
my problem is only when I want read an image file to download... as example: https://www.mySite.xx/img/logo.jpg https://www.mySite.xx/img/img1.jpg https://www.mySite.xx/img/img2.png ... ecc
in this case how I can do to not have CORS problem?... I can't write in a binary file...
This is the solution... no one setting server side...
Install cordova-plugin-wkwebview-file-xhr and cordova-plugin-wkwebviewxhrfix plugins
On config.xml set:
<platform name="ios">
<preference name="scheme" value="app" />
<preference name="hostname" value="localhost" />
...
</platform>
Than, to download the files:
function downloadTemporaryFile(pathOrig, key, pathDest) {
var req = new XMLHttpRequest();
req.open("GET", pathOrig, true);
req.responseType = "blob";
req.onload = function (event) {
var blob = req.response;
var storageLocation = cordova.file.dataDirectory;
if(storageLocation){
window.resolveLocalFileSystemURL(
storageLocation,
function (directoryEntry) {
directoryEntry.getFile(
pathDest,
{ create: true },
function (fileEntry) {
fileEntry.createWriter(
function (fileWriter) {
fileWriter.write(blob);
fileWriter.onwriteend = function (e) {
//console.log('Write of file completed.');
var split=pathDest.split("-");
var cont=split[0];
var thisContent=allAppData[cont];
var localFile = storageLocation+pathDest;
if(!thisContent["temporaryImages"]){
thisContent.temporaryImages={};
}
if(device.platform === "Android"){
thisContent.temporaryImages[key]=localFile;
}
else if(device.platform === "iOS"){
thisContent.temporaryImages[key]=window.WkWebView.convertFilePath(localFile);
}
};
fileWriter.onerror = function (e) { console.log("downloadTemporaryFile -> Err01"); };
},
function (err) {
console.log("downloadTemporaryFile -> Err02");
console.error(err);
}
);
},
function (err) {
console.log("downloadTemporaryFile -> Err03");
console.error(err);
}
);
},
function (err) {
console.log("downloadTemporaryFile -> Err04");
console.error(err);
}
);
}
};
req.send();
}
Thanks for your support... talking about the request from my app to my server to a file php there isn't problem because this is my php code:
<?php header('Access-Control-Allow-Origin: *'); ...
my problem is only when I want read an image file to download... as example: https://www.mySite.xx/img/logo.jpg https://www.mySite.xx/img/img1.jpg https://www.mySite.xx/img/img2.png ... ecc
in this case how I can do to not have CORS problem?... I can't write in a binary file...
If you're responding with the header Access-Control-Allow-Origin: *
on both the GET
and the OPTIONS
requests and it still isn't working with the native XMLHttpRequest/fetch APIs, then you might be hitting an issue I mentioned:
I've had issues with this method on older iOS devices however (pre iOS 10). I haven't actually tested if it works properly on iOS 11+.
I know for certain that iOS 10 and earlier didn't properly support wildcards, and based on what you're telling me that might still be the case with current iOS versions. If that's the situation then the proper solution would be to return the domain as read from the Origin
request header, which would simulate a wildcard behaviour.
Install cordova-plugin-wkwebview-file-xhr and cordova-plugin-wkwebviewxhrfix plugins
Using these plugins can work as well. They generally work by overwriting the browser's HTTP apis so that requests are made using the native HTTP layer rather than the browser's HTTP layer. This works because the native device HTTP APIs are not bounded by CORs since CORs is a browser concept. However, this is working around CORs instead of being CORS compliant.
If this is the solution you have decided to go with however, I'll close this issue.
I know for certain that iOS 10 and earlier didn't properly support wildcards, and based on what you're telling me that might still be the case with current iOS versions. If that's the situation then the proper solution would be to return the domain as read from the
Origin
request header, which would simulate a wildcard behaviour.
Like this?:
if (isset($_SERVER['HTTP_ORIGIN'])) {
header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Max-Age: 86400'); // cache for 1 day
}
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])){
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
}
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])){
header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
}
}
I'm not too familiar with PHP but that looks mostly right, however on the OPTIONS
you shouldn't be responding any content body back, so if this php script is handling both the GET
and OPTIONS
methods, then you'll need to return early without sending back the image. On the OPTIONS
method, the Content-Length
should be 0
and there should be no payload, Just the response headers.
In othewords, you should only return the image content if the HTTP method is the GET
request. I'm not sure how to do that in PHP myself, so I can't provide an example.
When building app everything is ok... I have many ajax call to remote file (php) and everything it's ok because i can manage header("Access-Control-Allow-Origin: ...."); But the issue arises when I have to read/download images files.
On config.xml I set
And reading some post I also installed
@ahovakimyan/cordova-plugin-wkwebviewxhrfix
This is my code:
On my console I have these errors: [Error] Origin app://localhost is not allowed by Access-Control-Allow-Origin. Status code: 200 [Error] XMLHttpRequest cannot load https://www.mySite.xx/img/logo.jpg due to access control checks. [Error] Failed to load resource: Origin app://localhost is not allowed by Access-Control-Allow-Origin. Status code: 200
I use the same code for Android an there aren't issue... How can I solve it?
Thanks in advance