如何使用 Lambda 访问 HTTP headers 以请求 AWS API 网关?

How to access HTTP headers for request to AWS API Gateway using Lambda?

我在 API Gateway FAQ 中看到可以访问发送到 API 网关的请求 header...

If you already utilize OAuth tokens or any other authorization mechanism, you can easily setup API Gateway not to require signed API calls and simply forward the token headers to your backend for verification.

但是,我在文档中找不到如何执行此操作的示例,也不清楚如何使用 Lambda 访问此数据。

我能够设置一个开放的 API 并获得 JSON object 的访问权,它是 POST (Walkthrough: API Gateway and Lambda Functions) 的一部分,但是为了使用我自己的提供商实现 OAuth 2.0 样式 API,我需要访问 "Authorization" header.

我更喜欢使用 Lambda 和 Java 8 进行设置,但是使用 node.js 的示例也有助于理解如何完成此操作。

您需要在仪表板屏幕上的 Integration Request 面板内创建输入映射,描述您的 API 方法。

以下代码将 name 查询输入参数转换为 Lambda Event input object:

{
   "name": "$input.params('name')"
}

截图:

您可以在原文 API Gateway to Lambda input thread on AWS Forums 中找到更多相关信息。

首先,您需要从 HTTP GET 请求中捕获 Authorization header。然后您需要将该值映射到 Lambda 事件 object.

转到 API 方法仪表板并单击“方法请求”。在那里你可以添加一个名为 AuthorizationHTTP Request Header,如下所示。

这将捕获 Authorization header 以便您以后可以使用它。

现在返回方法仪表板并单击 Integration Request。从这里,您可以使用像这样的映射将 header 的值传递到 Lambda 函数。

{
    "Authorization": "$input.params('Authorization')"
}

现在在您的 Lambda 函数中,您可以获得这样的值。

event.Authorization

您可以在集成请求中使用以下映射模板将所有路径、查询和 header 参数一般映射到 Lambda 事件中。您仍然需要在 API 网关的方法请求部分注册它们,但您至少可以将映射模板与您要使用的特定参数分离。这样您就不必在每次更改 headers、查询或路径参数时都更改映射模板代码。

我写了一篇博客 post,其中提供了映射模板的更多详细信息和一些解释:http://kennbrodhagen.net/2015/12/06/how-to-create-a-request-object-for-your-lambda-event-from-api-gateway/

这是您可以使用的映射模板:

{
  "method": "$context.httpMethod",
  "body" : $input.json('$'),
  "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
  }  
}

虽然这是一个旧话题,但我发现最好使用 lambda 代理集成。有了这个,你不必在 API 网关中配置任何东西,你可以在你的 lambda 函数中获得所有 headers...

https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html

根据 Prabhat 的回答,使用 lambda 代理集成请求设置是执行此操作的最简单方法,之后您可以通过

访问请求 headers、路径参数和查询参数
event['pathParameters']['param1']
event["queryStringParameters"]['queryparam1']
event['requestContext']['identity']['userAgent']
event['requestContext']['identity']['sourceIP']

kennbrodhagen 的解决方案对我非常有用,有关详细信息,请参阅他的回答和博客。由于发布者表达了对 Java 实现的偏好,我花了一段时间才弄清楚如何在 java 中实现 Kenn 的处理程序,我只是分享对应的 Java 代码:

public class MyHandler implements RequestHandler<Map<String,Object>,String> {

    @Override
    public String handleRequest(Map<String,Object> eventMap, Context context) {
        LambdaLogger logger = context.getLogger();
        logger.log("Body:" + eventMap.get("body"));
        logger.log("Headers:" + eventMap.get("headers"));
        logger.log("Method:" + eventMap.get("method"));
        logger.log("Params:" + eventMap.get("params"));
        logger.log("Query:" + eventMap.get("query"));
        return("{}");
    }
}

这是一个示例事件 object:

{
"requestContext": {
    "elb": {
        "targetGroupArn": "arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/lambda-279XGJDqGZ5rsrHC2Fjr/49e9d65c45c6791a"
    }
},
"httpMethod": "GET",
"path": "/lambda",
"queryStringParameters": {
    "query": "1234ABCD"
},
"headers": {
    "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
    "accept-encoding": "gzip",
    "accept-language": "en-US,en;q=0.9",
    "connection": "keep-alive",
    "host": "lambda-alb-123578498.us-east-2.elb.amazonaws.com",
    "upgrade-insecure-requests": "1",
    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36",
    "x-amzn-trace-id": "Root=1-5c536348-3d683b8b04734faae651f476",
    "x-forwarded-for": "72.12.164.125",
    "x-forwarded-port": "80",
    "x-forwarded-proto": "http",
    "x-imforwards": "20"
},
"body": "",
"isBase64Encoded": false

}

事件 object 中包含 "headers",您可以使用 event.headers.<header key>[=13= 访问发送到 API 网关的请求 headers ]