Вызов функции

Функцию можно вызвать:

Для каждого способа есть определенная структура данных запроса к функции и ответа функции.

Вызов функции с помощью HTTP

Если функция вызывается для обработки HTTP-запроса, то она получает первым аргументом данные о запросе в формате JSON: название HTTP-метода, заголовки, аргументы и другие параметры запроса.

Результат, который возвращает функция, также должен представлять из себя JSON-документ, содержащий код ответа HTTP, заголовки ответа и содержимое ответа. Cloud Functions автоматически обработает этот JSON, и пользователь получит данные в виде стандартного HTTP-ответа.

Примечание

Вы можете запускать функцию с указанием параметра строки запроса integration=raw. При использовании такой формы вызова функция не может анализировать и задавать HTTP-заголовки:

  • Содержимое тела HTTP-запроса передается первым аргументом (без преобразования в JSON-структуру).
  • Содержимое тела HTTP-ответа совпадает с ответом функции (без преобразования и проверки структуры), HTTP-статус ответа: 200.

Структура запроса

JSON-структура запроса:

{
    "httpMethod": "<название HTTP метода>",
    "headers": <словарь со строковыми значениями HTTP-заголовков>,
    "multiValueHeaders": <словарь со списками значений HTTP-заголовков>,
    "queryStringParameters": <словарь queryString-параметров>,
    "multiValueQueryStringParameters": <словарь списков значений queryString-параметров>,
    "requestContext": <словарь с контекстом запроса>,
    "body": "<содержимое запроса>",
    "isBase64Encoded": <true или false>
}

Подробное описание запроса:

  • httpMethod — название HTTP метода, такое как: DELETE, GET, HEAD, OPTIONS, PATCH, POST или PUT.

  • headers — словарь строк, содержащий HTTP-заголовки запроса и их значения. Если один и тот же заголовок передан несколько раз, словарь содержит последнее переданное значение.

  • multiValueHeaders — словарь, содержащий HTTP-заголовки запроса и списки с их значениями. Он содержит те же самые ключи, что и словарь headers, но если какой-либо заголовок повторялся несколько раз, список для него будет содержать все переданные значения для данного заголовка. Если заголовок был передан всего один раз, он включается в этот словарь, и список для него будет содержать одно значение.

  • queryStringParameters — словарь, содержащий параметры запроса. Если один и тот же параметр указан несколько раз, словарь содержит последнее указанное значение.

  • multiValueQueryStringParameters — словарь, содержащий для каждого параметра запроса список со всеми указанными значениями. Если один и тот же параметр указан несколько раз, словарь содержит все указанные значения.

  • requestContext содержит следующую структуру:

    {
        "identity": "<набор пар ключ:значение для аутентификации пользователя>",
        "httpMethod": "<DELETE, GET, HEAD, OPTIONS, PATCH, POST или PUT>",
        "requestId": "<ID запроса, генерируется в роутере>",
        "requestTime": "<время запроса в формате CLF>",
        "requestTimeEpoch": "<время запроса в формате Unix>"
    }
    

    Структура элемента identity:

    {
        "sourceIp": "<адрес, с которого был сделан запрос>",
        "userAgent": "<содержимое HTTP-заголовка User-Agent исходного запроса>"
    }
    
  • body — содержимое запроса в виде строки. Данные могут быть закодированы в формат Base64 (в этом случае Cloud Functions установит параметр isBase64Encoded: true).

    Примечание

    Если функция вызывается с заголовком Content-Type: application/json, то содержимое body останется в исходном формате (значение параметра isBase64Encoded: false).

  • isBase64Encoded — если body содержит данные закодированные в Base64, то Cloud Functions установит значение параметра в true.

Отладка функции

Чтобы отладить обработку параметров, используйте функцию, которая возвращает JSON-структуру запроса. Пример такой функции приведен ниже.

module.exports.handler = async (event) => {
    return { 
        body: JSON.stringify(event)
    };
};

Например, для запроса:

curl -XPOST -d "hello, world!" "https://functions.yandexcloud.net/<ID функции>?a=1&a=2&b=1"

Результат будет выглядеть следующим образом:

