シンプルなC#Aws Lambda関数があり、これはLambdaコンソールテストからのテストに成功しますが、API Gateway(Lambdaトリガーオプションから生成したもの)から呼び出された場合、およびpostmanを使用した場合に502(不良ゲートウェイ)で失敗します。 (この初期関数にはオープンアクセスがあります(セキュリティなし))
// 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 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;
}
}
//ラムダ応答/ 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; }
}
API GatewayでLambdaプロキシ統合を使用する場合、FunctionHandler
の最初のパラメーターはPOSTの本文ではなく、LambdaRequest
を呼び出す別のAPI Gateway作成オブジェクトです。これらの変更をサンプルコードに試してください。追加:
public class LambdaRequest
{
public string body { get; set; }
}
ハンドラプロトタイプを次のように変更します。
public LambdaResponse FunctionHandler(LambdaRequest req, ILambdaContext context)
そしてFunctionHandler
の中に追加:
ZipRequest input = JsonConvert.DeserializeObject<ZipRequest>(req.Body);
完全なLambdaRequestオブジェクトは、AWSドキュメントの プロキシ統合用のLambda関数の入力形式 に記載されており、HTTPヘッダー、HTTPメソッド、クエリ文字列、本文、およびその他いくつかのものが含まれています。
これは、OPが質問したときに利用できなかった可能性がありますが、API Gatewayを使用してLambda関数を呼び出すと、特定の応答オブジェクトが提供されます。
前述のドキュメント ラムダ入力形式のAPIゲートウェイシンプルプロキシ で述べたように、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
};
}
また、Getメソッドで渡された「パスパラメータ」を取得しようとすると、多くの時間を失いました。たとえば、次のようなパスがある場合
/ appsetting/123
...その後、次のように構成されます
リソース「appid」を{appid}として指定することにより、APIゲートウェイにこれをパス変数としてキャプチャするように指示します。
私が見つけた重要な発見の1つは、POSTタイプのアクションの本文に投稿することで、Lambdaが機能することです。他のいくつかのスレッドを読んで、パス変数をGETアクションの本体:
テストすると、appid値のみをプラグインして適切な結果を得ることができます。これが誰かを助けることを願っています。