概要 †Azure Functions で Goはサポートされていない。( Azure Functions でサポートされている言語 ) ここでは、Blobにファイルがアップロードされたタイミングで起動する Functions を Goで開発する方法について記載する。 目次 †
カスタムハンドラーの仕組み †カスタムハンドラーは軽量のWebサーバとして動作するもので、Functions Host と Web通信する事により動作する。
ーー リクエスト ーー>
<ーー レスポンス ーー
ーー Webリクエスト ーー>
<ーー Webレスポンス ーー
つまり、Webサーバがかける言語であれば何でも動く。 ファイル構成 †以下の通り構成する。 + host.json 準備 †ローカルでの Azure Storage の開発とテスト用にAzurite エミュレーターをインストールしておく。 インストール&起動 npm install -g azurite azurite --silent --location ./azurite --debug ./azurite/debug.log host.json の作成 †参考 ・defaultExecutablePath で今回 Go で作成するWebサーバの実行可能ファイルのPATHを指定する。 {
"version": "2.0",
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[1.*, 2.0.0)"
},
"httpWorker": {
"description": {
"defaultExecutablePath": "MyGoCustomHandlers.exe"
}
}
}
Azure functions が実行される Functions Host 上に既にランタイムがある場合 †スクリプトのPATH を defaultWorkerPath で指定する。 {
"version": "2.0",
"httpWorker": {
"description": {
"defaultExecutablePath": "node",
"defaultWorkerPath": "server.js"
}
}
}
function.json の作成 †参考: http://json.schemastore.org/function 以下、Blob トリガーにより起動される Functions の例 {
"bindings" : [ {
"type" : "blobTrigger",
"direction" : "in",
"name" : "triggerBlob",
"path" : "test-input-container/{name}",
"dataType" : "binary",
"connection" : "AzureWebJobsStorage"
},
{
"type" : "blob",
"direction" : "out",
"name" : "$return",
"path" : "test-output-container/{name}",
"dataType" : "binary",
"connection" : "AzureWebJobsStorage"
} ]
}
local.settings.json の作成 †{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "YOUR_STORAGE_CONNECTION_STRING"
}
}
ローカルのストレージエミュレータに接続する場合は以下の通り設定する。 :
"AzureWebJobsStorage": "UseDevelopmentStorage=true"
:
処理の作成 †以下、test-input-container にアップロードされたファイルを base64エンコードしたものを test-output-container に出力する例。 package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"os"
)
type ReturnValue struct {
Data string
}
type InvokeResponse struct {
Outputs map[string]interface{}
Logs []string
ReturnValue interface{}
}
type InvokeRequest struct {
Data map[string]interface{}
Metadata map[string]interface{}
}
func blobTriggerHandler(w http.ResponseWriter, r *http.Request) {
var invokeReq InvokeRequest
d := json.NewDecoder(r.Body)
decodeErr := d.Decode(&invokeReq)
if decodeErr != nil {
http.Error(w, decodeErr.Error(), http.StatusBadRequest)
return
}
fmt.Println("The JSON data is:invokeReq metadata......")
fmt.Println(invokeReq.Metadata)
// データはBASE64エンコードされいる
returnValue := invokeReq.Data["triggerBlob"]
invokeResponse := InvokeResponse{Logs: []string{"test log1", "test log2"}, ReturnValue: returnValue}
js, err := json.Marshal(invokeResponse)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.Write(js)
}
func main() {
httpInvokerPort, exists := os.LookupEnv("FUNCTIONS_HTTPWORKER_PORT")
if exists {
fmt.Println("FUNCTIONS_HTTPWORKER_PORT: " + httpInvokerPort)
}
mux := http.NewServeMux()
mux.HandleFunc("/BlobTrigger", blobTriggerHandler)
log.Println("Go server Listening...on httpInvokerPort:", httpInvokerPort)
log.Fatal(http.ListenAndServe(":"+httpInvokerPort, mux))
}
レスポンスとして以下を返却する。
※ https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-custom-handlers#response-payload 動作確認 †カスタムハンドラ起動 †go build func start : : Now listening on: http://0.0.0.0:7071 Application started. Press Ctrl+C to shut down. : テスト用のBlobストレージコンテナの作成 †# ローカルのエミュレータに接続するように環境変数を設定 export AZURE_STORAGE_CONNECTION_STRING="UseDevelopmentStorage=true" # 入出力用のコンテナをそれぞれ作成 az storage container create -n test-input-container az storage container create -n test-out-container コンテナにファイルをアップロード †az storage blob upload -f ./sample.txt -c test-input-container -n sample.txt |