github.com/twilio/twilio-go@v1.20.1/webhook_cluster_test.go (about) 1 //go:build webhook_cluster 2 // +build webhook_cluster 3 4 package twilio 5 6 import ( 7 "encoding/json" 8 "fmt" 9 "net/http" 10 "os" 11 "testing" 12 "time" 13 14 "github.com/localtunnel/go-localtunnel" 15 "github.com/stretchr/testify/assert" 16 twilio "github.com/twilio/twilio-go/client" 17 StudioV2 "github.com/twilio/twilio-go/rest/studio/v2" 18 ) 19 20 var testClient *RestClient 21 var authToken string 22 23 func TestMain(m *testing.M) { 24 var apiKey = os.Getenv("TWILIO_API_KEY") 25 var secret = os.Getenv("TWILIO_API_SECRET") 26 var accountSid = os.Getenv("TWILIO_ACCOUNT_SID") 27 authToken = os.Getenv("TWILIO_AUTH_TOKEN") 28 testClient = NewRestClientWithParams(ClientParams{apiKey, secret, accountSid, nil}) 29 ret := m.Run() 30 os.Exit(ret) 31 } 32 33 func createValidationServer(channel chan bool) *http.Server { 34 server := &http.Server{} 35 server.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 36 url := r.Header["X-Forwarded-Proto"][0] + "://" + r.Header["X-Forwarded-Host"][0] + r.URL.RequestURI() 37 signatureHeader := r.Header["X-Twilio-Signature"] 38 r.ParseForm() 39 params := make(map[string]string) 40 for k, v := range r.PostForm { 41 params[k] = v[0] 42 } 43 requestValidator := twilio.NewRequestValidator(authToken) 44 if len(signatureHeader) != 0 { 45 channel <- requestValidator.Validate(url, params, r.Header["X-Twilio-Signature"][0]) 46 } else { 47 channel <- false 48 } 49 }) 50 return server 51 } 52 53 func createStudioFlowParams(url string, method string) *StudioV2.CreateFlowParams { 54 jsonStr := fmt.Sprintf(`{ 55 "description": "Studio Flow", 56 "states": [ 57 { 58 "name": "Trigger", 59 "type": "trigger", 60 "transitions": [ 61 { 62 "next": "httpRequest", 63 "event": "incomingRequest" 64 } 65 ], 66 "properties": { 67 } 68 }, 69 { 70 "name": "httpRequest", 71 "type": "make-http-request", 72 "transitions": [], 73 "properties": { 74 "method": "%s", 75 "content_type": "application/x-www-form-urlencoded;charset=utf-8", 76 "url": "%s" 77 } 78 } 79 ], 80 "initial_state": "Trigger", 81 "flags": { 82 "allow_concurrent_calls": true 83 } 84 }`, method, url) 85 86 var definition interface{} 87 _ = json.Unmarshal([]byte(jsonStr), &definition) 88 89 params := &StudioV2.CreateFlowParams{ 90 Definition: &definition, 91 } 92 params.SetFriendlyName("Go Cluster Test Flow") 93 params.SetStatus("published") 94 return params 95 } 96 97 func createStudioExecutionParams() *StudioV2.CreateExecutionParams { 98 executionParams := &StudioV2.CreateExecutionParams{} 99 executionParams.SetTo("To") 100 executionParams.SetFrom("From") 101 return executionParams 102 } 103 104 func executeFlow(t *testing.T, flowSid string) { 105 _, exeErr := testClient.StudioV2.CreateExecution(flowSid, createStudioExecutionParams()) 106 if exeErr != nil { 107 t.Fatal("Error with Studio Execution Creation: ", exeErr) 108 } 109 } 110 111 func requestValidation(t *testing.T, method string) { 112 //Invoke Localtunnel 113 listener, ltErr := localtunnel.Listen(localtunnel.Options{}) 114 if ltErr != nil { 115 t.Fatal("Error with Localtunnel: ", ltErr) 116 } 117 //Create Validation Server & Listen 118 channel := make(chan bool) 119 server := createValidationServer(channel) 120 go server.Serve(listener) 121 122 //Extra time for server to set up 123 time.Sleep(1 * time.Second) 124 125 //Create Studio Flow 126 params := createStudioFlowParams(listener.URL(), method) 127 resp, flowErr := testClient.StudioV2.CreateFlow(params) 128 if flowErr != nil { 129 t.Fatal("Error with Studio Flow Creation: ", flowErr) 130 } 131 flowSid := *resp.Sid 132 executeFlow(t, flowSid) 133 134 //Await for Request Validation 135 afterCh := time.After(5 * time.Second) 136 select { 137 case validate := <-channel: 138 assert.True(t, validate) 139 case <-afterCh: 140 t.Fatal("No request was sent to validation server") 141 } 142 defer testClient.StudioV2.DeleteFlow(flowSid) 143 defer server.Close() 144 } 145 146 func TestRequestValidation_GETMethod(t *testing.T) { 147 requestValidation(t, "GET") 148 } 149 150 func TestRequestValidation_POSTMethod(t *testing.T) { 151 requestValidation(t, "POST") 152 }