2017-02-08 12 views
5

Mam prostą funkcję C# Aws Lambda, która udaje się do testu z testu konsoli Lambda, ale kończy się niepowodzeniem z 502 (Bad Gateway), jeśli jest wywoływana z bramki API (która została wygenerowana z . lambda opcja wyzwalania), a także, jeśli używam listonosza (ta początkowa funkcja ma otwarty dostęp (bez zabezpieczeń))Wysyłanie z bramy AWS-API do Lambda

// request header 
    Content-Type: application/json 

// request body 
    { 
     "userid":22, 
     "files":["File1","File2","File3","File4"] 
    } 

błąd pojawia się w dziennikach jest:

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

wydaje się, że wysłany obiekt nie jest przekazywany do argumentu wejściowego lambda.

kod poniżej

// 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; 
      } 
     } 

// reakcja Lambda/klasa 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; } 
} 

Odpowiedz

3

Podczas korzystania Lambda Integracja Proxy API Gateway, pierwszy parametr do FunctionHandler nie jest ciałem postu, ale jest to inny obiekt utworzony za pomocą API API, który nazwijmy: LambdaRequest. Wypróbuj te zmiany w kodzie przykładowym. Dodaj:

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

Zmień swój prototyp uchwytu do:

public LambdaResponse FunctionHandler(LambdaRequest req, ILambdaContext context) 

A wewnątrz FunctionHandler dodają:

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

Pełne LambdaRequest obiekt jest udokumentowany pod Input Format of a Lambda Function for Proxy Integration w docs AWS i zawiera HTTP nagłówki, metodę HTTP, ciąg zapytania, treść i kilka innych rzeczy.

5

To mogło nie być dostępne, gdy PO zadał pytanie, ale podczas wywoływania funkcji Lambda za pomocą bramy API udostępniono określone obiekty odpowiedzi.

Jak wcześniej wspomniano w dokumentacji Api Gateway Simple Proxy for Lambda Input Format, bramka API zawija argumenty wejściowe w dość obszernym opakowaniu. Oczekuje również podobnie obszernego obiektu odpowiedzi.

Nie jest jednak konieczne tworzenie niestandardowych obiektów żądań i odpowiedzi. Zespół AWS udostępnia bibliotekę Amazon.Lambda.APIGatewayEvents, która jest również dostępna w NuGet. Ta biblioteka zawiera gotowe obiekty o numerach APIGatewayProxyRequest i APIGatewayProxyResponse.

Konieczne jest ręczne przekształcenie z postaci szeregowej Body żądania, ponieważ jest to ciąg znaków, a nie obiekt JSON. Zakładam, że zrobiono to dla elastyczności?

Przykładowa funkcja może wyglądać tak. Jest to modyfikacja domyślnej funkcji zapewnianej przez narzędzia 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 
     }; 
    } 
Powiązane problemy