I have a Flutter Web project hosted on Firebase Hosting rendered with CanvasKit and I can't make it load external images hosted in a Xano CDN or load GooglePlaces API results (autocompiling). I read many other solutions (like this or this or this) but none works. I also configured CORS on Google Cloud.
This is my firebase.json
file:
{
"hosting": {
"public": "build/web",
"ignore": [
"firebase.json",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
],
"headers": [
{
"source": "*",
"headers": [
{
"key": "Access-Control-Allow-Origin",
"value": "*"
}
]
}
]
}
}
In index.html I have appended the following script, right before the </body>
tag:
<!-- Firebase -->
<script type="module">
// Import the functions you need from the SDKs you need
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.6.10/firebase-app.js";
import { getAnalytics } from "https://www.gstatic.com/firebasejs/9.6.10/firebase-analytics.js";
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
apiKey: *mykey*,
authDomain: "hearth-148b0.firebaseapp.com",
projectId: "hearth-148b0",
storageBucket: "hearth-148b0.appspot.com",
messagingSenderId: *id*,
appId: *myappid*,
measurementId: *id*
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
const analytics = getAnalytics(app);
</script>
I tried to include the header in the CachedNetworkImage:
return CachedNetworkImage(
httpHeaders: {"Access-Control-Allow-Origin": "*"},
imageUrl: imageUrl,
fit: fit,
width: width,
height: height,
progressIndicatorBuilder: (context, url, downloadProgress) =>
LoadingPlaceholder(width: width),
errorWidget: (context, url, error) => SizedBox(width: width),
);
And I tried to include the headers in GooglePlace initializer:
final GooglePlace googlePlace = GooglePlace(
kTokenGMaps,
headers: {"Access-Control-Allow-Origin": "*"},
);
These are the type of errors I get from the browser console:
Failed to load resource: net::ERR_BLOCKED_BY_CLIENT
or
Access to XMLHttpRequest at 'https://storage.googleapis.com/xatr-ly1x-gkt1.n7.xano.io/vault/xhL5_hu1/fMPW0YCx/C01_Ng../9de15d31/Monumento_ai_caduti_in_Corso_Europa.jpg' (redirected from 'https://xatr-ly1x-gkt1.n7.xano.io/vault/xhL5_hu1/fMPW0YCx/C01_Ng../Monumento_ai_caduti_in_Corso_Europa.jpg?tpl=big:box') from origin 'https://hearth-148b0.web.app' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
These are the commands I use to deploy on firebase, from android studio:
flutter build web
firebase deploy
I also tried to use another host with FTP and setting the .htaccess file to:
Header set Access-Control-Allow-Origin *
but no success.
I resolved this problem by adjusting the CORS settings on the server side. Initially, I thought it was a client problem, but it turned out to be caused by a misconfiguration on the server.
In my case, I was using Firebase Storage, and I had to create a cors.json file on my computer to enable CORS. Here's what my configuration looked like:
[
{
"origin": ["*"],
"method": ["GET"],
"maxAgeSeconds": 3600
}
]
To break this down:
"origin": ["*"]
allows requests from any origin to access the resource. You can specify a specific domain or a list of domains to restrict the origins that are allowed to access the resource.
"method": ["GET"]
allows only GET requests to access the resource. You can include other HTTP methods like POST, PUT, DELETE, etc. to restrict the methods that are allowed to access the resource.
"maxAgeSeconds": 3600
caches the CORS configuration in the browser for 1 hour (3600 seconds). Subsequent requests from the same origin and method will not require a CORS check during the cache duration.
After creating the cors.json file, and after installing gsutil
, execute this command in your terminal:
gsutil cors set cors.json gs://<bucket>.appspot.com
Make sure to replace <bucket>
with the name of your storage bucket.
By following these steps, I was able to fix my CORS issue and enable access to my resources.