Настройка заголовков ответов с помощью 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
Любое руководство, опыт, мысли высоко ценятся!