Création d'une application sans serveur à l'aide d'Azure Functions et Go

Dans le cadre du cours «Golang Developer. Professionnel »a préparé la traduction d'un article utile.



Nous invitons les futurs étudiants et toutes les personnes souhaitant participer au webinaire ouvert sur le thème
"Go-channels outside and inside". Dans la leçon, les participants recevront une simple abstraction en images pour comprendre les principes des canaux, en apprendre davantage sur la structure des canaux au niveau de la langue.






Aujourd'hui, nous allons apprendre à intégrer une application Slack en tant que backend sans serveur.

— FaaS ( ) . , , , ! serverless , , HTTP-. , Slack serverless () Go Azure Functions. Slack , , , Slack.





Giphy Slack. Giphy Slack . -, , () , Giphy Random API. Azure Functions Slack.





:





  • (Custom Handlers) Azure Functions;





  • , ;





  • , Azure Functions Slack;





  • , , Slack !





- Go ( GitHub). , Azure Functions , Go , . (Custom Handlers) !





?

, - -, . , /, HTTP! , HTTP- - / (input/output bindings) .





, ( )





( HTTP, , . .) (Functions host). , : (payload) - () , , . , .





, (, , ) .





, .





.
├── cmd
│   └── main.go
├── funcy
│   └── function.json
├── go.mod
├── host.json
└── pkg
    └── function
        ├── function.go
        ├── giphy.go
        └── slack.go
      
      



  • function.json



    , ( )





{
    "bindings": [
        {
            "type": "httpTrigger",
            "direction": "in",
            "name": "req",
            "methods": [
                "get",
                "post"
            ]
        },
        {
            "type": "http",
            "direction": "out",
            "name": "res"
        }
    ]
}
      
      



  • host.json



    , , -, HTTP. customHandler.description.defaultExecutablePath



    , , go_funcy



    — , -. "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"
        }
    }
}
      
      



  • cmd



    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



.





— ( Slack) , 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
	}
      
      







, , Slack, — , (Slack).





vals, err := parse(b)
	if err != nil {
		http.Error(w, "Failed to process request", http.StatusBadRequest)
		return
	}
	giphyTag := vals.Get("text")
      
      



GIF- , GIPHY REST API





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
	}
      
      



, GIPHY API, , Slack . !





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")
      
      







matchSignature



, , slack.go



giphy.go



( function



), , Go (JSON), . , .





! . ! , , .





  • Go, .





  • Azure functions Core Tools — ( ).





  • Slack, .





  • API GIPHY — GIHPY ( !) . API.





- API GIPHY, .





, Azure Function Slack - (Slash command).





Azure Functions

(Resource Group) .





-

- (Function App) Azure (Add).





: (Custom Handler) (Runtime stack).





(Hosting ) Linux Consumption (Serverless) (Operating system) (Plan type) .





Application Insights ( ).





(Create), .





- :





  • App Service plan ( Consumption/Serverless)





  • Azure Storage





  • Azure Application Insights





GitHub (build



)





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



Linux, Linux -.





Azure Functions core tools CLI





func azure functionapp publish <enter name of the function app>
      
      



URL- , — .





Slack

, Slack (-) :





  • Slack 





  • -









Slack -

Slack Slack.





(Create New Command), - . , URL- (Request URL) - , HTTP , , URL-, . , (Save), .





, -, , (Basic Information) , (Install your app to your workspace) (Install App to Workspace) — Slack, , API Slack. , (App Credentials).





- (Signing Secret) ,





… , - SLACKSIGNINGSECRET GIPHYAPIKEY — .





fun(cy) time!

Slack /funcy <search term>



. , /funcy dog



. !













, : /funcy



Slack, , Giphy API , , GIF ( !).





timeout error



Slack . , cold start



, , . , Slack 3 — .





. , , , !





: , , , , , (-, App Service Plan . .).





Go Azure! , . .






«Golang Developer. Professional».





«Go- ».












All Articles