получить необработанные и проанализированные полезные данные от шлюза aws api внутри события? - PullRequest
1 голос
/ 02 апреля 2019

Я пытаюсь проверить слабые запросы на события, которые я получаю на моей лямбде, в настоящее время я использую api-шлюз с лямбда-сервером.

На моем serverless.yml у меня есть это для моего событияобработчик

          integration: lambda
          passthroughBehavior: "WHEN_NO_TEMPLATE"
          request:
              template:
                application/x-www-form-urlencoded: ${file(aws-api-gateway-form-to-json.ftl)}

Я получил содержимое файла, сгенерированного через Консоль прокси-сервера AWS API, я использую сгенерированный проход запроса метода с одна модификация , которая просто добавляет необработанное телок полезной нагрузке, которая должна быть доставлена ​​в лямбду "rawBody": "$input.body",, однако, когда я добавляю эту модификацию, запросы перестают поступать в лямбду, и я получаю ошибки при отправке запросов.

##  See http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html
##  This template will pass through all parameters including path, querystring, header, stage variables, and context through to the integration endpoint via the body/payload
#set($allParams = $input.params())
{
"body-json" : $input.json('$'),
"rawBody": "$input.body",
"params" : {
#foreach($type in $allParams.keySet())
    #set($params = $allParams.get($type))
"$type" : {
    #foreach($paramName in $params.keySet())
    "$paramName" : "$util.escapeJavaScript($params.get($paramName))"
        #if($foreach.hasNext),#end
    #end
}
    #if($foreach.hasNext),#end
#end
},
"stage-variables" : {
#foreach($key in $stageVariables.keySet())
"$key" : "$util.escapeJavaScript($stageVariables.get($key))"
    #if($foreach.hasNext),#end
#end
},
"context" : {
    "account-id" : "$context.identity.accountId",
    "api-id" : "$context.apiId",
    "api-key" : "$context.identity.apiKey",
    "authorizer-principal-id" : "$context.authorizer.principalId",
    "caller" : "$context.identity.caller",
    "cognito-authentication-provider" : "$context.identity.cognitoAuthenticationProvider",
    "cognito-authentication-type" : "$context.identity.cognitoAuthenticationType",
    "cognito-identity-id" : "$context.identity.cognitoIdentityId",
    "cognito-identity-pool-id" : "$context.identity.cognitoIdentityPoolId",
    "http-method" : "$context.httpMethod",
    "stage" : "$context.stage",
    "source-ip" : "$context.identity.sourceIp",
    "user" : "$context.identity.user",
    "user-agent" : "$context.identity.userAgent",
    "user-arn" : "$context.identity.userArn",
    "request-id" : "$context.requestId",
    "resource-id" : "$context.resourceId",
    "resource-path" : "$context.resourcePath"
    }
}

Чтобы ответить на некоторыеобратной связи.Если я использую Use Lambda Proxy integration в Integration Request, я получаю такую ​​полезную нагрузку, что замечательно, но мне также нужен необработанный элемент, которого нет.

