lambda function URLsのeventをプロキシしてhttp apiに流す

小規模なSlack BotはAWS lambda functions URLsに作ると楽だった の話の続きです. 先日lambda function URLsを利用してhttp apiのような実装を記述する方法を紹介しました. 今回は httpadapter と net/http/httputil を利用してlambda function URLsをリバースプロキシとして動かしてbackend apiに流す方法です. 概略図 実装 普通のリバースプロキシを実装するときはhttputil.ReverseProxyを定義してserverを作って待ち受けるわけですが、 今回の場合はhttputil.ReverseProxyを定義した後httpadapter.NewV2に食わせるだけですね. 次の例はlambdaのeventを受け取ったあとlocalで8080ポートで待ち受けるhttp serverにリクエストを流すproxyの例です. func main() { director := func(req *http.Request) { req.URL.Scheme = "http" req.URL.Host = ":8080" } rp := &httputil.ReverseProxy{Director: director} lambda.Start(httpadapter.NewV2(rp).ProxyWithContext) } すべてlambda関数上で完結させたい場合は func init() などでapiを予め立ち上げた後プロキシしてあげると良いと思います. github.com/ieee0824/le2hp ではそのような実装にしました.

2月 2, 2023

小規模なSlack BotはAWS lambda functions URLsに作ると楽だった

はじめに ここで言う小規模なSlack Botというのは個人で使うようなBotやチームレベルで使う書き捨てレベルのようなもののことです. このような想定のBotを実装するときそこまでちゃんとインフラコストをかけたくありません. 自前でサーバーを用意したとして処理内容と維持管理費用が割に合わないのです. 無料でhttp serverを立ち上げることができるけど定期的にリクエストを送っておかなければプロセスがkillされるようなサービスもあります. そのようなサービスを使う場合定期的にリクエストを送るか立ち上がるまで待った後Botのためのリクエストを送らないと機能しない問題があります. それらの問題を解消するのにlambda functions URLsは要件にあってそうだなぁと思いました. lambda function URLsはlambdaなので課金が発生する時間単位が短いのでたまにしか実行されないようなものでもサーバーを立てて実現するよりお金がかからないです. またlambda function URLsにリクエストを投げるとlambdaのeventが発火して即時にlambda関数が実行されるので待ち時間も発生しません. 一つ問題があるとしたらlambdaのeventとして作成したプログラムから見えるので普段Botをhttpのapiとして実装している場合はhttp requestとlambdaのeventとのギャップを埋める必要があるということです. とはいえそこまで大きな問題にはならないと思います. 特にGo言語の場合は github.com/awslabs/aws-lambda-go-api-proxy/httpadapter を利用するとほとんどhttp serverと同じような実装でアプリケーションを作ることができます. Goでlambda function URLsを使ってリクエスト受ける例 github.com/awslabs/aws-lambda-go-api-proxy/httpadapter を利用した実装例を上げておきます. frameworkを利用しない例 frameworkを利用しない例です. 生のGo言語でhttp serverを実装したことがある人なら雰囲気が解ると思います. package main import ( "io" "net/http" "github.com/aws/aws-lambda-go/lambda" "github.com/awslabs/aws-lambda-go-api-proxy/httpadapter" ) func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { io.WriteString(w, "It Works!") }) // lambda function URLsはapi gateway v2と同じeventなのでv2にする必要がある lambda.Start(httpadapter.NewV2(http.DefaultServeMux).ProxyWithContext) } Ginを利用した例 frameworkを利用することもできます. 例えばGinを利用する場合は次のように記述ができます. package main import ( "context" "net/http" "github....

1月 31, 2023

3月29日のGo言語のtime.Time#AddDateの挙動について

3月29日と書いて有るが前の月よりも長いときで且つ前の月にない日付のときに AddDate で -1ヶ月するときの挙動についてである. -1ヶ月してないときは月初に丸められるっぽい. package main import ( "fmt" "time" ) func main() { fmt.Println(time.Date(2022, 3, 1, 0, 0, 0, 0, time.UTC).AddDate(0, -1, 0)) // 2022-02-01 00:00:00 +0000 UTC fmt.Println(time.Date(2022, 3, 29, 0, 0, 0, 0, time.UTC).AddDate(0, -1, 0)) // 2022-03-01 00:00:00 +0000 UTC fmt.Println(time.Date(2022, 12, 31, 0, 0, 0, 0, time.UTC).AddDate(0, -1, 0)) // 2022-12-01 00:00:00 +0000 UTC }

3月 29, 2022

gocv+v4l2を利用して任意の画像をwebcamとして流す

リモートワークとかするときにzoomとかslackとかGoogle Meetとかでビデオ会議をするんですけど任意の画像をカメラ画像として差し込めると楽しいと思わないですか? LinuxだとCanonとかの一眼レフとかをWebカメラとして認識させるのにv4l2を利用してやる方法が有るんですけど, v4l2を利用することで任意の画像をWebカメラの画像として配信することができます. ざっくり言うと 標準出力に1フレームの情報としてjpegを吐き出す ffmpegでv4l2の仮想デバイスに吐き出す 簡単ですね. sample.jpegというダミー画像を出力することを考えましょう. まずはじめに仮想カメラを生成します. # /dev/video20 として仮想カメラを作る $ sudo modprobe v4l2loopback card_label="dummy_cam" video_nr=20 exclusive_caps=1 次にGoのプログラムを書く. とりあえず main.go とかで用意する. package main import ( "bytes" "image" "image/color" "image/jpeg" "os" ) func main() { of, err := os.Open("sample.jpeg") if err != nil { panic(err) } jpg, err := jpeg.Decode(of) if err != nil { panic(err) } b := jpg.Bounds() // jpegをYUV420pに変換する converted := image.NewYCbCr(b, image....

12月 2, 2020

電話番号の判定やりたくて

電話番号の判定をやりたくてつくり始めた. 一応ルールがあるらしい. 細かい解説はqiitaに存在していたので割愛する. とりあえず作り始めたやつはこれ(tel-num-parser). 使い方 参考実装です. 電話番号であるかどうかと種別が取得できます. package main import ( "fmt" tnp "github.com/ieee0824/go-tel-num-parser-jp" ) var telList = map[string]string{ "東京都庁": "03-5321-1111", "東京都庁2": "03(5321)1111", "東京都庁3": "0353211111", "国土交通省": "03-5253-4150", } func main() { for k, v := range telList { fmt.Print(k + ": ") fmt.Println(tnp.IsTelNumber(v)) } }

11月 8, 2018