【问题标题】:AWS Lambda - Get API Gateway path in the lambda functionAWS Lambda - 在 lambda 函数中获取 API Gateway 路径
【发布时间】:2020-05-28 01:14:26
【问题描述】:

我有一个绑定到 API Gateway 的 Lambda 函数,我正在尝试从传递给 Lambda 函数的事件或上下文对象中获取路径和阶段。

AWS控制台生成的映射模板如下:

##  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('$'),
"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" : {
"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",
    "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"
    }
}

我正在尝试从上下文对象中获取舞台,如下所示:

exports.handler = function(event, context) {
 console.log("Stage: " + context.stage);
 ...
}

但 logcat 显示为 Stage : undefined

我还有其他查询参数,我可以像这样从事件对象的参数中提取这些参数

var id = event.params.querystring.id;
var publisher_id = event.params.querystring.publisher_id;

如何使用上述映射模板从上下文中提取路径和阶段值?

【问题讨论】:

  • 您是否尝试过记录整个上下文以查看其中的内容?如果您更改了映射模板,请确保之后“部署”API Gateway 以使模板生效。
  • 找到了一种从事件对象中获取它的方法。当然不是我想要的,但仍然需要看看为什么上下文没有给出它。

标签: node.js amazon-web-services aws-lambda aws-api-gateway


【解决方案1】:

您必须在 API 网关上的方法集成中勾选“Lambda 代理集成”,才能接收阶段信息。

要使用阶段变量自定义 HTTP 集成端点,您必须首先配置一个指定名称的阶段变量,例如 url,然后为其分配一个值,例如 example.com。接下来,从您的方法配置中,设置 HTTP 代理集成,您可以告诉 API Gateway 使用阶段变量值 http://${stageVariables.url},而不是输入端点的 URL。此值告诉 API Gateway 在运行时替换您的阶段变量 ${},具体取决于您的 API 正在运行的阶段。您可以以类似的方式引用阶段变量,以在凭证字段中指定 Lambda 函数名称、AWS 服务代理路径或 AWS 角色 ARN。

参考:https://docs.aws.amazon.com/apigateway/latest/developerguide/stage-variables.html

【讨论】:

  • 这是不正确的。阶段信息在 API Gateway 映射模板docs.aws.amazon.com/apigateway/latest/developerguide/… 中可用
  • docs.aws.amazon.com/apigateway/latest/developerguide/… - 要使用阶段变量,您需要集成映射
  • 这只是为了遵循该页面上给出的示例。 API Gateway 在 Lambda 代理集成成为现实之前就支持阶段变量。如果您必须使用代理集成来使用阶段变量,那么为什么阶段变量会在自定义 API 网关映射模板中可用,而这些模板仅用于非代理集成?
  • 我会再次尝试 Lambda 代理,但是当映射表明该值将在上下文中时,为什么我无法检索它?
【解决方案2】:

我在映射模板中添加了这一行"stage":"$context:stage",,并使用event[stage] 来检索值。这行得通。不要忘记重新部署 api。

更改的映射模板:

##  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('$'),
"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
},
"stage" : "$context.stage", // added this line
"context" : {
"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",
    "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"
    }
}

和代码:

exports.handler = function(event, context) {
 console.log("Stage: " + event[stage]);
 ...
}

【讨论】:

    【解决方案3】:

    stage 值在 event.context.stage 中可用。所以把你的代码改成这样:

    exports.handler = function(event, context) {
     console.log("Stage: " + event.context.stage);
     ...
    }
    

    我们正在使用此处列出的基本映射模板:

    ##  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('$'),
    "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"
        }
    }
    

    【讨论】:

    • 是的,这也可以解决问题,无需在映射模板中添加额外的“阶段”
    猜你喜欢
    • 2018-08-28
    • 2018-02-02
    • 2021-08-04
    • 2018-12-08
    • 1970-01-01
    • 2021-05-07
    • 2018-03-07
    • 2017-09-19
    • 2020-04-21
    相关资源
    最近更新 更多