{ body: 
{ token: 'xxxxxxxxxxxx',
team_id: 'xxxxxxxxxxxx',
api_app_id: 'xxxxxxxxxxxx',
event: 
{ client_msg_id: 'xxxxxxxxxxxx',
type: 'message',
text: 'xxxxxxxxxxxx',
user: 'xxxxxxxxxxxx',
ts: '123456789.000200',
channel: 'xxxxxxxxxxxx',
event_ts: '123456789.000200',
channel_type: 'im' },
type: 'event_callback',
event_id: 'xxxxxxxxxxxx',
event_time: 123456798,
authed_users: [ 'xxxxxxxxxxxx' ] },
method: 'POST',
principalId: '',
stage: 'dev',
cognitoPoolClaims: { sub: '' },
enhancedAuthContext: {},
headers: 
{ Accept: '*/*',
'Accept-Encoding': 'gzip,deflate',
'CloudFront-Forwarded-Proto': 'https',
'CloudFront-Is-Desktop-Viewer': 'true',
'CloudFront-Is-Mobile-Viewer': 'false',
'CloudFront-Is-SmartTV-Viewer': 'false',
'CloudFront-Is-Tablet-Viewer': 'false',
'CloudFront-Viewer-Country': 'US',
'Content-Type': 'application/json',
Host: 'xxxxxxxxxxxx.execute-api.region.amazonaws.com',
'User-Agent': 'Slackbot 1.0 (+https://api.slack.com/robots)',
Via: '1.1 xxxxxxxxxxxx.cloudfront.net (CloudFront)',
'X-Amz-Cf-Id': 'xxxxxxxxxxxx==',
'X-Amzn-Trace-Id': 'Root=xxxxxxxxxxxx',
'X-Forwarded-For': 'xx.xx.xx.xx, xx.xx.xx.xx',
'X-Forwarded-Port': '443',
'X-Forwarded-Proto': 'https',
'X-Slack-Request-Timestamp': '12345678',
'X-Slack-Signature': 'v0=xxxxxxxxxxxx' },
query: {},
path: {},
identity: 
{ cognitoIdentityPoolId: '',
accountId: '',
cognitoIdentityId: '',
caller: '',
sourceIp: 'xx.xx.xx.xx',
accessKey: '',
cognitoAuthenticationType: '',
cognitoAuthenticationProvider: '',
userArn: '',
userAgent: 'Slackbot 1.0 (+https://api.slack.com/robots)',
user: '' },
stageVariables: {} }

Ответы [ 2 ]

4 голосов
/ 02 апреля 2019

Я не знаю, как работает сервер, мой рабочий процесс ограничен написанием кода локально и загрузкой zip-файлов, а любая другая конфигурация выполняется на самом AWS Consolse.

Я полагаю, что вам нужна небольшая функция под названием Интеграция с Lambda Proxy , вы найдете ее на вкладке Запрос на интеграцию на API-шлюзе. Он предоставляет два стандартных шаблона сопоставления как для запроса, так и для ответа.

Когда вы используете Lambda Proxy Integration, ваш объект события будет выглядеть примерно так:

{
  "resource": "/users/single",
  "path": "/users/single",
  "httpMethod": "GET",
  "headers": {
    "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
    "accept-encoding": "gzip, deflate, br",
    "accept-language": "en-GB,en-US;q=0.9,en;q=0.8",
    "Host": "xxxxxxx.execute-api.xxxx.amazonaws.com",
    "upgrade-insecure-requests": "1",
    "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36",
    "X-Amzn-Trace-Id": "Root=xxxxxxxxxxxxxxxxx",
    "X-Forwarded-For": "xx.xx.xx.xx",
    "X-Forwarded-Port": "443",
    "X-Forwarded-Proto": "https"
  },
  "multiValueHeaders": {
    "accept": [
      "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"
    ],
    "accept-encoding": ["gzip, deflate, br"],
    "accept-language": ["en-GB,en-US;q=0.9,en;q=0.8"],
    "Host": ["xxxxx.execute-api.xxxx.amazonaws.com"],
    "upgrade-insecure-requests": ["1"],
    "User-Agent": [
      "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"
    ],
    "X-Amzn-Trace-Id": ["Root=xxxxx"],
    "X-Forwarded-For": ["xx.xx.xx.xx"],
    "X-Forwarded-Port": ["443"],
    "X-Forwarded-Proto": ["https"]
  },
  // this contains the get body
  "queryStringParameters": { "id": "2" },
  "multiValueQueryStringParameters": { "id": ["2"] },
  // This contains pathParams, if you url looks like users/{id}, this object will contain a key called id containing the value from the URL
  "pathParameters": null,
  "stageVariables": null,
  "requestContext": {
    "resourceId": "xxxxx",
    "resourcePath": "/users/single",
    "httpMethod": "GET",
    "extendedRequestId": "xxxxxxx=",
    "requestTime": "xx/xx/xxxx:xx:xx:xx +0000",
    "path": "/dev/users/single",
    "accountId": "642495909037",
    "protocol": "HTTP/1.1",
    "stage": "dev",
    "domainPrefix": "xxxxx",
    "requestTimeEpoch": 1547113372715,
    "requestId": "xx-xx-xx-xxxxx-xxxxxxxxx",
    "identity": {
      "cognitoIdentityPoolId": null,
      "accountId": null,
      "cognitoIdentityId": null,
      "caller": null,
      "sourceIp": "xx.xx.xx.xx",
      "accessKey": null,
      "cognitoAuthenticationType": null,
      "cognitoAuthenticationProvider": null,
      "userArn": null,
      "userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36",
      "user": null
    },
    "domainName": "xxxxxxx.execute-api.xxxxxxx.amazonaws.com",
    "apiId": "xxxx"
  },
  "body": null, //this contains the post body
  "isBase64Encoded": false
}