{
  "httpMethod": "POST",
  "headers": {
    "Accept": "*/*",
    "Content-Length": "13",
    "Content-Type": "application/x-www-form-urlencoded",
    "User-Agent": "curl/7.58.0",
    "X-Real-Remote-Address": "[88.99.0.24]:37310",
    "X-Request-Id": "cd0d12cd-c5f1-4348-9dff-c50a78f1eb79",
    "X-Trace-Id": "92c5ad34-54f7-41df-a368-d4361bf376eb"
  },
  "path": "",
  "multiValueHeaders": {
    "Accept": [ "*/*" ],
    "Content-Length": [ "13" ],
    "Content-Type": [ "application/x-www-form-urlencoded" ],
    "User-Agent": [ "curl/7.58.0" ],
    "X-Real-Remote-Address": [ "[88.99.0.24]:37310" ],
    "X-Request-Id": [ "cd0d12cd-c5f1-4348-9dff-c50a78f1eb79" ],
    "X-Trace-Id": [ "92c5ad34-54f7-41df-a368-d4361bf376eb" ]
  },
  "queryStringParameters": {
    "a": "2",
    "b": "1"
  },
  "multiValueQueryStringParameters": {
    "a": [ "1", "2" ],
    "b": [ "1" ]
  },
  "requestContext": {
    "identity": {
      "sourceIp": "88.99.0.24",
      "userAgent": "curl/7.58.0"
    },
    "httpMethod": "POST",
    "requestId": "cd0d12cd-c5f1-4348-9dff-c50a78f1eb79",
    "requestTime": "26/Dec/2019:14:22:07 +0000",
    "requestTimeEpoch": 1577370127
  },
  "body": "aGVsbG8sIHdvcmxkIQ==",
  "isBase64Encoded": true
}

Служебные данные

Опционально функция может принимать второй аргумент со следующей структурой:

{
  "requestId": "<идентификатор запроса>",
  "functionName": "<идентификатор функции>",
  "functionVersion": "<идентификатор версии функции>",
  "memoryLimitInMB": "<объем памяти версии функции, МБ>",
  "token": "<опционально, IAM-токен>",
}
  • requestId — идентификатор запроса к функции, генерируется при обращении к функции и отображается в журнале вызова функции.
  • functionName — идентификатор функции.
  • functionVersion — идентификатор версии функции.
  • memoryLimitInMB — объем памяти, указанный для версии функции, МБ.
  • tokenIAM-токен сервисного аккаунта, указанного для версии функции. Актуальное значение генерируется автоматически. Используется для работы с API Яндекс.Облака. Поле присутствует только если для версии функции указан корректный сервисный аккаунт.

Пример использования служебных данных в функции:

module.exports.handler = async (event, context) => {
    const iamToken = context.token;
    ...
    return { 
        body: ...
    };
};

Структура ответа

Cloud Functions интерпретирует результат выполнения функции для того, чтобы заполнить содержимое HTTP-ответа, его заголовки и код состояния. Для этого функция должна возвращать ответ следующей структуры:

{
    "statusCode": <HTTP код ответа>,
    "headers": <словарь со строковыми значениями HTTP-заголовков>,
    "multiValueHeaders": <словарь со списками значений HTTP-заголовков>,
    "body": "<содержимое ответа>",
    "isBase64Encoded": <true или false>
}

Подробное описание ответа:

  • statusCode — код состояния HTTP, по которому клиент узнаёт результаты запроса.
  • headers — словарь строк, содержащий HTTP-заголовки ответа и их значения.
  • multiValueHeaders — словарь, в котором для HTTP-заголовков ответа можно указать одно или несколько значений в виде списка. Если один и тот же заголовок указан и в headers и в multiValueHeaders, содержимое headers игнорируется.
  • body — содержимое ответа в виде строки. Для работы с бинарными данными содержимое может быть закодировано в формат Base64. В этом случае установите параметр isBase64Encoded: true.
  • isBase64Encoded — если body закодирован в формат Base64, установите значение параметра в true.

Обработка ошибок в коде пользовательской функции

В случае возникновения необработанной ошибки в пользовательском коде, Cloud Functions вернет результат с кодом ошибки 502 и подробным описанием ошибки в виде следующей JSON-структуры:

{
  "errorMessage": "<сообщение ошибки>",
  "errorType": "<тип ошибки>",
  "stackTrace": <опционально, список вызываемых методов>
}

Подробное описание ошибки:

  • errorMessage — строка с описанием ошибки.
  • errorType — зависящий от языка программирования тип ошибки или исключения.
  • stackTrace — стек выполнения функции в момент возникновения ошибки.

Конкретное содержимое указанных полей зависит от языка программирования и среды выполнения вашей функции.

