使用Google Places API的Flutter-Web的XMLHttpRequest错误(firebase托管)

lnlaulya  于 2023-08-07  发布在  Flutter
关注(0)|答案(7)|浏览(139)

在我的Flutter-Web应用程序中,我试图使用flutter_google_places包获取地址。我正在尝试简单的代码来获取自动完成地址字段(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');},
    );
  },
);

字符串
当我运行应用程序并在字段中插入一些东西时,我没有得到任何结果。但是我得到了这个错误(从主机上的inspect console捕获,我在本地也得到了同样的错误):

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" : "*"
      } ]
    }]
  }
}


部署了,但也得到了同样的错误。
任何关于解决这个问题的提示(本地和托管)都很感激。

iklwldmw

iklwldmw1#

因此,由于没有答案,我分享了解决我的情况的方法,希望很快能从Maven那里得到更好的答案。

问题:

Google Places API阻止CORS。所以我们不能从客户端发出请求。当PlacesAutocomplete小部件向Google places API发出http请求时,如下所示:

https://maps.googleapis.com/maps/api/place/autocomplete/json?input={queryString}&key={API-Key}

字符串
将阻止此客户端请求。

我的解决方案:

首先,我不再使用PlacesAutocomplete widget了。
我写了一个简单的cloud函数,它以Url为参数,然后对同一个Url发出http请求并返回数据。但这次请求将来自服务器端,所以我可以绕过cors。在index.ts中,我写了如下函数:

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);
  }
});


然后从客户端我写了这个函数(在dart中),它为任何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;
    }


现在我可以调用这个函数从项目中的任何地方获取API url(或任何url)的数据。
我最终构建了自己的autoComplete小部件,它使用此函数调用API。
希望这个答案能帮助面临类似问题的人,并期待Maven更好的答案。

isr3a4wc

isr3a4wc2#

我发现了一个解决方案,可以让你在这个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

ogsagwnx

ogsagwnx3#

从Flutter Web调用Google Places API。
按下面的方式添加Header到您的api-client。

{
 "x-requested-with" : "XMLHttpRequest"
}

字符串
现在,在下面添加带有Google Places API的URL。

https://proxy.cors.sh/


因此,将您的API调用为

https://proxy.cors.sh/<Google Places API>

kadbb459

kadbb4594#

此API不适用于Web。为了在Flutter web上利用Place Autocomplete,有必要使用一个库来实现与JavaScript的互操作,如下所示:https://pub.dev/packages/flutter_google_places_sdk

fgw7neuy

fgw7neuy5#

我参考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);
  }
});

字符串
对于CLient方面,这是更新

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;
  }
}

zour9fqk

zour9fqk6#

如果您想在本地测试,您可以使用“允许CORS:Access-Control-Allow-Origin”,以便Chrome禁用它

gjmwrych

gjmwrych7#

基于这个answer
使用https://app.cors.bridged.cc/代替https://cors-anywhere.herokuapp.com/
请阅读本文了解更多详情:https://blog.grida.co/cors-anywhere-for-everyone-free-reliable-cors-proxy-service-73507192714e

相关问题