Ошибка XMLHttpRequest с Flutter-Web с использованием Google Places API (хостинг Firebase) - PullRequest
0 голосов
/ 12 апреля 2020

Внутри моего приложения 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" : "*"
      } ]
    }]
  }
}

Развернул это, но также получил ту же ошибку.

Любые советы по ее решению (локально и на хостинге) приветствуются.

Ответы [ 2 ]

0 голосов
/ 16 апреля 2020

Так как ответов не было, я делюсь тем, что решило мою ситуацию, надеюсь, скоро получим лучшие ответы от экспертов.

Проблема:

API Google Мест предотвращает CORS . Поэтому мы не можем сделать запрос со стороны клиента. А так как виджет PlacesAutocomplete отправляет http-запрос к API мест Google следующим образом:

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

Этот запрос на стороне клиента будет отклонен.

Мое решение:

Сначала я больше не использую виджет PlacesAutocomplete.

Я написал простую облачную функцию , которая принимает Url в качестве параметра, затем выполняет http-запрос для того же URL-адреса и возвращает данные. Но на этот раз запрос будет от серверной , поэтому я могу обойти 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;
    }

Теперь я могу вызывать эту функцию, чтобы получать данные для URL-адреса API (или любого URL-адреса) из любого места в моем проекте.

Я закончил создание своего собственного виджета autoComplete, который вызывает API с помощью этого функция.

Надеюсь, что этот ответ поможет кому-то, сталкивающемуся с подобной проблемой, и ожидает более качественных ответов от экспертов.

0 голосов
/ 15 апреля 2020

Если вы хотите проверить это локально, вы можете использовать «Разрешить CORS: Access-Control-Allow-Origin» для Chrome, чтобы отключить его

...