Wiring from AWS-API Gateway to Lambda

I have a simple C # Aws Lambda function that successfully passes the test from the Lambda console test, but does not work with 502 (Bad Gateway) if called from the API gateway (which I created from the Lambda trigger option), and also if I use postman . (this initial function has open access (without security))

// request header Content-Type: application/json // request body { "userid":22, "files":["File1","File2","File3","File4"] } 

The error I get in the logs is:

 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 )" ] } 

It seems that the published object is not being passed to the lambda input argument.

Code below

 // 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 response / ZipRequest class

 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; } } 
+9
source share
3 answers

When using the Lambda Proxy integration in the Gateway API, the first parameter for your FunctionHandler is not the body of your POST, but another object created by the API gateway that allows you to call LambdaRequest . Try these changes in your sample code. Add:

 public class LambdaRequest { public string body { get; set; } } 

Change your prototype handler to:

 public LambdaResponse FunctionHandler(LambdaRequest req, ILambdaContext context) 

And inside the FunctionHandler add:

 ZipRequest input = JsonConvert.DeserializeObject<ZipRequest>(req.Body); 

The full LambdaRequest object is described in the section " Input format for lambda functions for proxy integration" in AWS documents and contains HTTP headers, HTTP method, request string, body and some other things.

+6
source

It may not have been available when the OP asked the question, but when calling the Lambda function using the API gateway, specific response objects are provided.

As noted in the Api Gateway Simple Proxy documentation for the Lambda input format , the API gateway wraps the input arguments in a fairly detailed wrapper. It also expects a similar verbose response object.

However, there is no need to create custom request and response objects. The AWS team provides the Amazon.Lambda.APIGatewayEvents library, which is also available on NuGet. This library includes APIGatewayProxyRequest and APIGatewayProxyResponse objects ready.

It is still necessary to manually deserialize the request Body , as this is a string, not a JSON object. I assume this was done for flexibility?

An example function might look like this. This is a modification to the default function provided by 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 }; } 
+17
source

I also lost a lot of time trying to pass the "path parameter" to the Get method. For example, if you had a path such as

/ Appsetting / 123

... then you would configure something like

enter image description here

By specifying the "appid" resource as {appid}, it tells the API gateway to capture it as a path variable.

One of the key discoveries that I discovered was that when I publish actions like POST in the body, my Lambda will work. Reading about some other threads, I found that I can convert the path variable to the GET action body:

  1. Select GET value (as shown)
  2. By clicking integration request
  3. Create a display template as shown below

enter image description here

Now, when I test, I can only connect my appid value and get the correct result. Hope this helps someone.

0
source

Source: https://habr.com/ru/post/1263970/


All Articles