GOとAzure関数を使用してServerlessアプリをビルドする


WebhookバックエンドはFAAS(機能- AS - A)プラットフォームのための人気のユースケースです.彼らは面白いGIFで応答する顧客通知を送信するなど、多くのユースケースに使用することができます!Serverless関数を使用すると、Webhook機能をカプセル化し、HTTPエンドポイントの形でそれを公開するのは非常に便利です.このチュートリアルではSlack app 無記名バックエンドとしてAzure Functions and Go . あなたはスラックプラットフォームを拡張し、スラックで強力な経験を構築できるようにプラットフォームの完全なスコープにアクセスできるカスタムアプリケーションやワークフローを実装することによってサービスを統合することができます.
これは、シンプルなバージョンのGiphy for Slack . 元のGIFスラックアプリケーションは、検索要求に応答して複数のGIFに応答して動作します.単純さのために、このポストで実証されたファンクションアプリケーションはGiphy Random API . この投稿は、アプリケーションを配備するためのステップバイステップガイドを提供しますAzure Functions そして、あなたのスラックのワークスペースと統合します.

この投稿では、
  • 概要Custom Handlers in Azure Functions
  • 理解してどのようなシーンの背後にある簡単なコードを歩く
  • 方法Azure関数とスラックを使用してセットアップを解決する方法を学ぶ
  • そしてもちろん、ワークスペースであなたのスラックアプリを実行する!
  • バックエンド関数ロジックはgoavailable on GitHub . Azure関数で動作している人は、Goがデフォルトでサポートされている言語ハンドラの一つではないことを思い出すかもしれません.それでCustom Handlers 救助に来る!

    カスタムハンドラとは


    一言で言えば、カスタムハンドラは、関数ホストからイベントを受け取る軽量Webサーバーです.お好みのランタイム/言語でカスタムハンドラを実装する必要がある唯一のことは:HTTPサポート!これはカスタムハンドラがHTTP triggers のみ-あなたは無料で使用するother triggers along with input and output bindings 拡張子のバンドル.
    ここでは、カスタムハンドラが高レベルで動作する方法の概要を示します

    イベントトリガー(HTTP、ストレージ、イベントハブなど)は、関数ホストを呼び出します.カスタムハンドラが伝統的な関数と異なる方法は、関数ホストが中身として機能することです.これは、カスタムハンドラーのWebサーバーへの要求ペイロードを発行します.この関数は、応答のデータを処理のための関数の出力バインディングに渡す関数ホストに応答を返します.

    概要


    我々が他の地域に飛び込む前に、コードを調査することによって亜高潔さを理解するのを助けるかもしれません

    アプリケーション構造


    アプリの設定方法を見てみましょう.これはDOC
    .
    ├── cmd
    │   └── main.go
    ├── funcy
    │   └── function.json
    ├── go.mod
    ├── host.json
    └── pkg
        └── function
            ├── function.go
            ├── giphy.go
            └── slack.go
    
  • The function.json ファイルは、名前が関数名を使用するフォルダにありますthis is by convention )
  • {
        "bindings": [
            {
                "type": "httpTrigger",
                "direction": "in",
                "name": "req",
                "methods": [
                    "get",
                    "post"
                ]
            },
            {
                "type": "http",
                "direction": "out",
                "name": "res"
            }
        ]
    }
    
  • host.json HTTPホストを処理することができるWebサーバを指してリクエストを送信する関数ホストに指示します.注意customHandler.description.defaultExecutablePathgo_funcy Webサーバを実行するために使用する実行可能ファイルの名前です."enableForwardingHttpRequest": true 生のHTTPデータがどんな変更なしでカスタムハンドラに送られるのを確実にします
  • {
        "version": "2.0",
        "extensionBundle": {
            "id": "Microsoft.Azure.Functions.ExtensionBundle",
            "version": "[1.*, 2.0.0)"
        },
        "customHandler": {
            "description": {
                "defaultExecutablePath": "go_funcy"
            },
            "enableForwardingHttpRequest": true
        },
        "logging": {
            "logLevel": {
                "default": "Trace"
            }
        }
    }
    
  • The cmd and pkg ディレクトリにGOソースコードが含まれます.次のサブセクションでこれを調べましょう
  • コードウォークスルー

    cmd/main.go HTTPサーバーを設定して起動します.注意/api/funcy エンドポイントは、機能ホストがカスタムハンドラーHTTPサーバーに要求を送信するものです.
    func main() {
        port, exists := os.LookupEnv("FUNCTIONS_CUSTOMHANDLER_PORT")
        if !exists {
            port = "8080"
        }
        http.HandleFunc("/api/funcy", function.Funcy)
        log.Fatal(http.ListenAndServe(":"+port, nil))
    }
    
    すべての重い持ち上げが行われますfunction/function.go .
    最初の部分はリクエスト本文を読んで、this recipe defined by Slack .
        signingSecret := os.Getenv("SLACK_SIGNING_SECRET")
        apiKey := os.Getenv("GIPHY_API_KEY")
    
        if signingSecret == "" || apiKey == "" {
            http.Error(w, "Failed to process request. Please contact the admin", http.StatusUnauthorized)
            return
        }
    
        slackTimestamp := r.Header.Get("X-Slack-Request-Timestamp")
    
        b, err := ioutil.ReadAll(r.Body)
        if err != nil {
            http.Error(w, "Failed to process request", http.StatusBadRequest)
            return
        }
        slackSigningBaseString := "v0:" + slackTimestamp + ":" + string(b)
        slackSignature := r.Header.Get("X-Slack-Signature")
    
        if !matchSignature(slackSignature, signingSecret, slackSigningBaseString) {
            http.Error(w, "Function was not invoked by Slack", http.StatusForbidden)
            return
        }
    
    関数が実際にスラックを介して呼び出されたことを確認したら、次の部分は(スラック)ユーザが入力した検索語を抽出することです
        vals, err := parse(b)
        if err != nil {
            http.Error(w, "Failed to process request", http.StatusBadRequest)
            return
        }
        giphyTag := vals.Get("text")
    
    GIFS REST APIを起動することによって検索用語でGIFを調べてください
        giphyResp, err := http.Get("http://api.giphy.com/v1/gifs/random?tag=" + giphyTag + "&api_key=" + apiKey)
        if err != nil {
            http.Error(w, "Failed to process request", http.StatusFailedDependency)
            return
        }
    
        resp, err := ioutil.ReadAll(giphyResp.Body)
        if err != nil {
            http.Error(w, "Failed to process request", http.StatusInternalServerError)
            return
        }
    
    応答はGPIA APIによって返されます.それだ!
        var gr GiphyResponse
        json.Unmarshal(resp, &gr)
        title := gr.Data.Title
        url := gr.Data.Images.Downsized.URL
    
        slackResponse := SlackResponse{Text: slackResponseStaticText, Attachments: []Attachment{{Text: title, ImageURL: url}}}
    
        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(slackResponse)
        fmt.Println("Sent response to Slack")
    

    Check the matchSignature function if you're interested in checking the signature validation process and look at slack.go, giphy.go (in the function directory) to see the Go structs used represent information (JSON) being exchanged between various components. These have not been included here to keep this post concise.


    ああ!これまで、我々は理論と背景情報の多くをカバーしている.物事を成し遂げる時だ!あなたが進む前に、あなたが下記の前提条件の注意をすることを確認してください.

    事前の要件


  • Download and install Go あなたがそれを持っていないならば
  • インストールAzure functions Core Tools - これにより、CLIを使用して関数を展開することができます(また、テストを実行し、ローカルでデバッグします).

  • Create a Slack workspace あなたが1を持たないならば.
  • ギフィーAPIキーを取得- GHYPYアカウントを作成する必要がありますand create an app . 作成する各アプリケーションには独自のAPIキーがあります.
  • Please note down your GIPHY API key as you will be using it later



    今後のセクションでは、azure関数を展開し、スラッシュコマンドのスラックを設定するプロセスをご案内します.

    Azure関数設定


    を作成するResource Group ソリューションのすべてのコンポーネントをホストするには.

    機能アプリの作成


    Azureポータル内の関数アプリを検索して起動する

    必要な詳細を入力します.ランタイムスタックとしてカスタムハンドラを選択する必要があります

    ホスティングセクションでは、オペレーティングシステムとプランタイプのそれぞれのLinuxと消費を選択します.

    アプリケーションの洞察を有効にする

    最終設定を確認し、「Create」をクリックします

    プロセスが完了すると、次のリソースも機能アプリケーションと一緒に作成されます.

  • App Service plan (この場合の消費者/無担保計画)
  • Azure Storage account
  • Azure Application Insights 機能)
  • 関数の配備


    Githubレポをクローンし、機能を構築する
    git clone https://github.com/abhirockzz/serverless-go-slack-app
    cd serverless-go-slack-app
    
    GOOS=linux go build -o go_funcy cmd/main.go
    

    GOOS=linux is used to build a Linux executable since we chose a Linux OS for our Function App


    展開するには、Azure関数のコアツールCLI
    func azure functionapp publish <enter name of the function app>
    
    展開したら、コマンドによって返される関数URLをコピーします

    スラックの設定


    このセクションでは、ワークスペースでスラックアプリケーション(スラッシュコマンド)を設定するために実行する必要があります.
  • スラックアプリの作成
  • スラッシュコマンドを作成する
  • あなたのワークスペースにアプリケーションをインストールします
  • スラックアプリケーションを作成し、スラッシュコマンド


    あなたのサインSlack Workspace で始まるcreating a new Slack App

    をクリックして新しいコマンドを使用して新しいスラッシュコマンドを必要な情報を定義します.リクエストURLフィールドは、前のセクションで関数を展開した後に得たURL以外の関数のHTTPエンドポイントを入力する場所です.完了したら、完了するには、ヒットを保存します.

    あなたのワークスペースにアプリケーションをインストールします


    したら、スラッシュのコマンドを作成し、あなたのアプリケーションの設定ページに頭をクリックして、ナビゲーションメニューの基本的な情報機能をクリックして、ワークスペースにアプリケーションをインストールし、ワークスペースにインストールアプリケーションをクリックしてください-これはあなたのアプリをテストし、スラックAPIと対話するために必要なトークンを生成するあなたのスラックのワークスペースにアプリケーションをインストールします.アプリをインストールし終えるとすぐに、アプリの資格情報は、同じページに表示されます.

    Make a note of your app Signing Secret as you'll be using it later



    楽しい部分に移動する前に.


    ... スラック署名秘密を追加するには、アプリケーションの設定を更新してくださいSLACK_SIGNING_SECRET ) とGIAPI APIキーGIPHY_API_KEY ) - 関数の内部環境変数として利用できます.

    楽しい(cy)時間!


    あなたのスラックのワークスペースから/funcy <search term> . 例えば/funcy dog .
    あなたが戻って戻ってランダムなGIFを取得する必要があります!

    ちょうど何が起こっているかの要約:あなたが/funcy スラックでコマンドを実行し、関数を呼び出します.この関数はGIF APIを相互作用し、最終的にGIFをユーザに返します(すべてがうまくいくなら).
    あなたはtimeout error 最初の呼び出しの後のスラックから.これはおそらくcold start 関数を起動する際に起動するには数秒かかる.これは事実と組み合わされているSlack expects a response in 3 seconds - したがって、エラーメッセージ.
    心配することはない.すべての必要な再試行し、物事は素晴らしいはずです!

    Clean up: Once you're done, don't forget to delete the resource group which in turn will delete all the resources created before (Function app, App Service Plan etc.)


    何もAzureであなたのServerlessな機能のためにGOを使用してから停止することはありません!私はこれがカスタムハンドラを試して楽しい方法であることを願っています.あなたが何を考えて知ってみよう!