12

我正在尝试查看如何从 lambda 代码中访问请求标头和正文值。如果请求正文是 JSON 格式,它似乎会自动被解析并在事件对象中可用。

如何访问 Lambda 内任何类型的传入“Content-Type”请求的完整查询字符串、请求正文、请求标头 (cookie)?


下面的编辑是我收集的信息,以帮助解决可能相关或不相关的问题。如果您愿意,请忽略它们。


编辑:

我在这里这里浏览了关于 SE 的现有问题。根据这个线程,使用$input.json('$')应该可以解决问题。我猜上面这些链接的答案已经过时了,因为默认情况下 API 网关似乎可以识别请求中的 JSON,如果是这样,它可以在event对象中使用而无需配置任何映射模板。

按照建议设置映射对我不起作用。它不包含请求头信息。

这是有关如何配置的屏幕截图。

在此处输入图像描述


在此处输入图像描述

“headers”键返回一个空白值。使用$input.params('$')还是"$input.params('$')"出错了。


编辑 2

尝试在方法请求中定义标头。仍然没有在 lambda 中获取 User-Agent 值。

在此处输入图像描述


编辑 3

我在 API Gateway 上使用了以下模板映射

{
    "request": $input.json('$'),
    "headers": "$input.params()"
}

以及下面的 lambda 代码

context.succeed("event.key32:"+JSON.stringify(event, null, 2) );

API 网关生成的响应显示了这一点 在此处输入图像描述

查看响应中的“标头”值,AWS-SDK/API 网关/cloudfront 似乎剥离了从 HTTP 客户端接收到的所有标头?这是 $input.params().header 返回的 JSON 的全文

header={CloudFront-Forwarded-Proto=https, CloudFront-Is-Desktop-Viewer=true, CloudFront-Is-Mobile-Viewer=false, CloudFront-Is-SmartTV-Viewer=false, CloudFront-Is-Tablet-Viewer=false, Content-Type=application/json, Via=1.1 5d53b9570d94ce920abbd471.cloudfront.net (CloudFront), 1.1 95eea7baa7ec95c9a41eca9e3ab7.cloudfront.net (CloudFront), X-Amz-Cf-Id=GBqmObLRy6Iem9bJbVPrrW1K3YoWRDyAaMpv-UkshfCsHAA==, X-Forwarded-For=172.35.96.199, 51.139.183.101, X-Forwarded-Port=443, X-Forwarded-Proto=https}}

它的标头中没有 User-Agent 字符串,尽管如上面的屏幕截图所示,它是由 REST 客户端发送的。有趣的是,整个查询字符串都可用。不确定这是否是访问它的预期方式。

4

4 回答 4

4

可以使用访问请求标头$input.params('header-name')

令人惊讶的是,上面的代码无法访问 User-Agent 标头。您需要跳过以下环来检索它:

$context.identity.userAgent

应该可以使用以下代码访问请求正文/有效负载。更多参考hereherehere

{
   "reqbody": "$input.path('$')"
}

目前尚不清楚请求正文是否应采用 JSON 格式。需要注意的是,根据这篇文章,请求被视为 UTF-8。


目前似乎有两个错误

  1. “User-Agent”标头丢失/被 Amazon API 剥离。
  2. 当标头值包含双引号 (") 时,不会执行 lambda 函数。(我在 cloudwatch 日志中没有看到此类请求的日志条目)。相反,http 响应正文包含以下内容:

    {
       "Type": "User",
       "message": "Could not parse request body into json."
    }
    

在 Amazon API 中失败的示例请求 在此处输入图像描述

我相信这需要更正才能实现 ETag 缓存机制。

参考:

Etag 应该用双引号括起来。浏览器应该通过 If-None-Match 标头发回这个确切的值,这就是 Amazon API 中断的地方。

ETag 的语法?

HTTP:etag 的最大长度

http://gsnedders.com/http-entity-tags-confusion

于 2015-08-08T03:32:13.140 回答
2

似乎如果没有发送“Content-Type”,AWS API Gateway 会将其默认为“application/json”: https ://forums.aws.amazon.com/thread.jspa?threadID=215471

所以只需为“application/json”定义映射模板。

于 2015-10-01T03:06:12.560 回答
2

您必须在模板映射中获取您需要的信息并将它们发送回您的 Lambda 函数,这是我用来向 Lambda 函数发送信息的模板之一:

{
   "params" : "$input.params()",
   "content-type-value" : "$input.params().header.get('Content-Type')",
   "body" : "$input.json('$')",
   "request-id": "$context.requestId",
   "method": "$context.httpMethod",
   "resource": "$context.resourcePath",
   "id": "$input.params('id')" //This is a path parameter in my case
}

你可以这样做,或者你可以访问params.path.id(在我的情况下)。这是文档的链接

干杯,

于 2015-10-05T13:53:49.430 回答
1

我更新了在回答一个引用问题时使用的映射模板,以包含 userAgent 属性。

{
  "method": "$context.httpMethod",
  "body": $input.json('$'),
  "userAgent": "$context.identity.userAgent",
  "headers": {
    #foreach($param in $input.params().header.keySet())
    "$param": "$util.escapeJavaScript($input.params().header.get($param))" #if($foreach.hasNext),#end

    #end
  },
  "queryParams": {
    #foreach($param in $input.params().querystring.keySet())
    "$param": "$util.escapeJavaScript($input.params().querystring.get($param))" #if($foreach.hasNext),#end

    #end
  },
  "pathParams": {
    #foreach($param in $input.params().path.keySet())
    "$param": "$util.escapeJavaScript($input.params().path.get($param))" #if($foreach.hasNext),#end

    #end
  }  
}

此处提供了模板的详细说明:http: //kennbrodhagen.net/2015/12/06/how-to-create-a-request-object-for-your-lambda-event-from-api-gateway/

于 2016-03-13T14:48:19.427 回答