从AWS-API网关发布到Lambda

Tim*_*Tim 10 c# amazon-web-services aws-lambda aws-api-gateway

我有一个简单的C#Aws Lambda函数,它成功通过Lambda控制台测试进行测试,但如果从API网关(我从Lambda触发器选项生成)调用了502(Bad Gateway)失败,并且如果我使用postman. (此初始功能具有开放访问权限(无安全性))

// request header
    Content-Type: application/json

//  request body
    {
        "userid":22,
        "files":["File1","File2","File3","File4"]
    }
Run Code Online (Sandbox Code Playgroud)

我在日志中得到的错误是:

Wed Feb 08 14:14:54 UTC 2017 : Endpoint response body before transformations: {
  "errorType": "NullReferenceException",
  "errorMessage": "Object reference not set to an instance of an object.",
  "stackTrace": [
    "at blahblahmynamespace.Function.FunctionHandler(ZipRequest input, ILambdaContext context)",
    "at lambda_method(Closure , Stream , Stream , ContextInfo )"
  ]
}
Run Code Online (Sandbox Code Playgroud)

似乎发布的对象没有传递给lambda输入参数.

代码如下

// Lambda function
     public LambdaResponse FunctionHandler(ZipRequest input, ILambdaContext context)
        {
            try
            {
                var logger = context.Logger;
                var headers = new Dictionary<string, string>();

                if (input == null || input.files.Count == 0)
                {
                    logger.LogLine($"input was null");
                    headers.Add("testheader", "ohdear");
                    return new LambdaResponse { body = "fail", headers = headers, statusCode = HttpStatusCode.BadRequest };
                }
                else
                {
                    logger.LogLine($"recieved request from user{input?.userid}");
                    logger.LogLine($"recieved {input?.files?.Count} items to zip");
                    headers.Add("testheader", "yeah");
                    return new LambdaResponse { body = "hurrah", headers = headers, statusCode = HttpStatusCode.OK };
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
Run Code Online (Sandbox Code Playgroud)

// Lambda响应/ ZipRequest类

public class LambdaResponse
{

    public HttpStatusCode statusCode { get; set; }
    public Dictionary<string, string> headers { get; set; }
    public string body { get; set; }
}
public class ZipRequest
{
    public int userid { get; set; }
    public IList<string> files { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

Sou*_*eAK 18

当OP提出问题时,这可能不可用,但是当使用API​​网关调用Lambda函数时,会提供特定的响应对象.

正如之前在文档Api Gateway Simple Proxy for Lambda输入格式中所述,API网关将输入参数包装在一个相当详细的包装器中.它还期望一个类似的详细响应对象.

但是,没有必要创建自定义请求和响应对象.AWS团队提供Amazon.Lambda.APIGatewayEvents库,该库也可在NuGet上使用.这个库包括APIGatewayProxyRequestAPIGatewayProxyResponse对象做好准备.

仍然需要手动反序列Body化请求,因为它是字符串,而不是JSON对象.我认为这是为了灵活性吗?

示例函数可能如下所示.它是AWS工具提供的默认功能的修改:

    public APIGatewayProxyResponse FunctionHandler(APIGatewayProxyRequest request, ILambdaContext context)
    {
        var bodyString = request?.Body;

        if (!string.IsNullOrEmpty(bodyString))
        {
            dynamic body = JsonConvert.DeserializeObject(bodyString);

            if (body.input != null)
            {
                body.input = body.input?.ToString().ToUpper();

                return new APIGatewayProxyResponse
                {
                    StatusCode = 200,
                    Body = JsonConvert.SerializeObject(body)
                };
            }
        }

        return new APIGatewayProxyResponse
        {
            StatusCode = 200
        };
    }
Run Code Online (Sandbox Code Playgroud)


小智 7

在API网关中使用Lambda代理集成时,您的第一个参数FunctionHandler不是POST的主体,而是另一个API网关创建的对象,可以调用它LambdaRequest.尝试对示例代码进行这些更改.加:

public class LambdaRequest
{
   public string body { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

将处理程序原型更改为:

public LambdaResponse FunctionHandler(LambdaRequest req, ILambdaContext context)
Run Code Online (Sandbox Code Playgroud)

内部FunctionHandler添加:

ZipRequest input = JsonConvert.DeserializeObject<ZipRequest>(req.Body);
Run Code Online (Sandbox Code Playgroud)

完整的LambdaRequest对象记录在AWS文档中用于代理集成的Lambda函数的输入格式下,并包含HTTP标头,HTTP方法,查询字符串,正文和其他一些内容.