【问题标题】:XMLHttpRequest error with Flutter-Web using Google Places API (firebase hosting)使用 Google Places API(firebase 托管)的 Flutter-Web 出现 XMLHttpRequest 错误
【发布时间】:2020-07-25 00:10:04
【问题描述】:

在我的 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');},
    );
  },
);

当我运行应用程序并向字段中插入内容时,我没有得到任何结果。但是我收到了这个错误(从托管上的检查控制台捕获,我在本地也收到了同样的错误):

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

部署了,但也遇到了同样的错误。

感谢任何有关解决该问题(本地和托管)的提示。

【问题讨论】:

    标签: cors google-places-api firebase-hosting flutter-web


    【解决方案1】:

    我在这个 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

    【讨论】:

    • 天哪,谢谢。我不知道 cors-anywhere 或 herokuapp 以任何方式。令人难以置信的是,我可以 24/7 免费托管节点项目,我什至可以在那里制作一个免费的 api:o
    • 试过了,现在卡在这个问题上:github.com/lejard-h/google_maps_webservice/issues/92有什么解决办法吗?
    • 这个接缝很危险,你有你的钥匙
    【解决方案2】:

    因此,由于没有答案,我正在分享解决我的情况的方法,希望尽快从专家那里得到更好的答案。

    问题:

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

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

    此客户端请求将被阻止。

    我的解决方案:

    首先我不再使用 PlacesAutocomplete 小部件。

    我写了一个简单的云函数,它以 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。

    希望这个答案对面临类似问题的人有所帮助,并期待专家提供更好的答案。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 谢谢。但重要的是在测试时让用户有相同的行为。
      【解决方案4】:

      基于此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

      【讨论】:

        猜你喜欢
        • 2020-06-04
        • 2021-02-15
        • 1970-01-01
        • 2020-10-15
        • 1970-01-01
        • 2021-10-30
        • 2021-02-04
        • 1970-01-01
        • 2022-01-07
        相关资源
        最近更新 更多