Ошибка в случае некорректной JSON-структуры ответа

Если структура ответа вашей фунцкии не соответствует тому, что описано в разделе Структура данных ответа, то Cloud Functions вернет результат с кодом ошибки 502 и следующий ответ:

{
  "errorMessage": "Malformed serverless function response: not a valid json",
  "errorType": "ProxyIntegrationError",
  "payload": "<исходное содержимое ответа функции>"
}

Возможные коды ответа Cloud Functions

В случае ошибки в пользовательской функции к ответу добавляется заголовок X-Function-Error: true.

Cloud Functions может возвращать результат со следующими HTTP-кодами:

  • 200 OK — функция успешно выполнена.
  • 400 BadRequest — ошибка в параметрах HTTP-запроса (TODO: примеры).
  • 403 Forbidden — запрос не может быть выполнен из-за ограничений в доступе для клиента к функции.
  • 404 Not Found — по указанному URL не найдена функция.
  • 413 Payload Too Large — превышение лимита на размер JSON-структуры запроса превышает 3,5 МБ.
  • 429 TooManyRequests — слишком высокая интенсивность вызова функции:
    • Превышение квоты на количество выполняемых запросов.
    • Текущий запрос не был выполнен, так как все исполнители уже перегружены существующими запросами к данной функции.
  • 500 Internal Server Error — внутренняя ошибка сервера.
  • 502 BadGateway — ошибка в коде функции или в формате возвращаемого JSON-ответа.
  • 503 Service Unavailable — недоступность сервиса Cloud Functions.
  • 504 Gateway Timeout — превышено максимальное время выполнения функции до таймаута.

Фильтрация заголовков сообщений

Ваша функция получает и передает содержимое HTTP-заголовков в виде полей JSON-структуры, как описано выше. Некоторые заголовки запроса и ответа удаляются или переименовываются, как описано ниже.

Удаляются из запроса:

  • "Expect"
  • "Te"
  • "Trailer"
  • "Upgrade"
  • "Proxy-Authenticate"
  • "Authorization"
  • "Connection"
  • "Content-Md5"
  • "Max-Forwards"
  • "Server"
  • "Transfer-Encoding"
  • "Www-Authenticate"
  • "Cookie"
  • Удаляются из ответа:

    • "Host"
    • "Authorization"
    • "User-Agent"
    • "Connection"
    • "Max-Forwards"
    • "Cookie"
  • Вызывают ошибку, если присутствуют в ответе:

    • "Proxy-Authenticate"
    • "Transfer-Encoding"
    • "Via"
    • "Www-Authenticate"
  • Перезаписываются с добавлением префикса X-Yf-Remapped-:

    • "Content-Md5"
    • "Date"
    • "Server"

Вызов функции с помощью YC CLI

Вызов функции с помощью CLI — это HTTP-запрос с методом POST и параметром integration=raw (без преобразования запроса в JSON-структуру и без проверки ответа).

Посмотрите справку о команде вызова функции:

yc serverless function invoke --help
Invoke the specified function

Usage:
  yc serverless function invoke <FUNCTION-NAME>|<FUNCTION-ID> [Flags...] [Global Flags...]

Flags:
      --id string          Function id.
      --name string        Function name.
      --tag string         Tag. Default $latest.
  -d, --data string        Data to be sent
      --data-file string   Data (file location) to be sent
      --data-stdin         Await stdin for data to be sent

Подробное описание способов передачи данных с использованием разных флагов и аргументов:

  • Флаг или аргумент не указан — передается пустая строка.

  • -d, --data — данные передаются как аргумент.

    yc serverless function invoke <ID функции> -d '{"queryStringParameters": {"parameter_name": "parameter_value"}}'
    
  • --data-file — данные читаются из файла.

    yc serverless function invoke <ID функции> --data-file <путь к файлу>
    

    Аналогично команде с аргументом -d, имеющим значение @<имя файла>: yc serverless function invoke b09bhaokchn9pnbrlseb -d @<путь к файлу>

  • --data-stdin — данные читаются из потока ввода.

    echo '{"queryStringParameters": {"parameter_name": "parameter_value"}}' | yc serverless function invoke <ID функции> --data-stdin
    

    Аналогично команде с аргументом -d, имеющим значение @-:

    echo '{"queryStringParameters": {"parameter_name": "parameter_value"}}' | yc serverless function invoke <ID функции> -d @-`.