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上使用.这个库包括APIGatewayProxyRequest
和APIGatewayProxyResponse
对象做好准备.
仍然需要手动反序列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方法,查询字符串,正文和其他一些内容.