Ключ "body" всегда является строкой, его необходимо проанализировать в соответствии с типом содержимого, т. Е. Json, www-form-encoded или любым другим.

При использовании Lambda Proxy объект, который вы возвращаете из обработчика , имеет , чтобы следовать определенному формату, в соответствии с которым API-шлюз сопоставляет его с ответом, а именно:

{
    statusCode: Integer,
    headers: HashTable<String, String>,
    body: String
}
1 голос
/ 06 апреля 2019

Так что в Serverless здесь есть несколько вариантов интеграции. https://serverless.com/framework/docs/providers/aws/events/apigateway/#request-templates

Чтобы уточнить, вы используете lambda, так что вы попадаете на крючок для ручного определения вашего шаблона в API Gateway (который вы предоставили).

Когда вы пытаетесь заставить serverless.yml использовать lambda-proxy (альтернативно принятый как aws-proxy или aws_proxy), вы говорите, что получили все, что вам отправили в другом формате, который не содержал необработанного корпус.

Примечание: с точки зрения интеграции API-шлюза LAMBDA_PROXY вы должны получить полное тело запроса. Это интеграция, которую я использую все время (вместе с методом ANY на пути запроса {proxy+}), чтобы специально избегать шаблонов отображения. Я не уверен, что Serverless Framework завершит дополнительный анализ event, но у вас действительно должно быть все тело в событии, переданном обработчику функции Lambda. Я написал основу для AWS без сервера, и это то, что я использую там, и я обрабатываю форматы запросов, отличные от JSON. Так что я знаю, что вы можете получить «сырое» тело. Вам нужно использовать фреймворк в этом случае?

Хорошо, я понимаю, что вы не можете работать с интеграцией lambda-proxy и должны прибегнуть к пользовательскому отображению в API Gateway.

Честно говоря, мне нужно увидеть некоторые ошибки из CloudWatch. Я также хотел бы увидеть примеры примеров тела запроса, которые вы ожидаете получить. Вы сказали, что есть ошибки, но ничего о них не публиковали. Я предполагаю, что это проблема шаблона в API Gateway. Прошло некоторое время с тех пор, как я детально работал с отображениями (опять же, интеграция LAMBDA_PROXY - это путь), но позвольте мне высказать некоторые идеи.

Помните, что $input.body может включать JSON, который может испортить шаблон. Это создаст ошибку, и ваша лямбда никогда не сработает. В CloudWatch вы увидите, что не можете разобрать что-либо.

Вы можете попробовать функцию $util.escapeJavaScript(). Вы можете попробовать хитрость и с помощью функции $util.base64Decode() (для этого требуется включить поддержку двоичного кода в вашем API).

API Gateway может работать с двоичными данными, представленными в виде строк base64, и это один из способов избежать проблем с отображением шаблонов. Тогда, например, "rawBody": "$util.base64Decode($input.body)" будет работать в вашем шаблоне сопоставления.

Чтобы включить бинарную поддержку, перейдите в настройки API Gateway API, и вы увидите раздел для Binary Media Types. Вы можете указать любую строку типа содержимого, которую вы хотите, даже application/json, если вы действительно этого хотите. Я думаю, что если вы принимаете JSON, вам, вероятно, будет хорошо его проанализировать (возможно, наряду с выходом из него) ... Но если вы застряли с чем-то странным, вам, возможно, придется это сделать. Хотя имейте в виду, это широкая настройка API. Я думаю, судя по тому, что вы поделились, вы просто использовали бы здесь application/x-www-form-urlencoded, поэтому обычные запросы JSON не будут затронуты, например.

Суть в том, что где-то произошла ошибка синтаксического анализа.

...