準備(詳しくないので雑に書く)
-
https://engr-tie.net/posts/lambda-net6/prepare/
- .NET6.0 SDK -> https://dotnet.microsoft.com/download
dotnet new -i Amazon.Lambda.Templatesdotnet tool install -g Amazon.Lambda.Tools- AWS CLI -> https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html
- AWS CDK -> https://aws.amazon.com/cdk/
途中は略
なんかいい感じにcdkとlambdaを実装してください
要点(この記事の肝)
Lambda(C#)部分のビルドについて
パスは適当に読み替えてください。
概要としては dotnet lambda package でzipファイルの生成です
build.bash
# cdkのルートディレクトリにいるものとして
# .csprojファイルのあるディレクトリへ移動
pushd path/to/CSName/src/Project
# このコマンドでビルドされて
# path/to/CSName/src/Project/bin/Release/net6.0 フォルダへ
# zip ファイルが生成される
dotnet lambda package
# ルートディレクトリに戻る
popd
# さっきビルドされたファイルを適当な場所に置く。どこでもいい
cp path/to/CSName/src/Project/bin/Release/net6.0/CSName.zip ./cache/CSName.zip
CDK(JavaScript側の指定について)
パスは適当に読み替えてください。
概要としては dotnet lambda package で生成されたzipファイルを Code.fromAsset で指定することです
cdk.js
const path = require("path")
const { aws_lambda, CfnOutput } = require('aws-cdk-lib');
const fn_cs = new Function (this,"cs",{
runtime: aws_lambda.Runtime.DOTNET_6, // C#だし
// さっき cp で配置した場所(よく考えたらcpでコピーする必要ないかもなぁ……)
code: aws_lambda.Code.fromAsset(path.join(__dirname, '../cache/CSName.zip')),
// https://docs.aws.amazon.com/lambda/latest/dg/csharp-handler.html#csharp-handler-signatures
// `ASSEMBLY::TYPE::METHOD` この形式。
handler: "CSName::Project.Function::FunctionHandler",
// 残りの指定は適当にどうぞ
})
// AWS Lambda Function URLs やりたい人は適当に設定してください
const furl = fn_cs.addFunctionUrl({
authType: FunctionUrlAuthType.NONE,
})
// 設定されたURLを出力するため
new CfnOutput(this,"CSUrl",{
value: furl.url,
});
Lambda(C#)部分の実装について
公式ドキュメントは https://docs.aws.amazon.com/lambda/latest/dg/lambda-csharp.html ですが、ぶっちゃけよく分かりませんでした。
要点としては
- Handlerで指定された関数が呼ばれる
- AWS LambdaにJSONが渡されれば、それは
LambdaSerializerが良い感じにデシリアライズして関数の第1引数に設定してくれる - 関数の戻り値は
LambdaSerializerが良い感じにシリアライズしてくれる - AWS Lambda Function URLs でやる場合、POSTされた入力は、入力JSONの $.Body へ文字列として埋め込まれる
みたいなところです。
Function.cs
using Amazon.Lambda.Core;
using System.Text.Json;
// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace Project;
public class MyInput{
public string Test {get;set;} = "";
}
public class MyOutput{
public string Result {get;set;} = "";
}
public class MyLambdaFunctionInput{
public string Body {get;set;} = "";
}
public class Function
{
///
/// JSONとして単一の文字列が渡される場合のシグネチャ(引数と戻り値の型)
/// "Hello, world!" みたいな単一文字列が直接Lambdaへ渡される場合
/// そして単一の文字列が戻り値となる
///
public string StringHandler(string input, ILambdaContext context)
{
return input.ToUpper()
}
///
/// 良い感じのJSONが渡される場合のシグネチャ
/// { "Test": "Hello" } みたいな JSON が直接Lambdaへ渡される場合
/// そして戻り値の型が良い感じに JSON になったものが戻り値となる
///
public MyOutput FunctionHandler(MyInput input, ILambdaContext context)
{
return new MyOutput{
Result = input.Test.ToUpper(),
};
}
///
/// よく分からんけど何か入力のシリアライズとかを自前でやる場合
/// よくわからん
///
public Stream StreamHandler(Stream input){
return input;
}
///
/// AWS Lambda Function URLsで受ける場合の例
/// AWS Lambda Function URLsで呼ばれた場合
/// 入力JSONの $.Body として入力内容が文字列として入り込むのでまずBodyをstringとして読む
/// そのあと JSON にする
/// この例では
/// curl https://anywhere.lambda-url.ap-where.on.aws/ -X POST -H "Content-Type: application/json" -d '{"Test":"Hello"}'
/// みたいな入力を想定している
///
public MyOutput LURLHandler(MyLambdaFunctionInput input, ILambdaContext context){
MyInput? myInput =
JsonSerializer.Deserialize<MyInput>(input.Body);
return new MyOutput{
Result = input.Body.ToUpper(),
};
}
}
以上。