Azure Functions カスタム ハンドラー + Golang で Event Grid トリガーを試してみる
Azure Functions custom handler in Go に EventGridTrigger がなかったので試してみました。
カスタム ハンドラーの説明、その他のサンプルは以下にありますので、設定とコードのみざっくりと。
- Azure Functions のカスタム ハンドラー
- GitHub - Azure-Samples/functions-custom-handlers: Sample code for Azure Functions custom handlers
Event Grid トリガーでQueue Storage 出力の function.json です。
function.json
{ "bindings":[ { "type":"eventGridTrigger", "name":"eventGridEvent", "direction":"in" }, { "name": "$return", "type": "queue", "direction": "out", "queueName": "test-output-node", "connection": "AzureWebJobsStorage" } ] }
Name | Trigger | Input | Output |
---|---|---|---|
eventGridTrigger | Event Grid | Event Grid | Queue Storage |
イベントを受信する部分は、GoCustomHandlers.goとちょっと変えて、ginを使ってみます。
main.go
package main import ( "encoding/json" "fmt" "github.com/gin-gonic/gin" "log" "net/http" "os" ) func main() { customHandlerPort, exists := os.LookupEnv("FUNCTIONS_CUSTOMHANDLER_PORT") if !exists { customHandlerPort = "7071" } fmt.Println("FUNCTIONS_CUSTOMHANDLER_PORT: " + customHandlerPort) r := gin.Default() r.GET("/", home) r.POST("/EventGridTrigger", eventGridTriggerHandler) r.Run(":" + customHandlerPort) } func home(ctx *gin.Context) { ctx.JSON(http.StatusOK, nil) } func eventGridTriggerHandler(ctx *gin.Context) { var req EventMessage if err := ctx.ShouldBindJSON(&req); err != nil { log.Fatalf(err.Error()) return } var me EventGridData if val1, ok := req.Data["eventGridEvent"]; ok { jsonb, err := json.Marshal(val1) if err != nil { log.Fatalf(err.Error()) return } if err := json.Unmarshal(jsonb, &me); err != nil { log.Fatalf(err.Error()) return } } returnValue := HTTPResponse {} returnValue.Outputs.Res.Body = "OK" returnValue.Outputs.Res.StatusCode = "200" returnValue.ReturnValue = me.Data ctx.JSON(http.StatusOK, returnValue) } type HTTPResponse struct { Outputs struct { Res struct { Body string `json:"body"` StatusCode string `json:"statusCode"` } `json:"res"` } Logs []string ReturnValue interface{} } type EventMessage struct { Data map[string]interface{} Metadata map[string]interface{} } type EventGridData struct { Id string `json:"id"` Topic string `json:"topic"` Subject string `json:"subject"` Data struct { UserId int64 `json:"userId"` Name string `json:"name"` } `json:"data"` EventType string `json:"eventType"` EventTime string `json:"eventTime"` MetadataVersion string `json:"metadataVersion"` DataVersion string `json:"dataVersion"` }
あとは、Azure上に必要なリソース作成してデプロイ。適当なカスタムトピック(Azure Event Grid イベント スキーマ)を送信して動作しましたので、お試しは完了です。
func SendTopic(url string) error { key1 := "****" msg := [1]Topic{} uid, err := uuid.NewRandom() if err != nil { log.Fatalf(err.Error()) } msg[0].Id = uid.String() msg[0].Subject = "app/sample/test1" msg[0].EventType = "inserted" n := time.Now() msg[0].EventTime = n.Format(time.RFC3339) msg[0].Data.UserId = 1 msg[0].Data.Name = "Example" msg[0].DataVersion = "1.0" json, _ := json.Marshal(msg) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(json)) req.Header.Set("aeg-sas-key", key1) client := new(http.Client) resp, err := client.Do(req) if err != nil { return err } defer func() { if resp.Body != nil { resp.Body.Close() } }() contents, err := ioutil.ReadAll(resp.Body) fmt.Println(string(contents)) fmt.Println(err) if err != nil { return err } return err }