我有一个简单的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"]
}
我在日志中遇到的错误是:
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 )"
]
}
似乎没有将发布的对象传递给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;
}
}
// 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; }
}
答案 0 :(得分:17)
当OP提出问题时,这可能不可用,但是当使用API网关调用Lambda函数时,会提供特定的响应对象。
如前文档Api Gateway Simple Proxy for Lambda Input Format中所述,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
};
}
答案 1 :(得分:6)
在API网关中使用Lambda代理集成时,FunctionHandler
的第一个参数不是POST的主体,而是另一个API网关创建的对象,它可以调用{{1} }。尝试对示例代码进行这些更改。添加:
LambdaRequest
将处理程序原型更改为:
public class LambdaRequest
{
public string body { get; set; }
}
在public LambdaResponse FunctionHandler(LambdaRequest req, ILambdaContext context)
内添加:
FunctionHandler
完整的LambdaRequest对象记录在AWS文档中的Input Format of a Lambda Function for Proxy Integration下,包含HTTP标头,HTTP方法,查询字符串,正文和其他一些内容。
答案 2 :(得分:0)