Ошибка произвольного подключения в облачных функциях Google (Python) - PullRequest
0 голосов
/ 11 марта 2020

Поскольку последние несколько недель я получал неожиданные ошибки CORS в консоли браузера, я настроил супер простой сценарий Python с единственной функцией внутри Google Cloud Функции:

def prepData(request):

    if request.method == 'OPTIONS':
        headers = {
            'Access-Control-Allow-Origin': '*',
            'Access-Control-Allow-Methods': 'POST',
            'Access-Control-Allow-Headers': 'Content-Type',
            'Access-Control-Max-Age': '3600'
        }
        return ('', 204, headers)

    headers = {
        'Access-Control-Allow-Origin': '*'
    }
    return ("", 200, headers)

Это выглядит очень похоже на функцию, представленную Google на их странице документации с одним существенным отличием: я использую POST, а не GET.

При вызове функции я вижу успех сообщение (Function execution took 13 ms, finished with status code: 200) примерно в 50% случаев и ошибка соединения (Function execution took 11 ms, finished with status: 'connection error') во всех остальных случаях. Всякий раз, когда я получаю ошибку соединения внутри GCF, консоль Chrome регистрирует ошибку: No 'Access-Control-Allow-Origin' header is present on the requested resource.

В настоящее время я рассматриваю три возможные причины:

  1. Инфраструктура GCP. Я нашел несколько связанных вопросов, в которых Google признавал некоторые проблемы с инфраструктурой.
  2. Python ошибка
  3. ошибка CORS (пользователь sideshowbarker говорит: очень маловероятно)

Что причина проблемы и как ее исправить?


Вот код JS, который вызывает скрипт Python:

    const xhr = new XMLHttpRequest();
    xhr.open("POST", "[URL]");
    xhr.setRequestHeader("Content-Type", "application/json");
    xhr.send(stringified_serialized_data);

Править 4/2/20:

Я обнаружил способ не вызвать ошибку: Добавьте некоторый код между двумя операторами возврата. Я еще не выяснил, какой код нужен, но d = request.get_json() кажется достаточным. Новый код выглядит следующим образом:

def prepData(request):

    if request.method == 'OPTIONS':
        headers = {
            'Access-Control-Allow-Origin': '*',
            'Access-Control-Allow-Methods': 'POST',
            'Access-Control-Allow-Headers': 'Content-Type',
            'Access-Control-Max-Age': '3600'
        }
        return ('', 204, headers)

    d = request.get_json() #THIS LINE IS NEW

    headers = {
        'Access-Control-Allow-Origin': '*'
    }
    return ("", 200, headers)

1 Ответ

3 голосов
/ 17 марта 2020

ОБНОВЛЕНИЕ

Покопавшись дальше, мы поняли, что проблема на самом деле заключается в ошибке в сервисе Google Cloud Function. Эта ошибка касается конкретно облачных функций, использующих среду выполнения Python. Эти функции вызовут ошибку соединения (и вернут код 500), если они получат HTTP-запрос POST с телом больше ~ 10 КБ. Интересно, что это происходит не в каждом запросе с такими характеристиками, но в большинстве из них.

Служба поддержки Google была проинформирована об этой проблеме, и они признали ошибку. Они создали опубликованную c проблему в своем трекере проблем , которая должна быть обновлена ​​с дополнительной информацией в соответствии с ходом решения. На день написания статьи проблема помечена как «Новая».

Обходной путь: как предполагает @Timon, кажется, что вызов request.get_json() в функции, похоже, решает проблему для запросов с телами JSON. Это не будет работать, если тело вашего запроса использует другой формат.


СТАРЫЙ ОТВЕТ

Я только что установил чистую функцию G C с точно таким же кодом, который вы предоставили, и он работал безупречно. Я могу отправлять запросы через браузер (используя ваш код JS), и они никогда не перестают работать.

Это оставляет нам две возможности:

  1. В вашем браузере или вашем inte rnet подключении есть что-то, что вызывает сбой некоторых ваших запросов.
  2. В вашем GCF есть что-то, что вызывает ошибки.

Для варианта 1 отметьте это:

  • Встречаются ли неудачные запросы в пакетах? Или они случайно выбраны? Если они появляются партиями, проблема может быть в вашем rnet подключении.
  • Используете ли вы какой-либо VPN или прокси? Попробуйте отключить его.
  • Вы пробовали несколько браузеров? Если нет, попробуйте. Одинаково ли описанное поведение во всех них?

Для варианта 2 проверьте следующее:

  • Является ли ваша функция точно таким же кодом, который вы опубликовали? Если нет, и в нем больше кода, проблема, вероятно, здесь.
  • Развертываете ли вы свою функцию с помощью какого-либо инструмента командной строки? Да, попробуйте сделать это через встроенный редактор на веб-сайте GCP.
  • В настройках сети вашей функции (в дополнительных настройках) обязательно выберите «Разрешить все трафик c»
...