AWS Lambda устанавливает заголовки ответа при вызове из браузера AWS SDK - PullRequest
0 голосов
/ 26 апреля 2019

Настройка заголовков ответов с помощью API Gateway с интеграцией прокси-сервера AWS Lambda проста и выглядит следующим образом:

import zlib from 'zlib';

exports.handler = async (event, context, callback) => {
  const body = zlib.gzipSync(JSON.stringify({ data: 'mock' }));

  const headers = {};
  headers['Content-Type'] = 'application/json';
  headers['Content-Encoding'] = 'gzip';

  const responseObject = {
    statusCode: 200,
    headers,
    body: body.toString('base64'),
    isBase64Encoded: true
  };

  return callback(null, responseObject);
}

Все возвращается в сжатом виде, как ожидалось. Поскольку мы устанавливаем кодировку содержимого, браузер распаковывает ответ.

Вопрос в том, как аналогичным образом установить заголовки, если функция Lambda вызывается из браузера напрямую с помощью AWS SDK JS? API-шлюз - это служба, которая реализует заголовки в предыдущей настройке, без использования API-шлюза перед AWS. Лямбда-заголовки игнорируются и обычно имеют значение:

access-control-allow-origin: *
access-control-expose-headers: x-amzn-RequestId,x-amzn-ErrorType,x-amzn-ErrorMessage,Date,x-amz-log-result,x-amz-function-error
content-length: 1242
content-type: application/json
date: Fri, 26 Apr 2019 00:36:35 GMT
status: 200
x-amz-executed-version: $LATEST
x-amzn-remapped-content-length: 0
x-amzn-requestid: <REDACTED>
x-amzn-trace-id: <REDACTED>

Код вызова браузера AWS SDK JS выглядит примерно так:

import AWS from 'aws-sdk';

AWS.config.region = 'us-east-1'; // Region
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
    IdentityPoolId: '<SOME IDENTITY>',
});

const AWSLambda = new AWS.Lambda({region: REGION, apiVersion: '2015-03-31'});

const parameters = {
    FunctionName : 'MyFunctionName',
    InvocationType : 'RequestResponse',
    LogType : 'None',
    Payload: JSON.stringify({msg: 'hello lambda'})
};

(async () => {
  const response = await AWSLambda.invoke(shopParameters).promise();
  console.log(response);
})();

Возвращаемым ответом является указанный выше объект ответа в виде строки с общими заголовками. Браузер не распаковывает сжатый контент, возможно потому, что заголовок кодировки контента не установлен. AWS Lambda при вызове из браузера обрабатывает весь объект ответа Lambda как ответ и не выполняет преобразований, которые происходят с API Gateway. Например, API-шлюз может подобрать структуру объекта ответа и сопоставить заголовки объекта ответа с ответом перед отправкой клиенту.

Нет ли способа установить заголовки AWS Lambda без API Gateway? Или это единственный вариант распаковать содержимое gzip вручную на клиенте, используя что-то вроде https://github.com/nodeca/pako (вздох).

Идея не использовать API-шлюз возникла из документов AWS, найденных здесь, например, чтобы избежать затрат на API-шлюз: https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/browser-invoke-lambda-function-example.html

Любое руководство, опыт, мысли высоко ценятся!

Ответы [ 2 ]

3 голосов
/ 26 апреля 2019

Нет, нет способа сделать это без чего-то перед API сервиса Lambda - обычно это API-шлюз.

Ваш const responseObject фактически создает ответ, используя формат, указанный API-шлюзом - служба Lambda не выполняет интерпретацию ответа. Вот почему это не влияет на заголовки в вашем ответе, и почему base64 остается непереведенным - вся эта структура зависит от API-шлюза. Лямбда только что вернула JSON.

Если ответы достаточно малы, этим «чем-то» поочередно может быть Application Load Balancer , который может или не может быть достаточно простым для использования с Cognito , хотя аутентификация будет разные. По сути, он использует тот же формат ответа, что и API-шлюз, и балансировщик декодирует base64, прежде чем вернуть его в браузер.

Вы также можете вызывать функцию Lambda через HTTP (S) с помощью функции Lambda @ Edge CloudFront, автоматически устанавливать пользовательские заголовки и декодировать base64, но эта служба не имеет встроенной интеграции Cognito. и заметно отличается от полнофункциональной службы Lambda, поддерживающей только Node.js и выполняющей функцию Lambda в любом регионе AWS, ближайшем к браузеру, а не в регионе, где он был создан для лучшей глобальной производительности. Lambda @ Edge также ожидает другой выходной формат - это гораздо более продуманный дизайн, чем структура ответа, которую ожидает API Gateway, но как таковой он также не является взаимозаменяемым.

1 голос
/ 26 апреля 2019

В качестве альтернативы, в зависимости от ваших требований, стратегия, которую я использовал, заключается в том, чтобы лямбда записывала json в s3, где она была общедоступной, и ее можно было легко получить.

...