Here is my golang app listening requests from slack command:
main.go
:
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"time"
)
type SlackCmdResponse struct {
Text string `json:"text"`
}
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
if err := req.ParseForm(); err != nil {
panic(err)
}
responseUrl := req.PostFormValue("response_url")
go func() {
time.Sleep(time.Second)
postBack(responseUrl)
}()
rj, err := json.Marshal(SlackCmdResponse{Text: "Test started"})
if err != nil {
panic(err)
}
w.Header().Set("Content-Type", "application/json")
w.Write(rj)
})
fmt.Println("listening 8383")
if err := http.ListenAndServe(":8383", nil); err != nil {
panic(err)
}
}
func postBack(responseUrl string) {
fmt.Println("responseUrl", responseUrl)
cResp := SlackCmdResponse{
Text: "Test finished",
}
cj, err := json.Marshal(cResp)
if err != nil {
panic(err)
}
req, err := http.NewRequest("POST", responseUrl, bytes.NewReader(cj))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
if resp != nil {
fmt.Println(resp.StatusCode)
if b, err := ioutil.ReadAll(resp.Body); err != nil {
panic(err)
} else {
fmt.Println(string(b))
}
if resp.Body != nil {
resp.Body.Close()
}
}
}
I run it:
$ go run main.go
listening 8383
I use ngrok to make it accessible from the internet:
ngrok http 8383
I created slack slash command /my-command
with POST
option and pasted https URL that ngrok gave:
Now when I run /my-command
in slack, I get slack reply Test started
. And then in a second slack prints Test finished
For now, it's all fine.
Problem
If I replace line
time.Sleep(time.Second)
by line
time.Sleep(time.Hour) // long test
I don't get slack printed "Test finished" in hour. Instead, I see in my app logs:
responseUrl https://hooks.slack.com/commands/T3GBFUZ64/86817661808/XRmDO21jYaP1Wzu7GFpNw9eW
404
Expired url
Looks like slack's response URL has an expiration time. How to extend this expiration time?
Or in a case of expiration, is there another way to send a message to the user about having the test finished? I have name and id of a user launching /my-command
req.PostFormValue("user_name")
req.PostFormValue("user_id")
So I want to run integration tests by slack which are longer than 2 hours and get a response after finishing such tests in slack.