'XMLHttpRequest error with Flutter-Web using Google Places API (firebase hosting)
Inside my Flutter-Web application I'm trying to get address using flutter_google_places package. I'm trying simple code to get autocomplete address field (MyTextField is just a customized Text Field):
final addressField = MyTextField(
controller: _addressController,
labelText: 'Indirizzo',
readOnly: true,
onTap: () async {
await PlacesAutocomplete.show(
context: context,
apiKey: kGoogleApiKey,
mode: Mode.overlay,
onError: (error){print('ERROR: $error');},
);
},
);
When I run the app and insert something to the field I don't get any result. But I get this error (captured from inspect console on hosting, and I get the same error locally also):
Access to XMLHttpRequest at 'https://maps.googleapis.com/maps/api/place/autocomplete/json?input=h&key=**MY-API-KEY**' from origin 'https://**MY-HOSTING**.firebaseapp.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I read that it's a server-side issue and I tried to modify firebase.json like this:
{
"hosting": {
"public": "build/web",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
],
"headers": [ {
"source" : "**",
"headers" : [ {
"key" : "Access-Control-Allow-Origin",
"value" : "*"
} ]
}]
}
}
Deployed that but also got the same error.
Any tips about solving that (locally and on hosting) are appreciated.
Solution 1:[1]
I found a solution that lets you keep using PlacesAutocomplete in this github comment: https://github.com/lejard-h/google_maps_webservice/issues/70#issuecomment-636919093
GoogleMapsPlaces(
apiKey: 'YOUR_API_KEY',
baseUrl: kIsWeb
? 'https://cors-anywhere.herokuapp.com/https://maps.googleapis.com/maps/api'
: null,
);
This other StackOverflow answer talks about how the solution works a little more, as well as give more info about cors-anywhere (including how to host your own): https://stackoverflow.com/a/43881141/3001277
Solution 2:[2]
So as there was no answers I'm sharing what solved my situation, hope getting better answers from experts soon.
The Problem:
Google places API prevents CORS. So we can't make a request from client-side. And As the PlacesAutocomplete widget makes http request to the Google places API like this:
https://maps.googleapis.com/maps/api/place/autocomplete/json?input={queryString}&key={API-Key}
This client-side request will be prevented.
My Solution:
First I'm not using PlacesAutocomplete widget anymore.
I wrote a simple cloud function that takes Url as parameter then makes http request for the same Url and returns data. But this time the request will be from server-side so I can bypass cors. So Inside index.ts I wrote the following function:
const functions = require('firebase-functions');
const axios = require('axios');
exports.getDataFromUrl = functions.https.onCall(async (data, context) => {
const url = data.url;
try {
const info = await axios.get(url);
return info.data;
} catch (error) {
return (error);
}
});
Then from client-side I wrote this function (in dart) which calls the cloud function for any url:
Future httpRequestViaServer({url}) async {
HttpsCallable callable = CloudFunctions.instance.getHttpsCallable(
functionName: 'getDataFromUrl',
);
try {
final HttpsCallableResult result = await callable.call(
<String, dynamic>{
'url': url,
},
);
return (result.data);
} on CloudFunctionsException catch (e) {
print('caught firebase functions exception');
print(e.code);
print(e.message);
print(e.details);
return null;
} catch (e) {
print('caught generic exception');
print(e);
return null;
}
Now I can call this function to get data for the API url (or any url) from anywhere in my project.
I ended building my own autoComplete widget which calls the API using this function.
Hope this answer helps someone facing similar problem, and looking forward for better answers from experts.
Solution 3:[3]
if you want to test this locally you can use the "Allow CORS: Access-Control-Allow-Origin" for Chrome to disable it
Solution 4:[4]
Based on this answer,
Use https://app.cors.bridged.cc/ instead of https://cors-anywhere.herokuapp.com/
Follow this article for more details: https://blog.grida.co/cors-anywhere-for-everyone-free-reliable-cors-proxy-service-73507192714e
Solution 5:[5]
This API is not meant for the web. To take advantage of Place Autocomplete on Flutter web, it is necessary to use a library that implements the interop with javascript like this: https://pub.dev/packages/flutter_google_places_sdk
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | mrmax99 |
| Solution 2 | |
| Solution 3 | Tejero Lucas |
| Solution 4 | Omar Khaium Chowdhury |
| Solution 5 | Alevittoria |
