[英]XMLHttpRequest error in flutter web [Enabling CORS AWS API gateway]
[英]XMLHttpRequest error with Flutter-Web using Google Places API (firebase hosting)
在我的 Flutter-Web 应用程序中,我正在尝试使用 flutter_google_places package 获取地址。我正在尝试使用简单的代码来获取自动完成地址字段(MyTextField 只是一个自定义的文本字段):
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');},
);
},
);
当我运行应用程序并向字段中插入内容时,我没有得到任何结果。 但是我收到此错误(从托管检查控制台捕获,我也在本地收到相同的错误):
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.
我读到这是一个服务器端问题,我试图像这样修改 firebase.json:
{
"hosting": {
"public": "build/web",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
],
"headers": [ {
"source" : "**",
"headers" : [ {
"key" : "Access-Control-Allow-Origin",
"value" : "*"
} ]
}]
}
}
部署了它,但也遇到了同样的错误。
任何有关解决该问题(本地和托管)的提示都将受到赞赏。
因此,由于没有答案,我正在分享解决我的情况的方法,希望尽快从专家那里得到更好的答案。
问题:
谷歌放置 API 防止CORS 。 所以我们不能从客户端发出请求。 并且由于 PlacesAutocomplete 小部件向 Google 发出 http 请求,因此 API 如下所示:
https://maps.googleapis.com/maps/api/place/autocomplete/json?input={queryString}&key={API-Key}
此客户端请求将被阻止。
我的解决方案:
首先,我不再使用 PlacesAutocomplete 小部件。
我写了一个简单的云 function ,它以 Url 作为参数,然后对相同的 Z02A3A3A357710FB59ZDFB12 数据发出 http 请求并返回。 但是这次请求将来自服务器端,所以我可以绕过 cors。 所以在index.ts里面我写了以下 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);
}
});
然后从客户端我写了这个 function(在飞镖中),它为任何 url 调用云 function:
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;
}
现在我可以调用这个 function 从我项目中的任何位置获取 API url(或任何 url)的数据。
我结束了构建自己的 autoComplete 小部件,该小部件使用此 function 调用 API。
希望这个答案对面临类似问题的人有所帮助,并期待专家提供更好的答案。
我找到了一个解决方案,可以让您在此 github 评论中继续使用 PlacesAutocomplete: 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,
);
这个 StackOverflow 的另一个答案讨论了该解决方案的工作原理,并提供了有关 cors-anywhere 的更多信息(包括如何托管您自己的): https://stackoverflow.com/a/43881141/3001277
如果您想在本地进行测试,您可以使用 Chrome 的“Allow CORS: Access-Control-Allow-Origin”来禁用它
基于这个答案,
使用https://app.cors.bridged.cc/
代替https://cors-anywhere.herokuapp.com/
关注这篇文章了解更多详情: https://blog.grida.co/cors-anywhere-for-everyone-free-reliable-cors-proxy-service-73507192714e
此 API 不适用于 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
我参考了 Feras Senjab 的回答:
为了仍然有效,方法现在应该稍微改变了。
对于 index.js 没有变化
// Forwards a request call to get Google Places AUtocomplete Running
exports.getGooglePlacesAutocomplete = functions.https.onCall(async (data, context) => {
const url = data.url;
try {
console.log(url);
const info = await axios.get(url);
console.log(info);
return info.data;
} catch (error) {
return (error);
}
});
对于客户端,这是更新
import 'package:cloud_functions/cloud_functions.dart';
Future googlePlacesAutocompleteRequestViaServer({url}) async {
HttpsCallable callable =
FirebaseFunctions.instance.httpsCallable('getGooglePlacesAutocomplete');
try {
final HttpsCallableResult result = await callable.call(
<String, dynamic>{
'url': url,
},
);
return (result.data);
} on FirebaseFunctionsException 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;
}
}
从 Flutter Web 拨打 Google Places API。
将标题如下添加到您的 api-client。
{
"x-requested-with" : "XMLHttpRequest"
}
现在,append 您的 Google Places API 与
https://proxy.cors.sh
因此,将您的 API 称为
https://proxy.cors.sh/<Google Places API>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.