From 53f8e310e3b4c3ba77b13fc1ffe0b130302e98d9 Mon Sep 17 00:00:00 2001 From: jackspirou Date: Fri, 20 Nov 2015 17:51:50 -0600 Subject: [PATCH] adding auth and some updates --- main.go | 71 +++++++++++++++++++++++++++++++++++++++++------------- webhook.go | 16 ++++++++++++ 2 files changed, 70 insertions(+), 17 deletions(-) create mode 100644 webhook.go diff --git a/main.go b/main.go index 13bb380..6720bfe 100644 --- a/main.go +++ b/main.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" "fmt" + "io/ioutil" "net/http" "net/url" "os" @@ -14,26 +15,22 @@ import ( ) func main() { + + // plugin settings var repo = drone.Repo{} var build = drone.Build{} - var vargs = struct { - Urls []string `json:"urls"` - Headers map[string]string `json:"header"` - Method string `json:"method"` - Template string `json:"template"` - ContentType string `json:"content_type"` - }{} + var vargs = Webhook{} + // set plugin parameters plugin.Param("repo", &repo) plugin.Param("build", &build) plugin.Param("vargs", &vargs) - plugin.Parse() - // data structure - data := struct { - Repo drone.Repo `json:"repo"` - Build drone.Build `json:"build"` - }{repo, build} + // parse the parameters + if err := plugin.Parse(); err != nil { + fmt.Println(err) + os.Exit(1) + } // set default values if len(vargs.Method) == 0 { @@ -43,19 +40,26 @@ func main() { vargs.ContentType = "application/json" } + // data structure + data := struct { + Repo drone.Repo `json:"repo"` + Build drone.Build `json:"build"` + }{repo, build} + // creates the payload. by default the payload // is the build details in json format, but a custom // template may also be used. var buf bytes.Buffer if len(vargs.Template) == 0 { json.NewEncoder(&buf).Encode(&data) - } else { + t, err := template.New("_").Parse(vargs.Template) if err != nil { fmt.Printf("Error parsing content template. %s\n", err) os.Exit(1) } + t.Execute(&buf, &data) if err != nil { fmt.Printf("Error executing content template. %s\n", err) @@ -63,8 +67,11 @@ func main() { } } - // post payload to each url - for _, rawurl := range vargs.Urls { + // build and execute a request for each url. + // all auth, headers, method, template (payload), + // and content_type values will be applied to + // every webhook request. + for i, rawurl := range vargs.Urls { uri, err := url.Parse(rawurl) if err != nil { @@ -72,21 +79,51 @@ func main() { os.Exit(1) } + // vargs.Method defaults to POST, no need to check req, err := http.NewRequest(vargs.Method, uri.String(), &buf) if err != nil { fmt.Printf("Error creating http request. %s\n", err) os.Exit(1) } + + // vargs.ContentType defaults to application/json, no need to check req.Header.Set("Content-Type", vargs.ContentType) for key, value := range vargs.Headers { req.Header.Set(key, value) } + // set basic auth if a user or user and pass is provided + if len(vargs.Auth.Username) > 0 { + if len(vargs.Auth.Password) > 0 { + req.SetBasicAuth(vargs.Auth.Username, vargs.Auth.Password) + } else { + req.SetBasicAuth(vargs.Auth.Username, "") + } + } + resp, err := http.DefaultClient.Do(req) if err != nil { fmt.Printf("Error executing http request. %s\n", err) os.Exit(1) } - resp.Body.Close() + defer resp.Body.Close() + + if vargs.Verbose { + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + // I do not think we need to os.Exit(1) if we are + // unable to read a http response body. + fmt.Printf("Error reading http response body. %s\n", err) + } + + // scrub out basic auth pass + if len(vargs.Auth.Password) > 0 { + req.SetBasicAuth(vargs.Auth.Username, "XXXXX") + } + + // print out + fmt.Printf("%d\n URL: %s\n METHOD: %s\n HEADERS: %s\n BODY: %s\n RESPONSE STATUS: %s\n RESPONSE: %s", i+1, req.URL, req.Method, req.Header, req.Body, resp.Status, string(body)) + } } } diff --git a/webhook.go b/webhook.go new file mode 100644 index 0000000..01f8ef0 --- /dev/null +++ b/webhook.go @@ -0,0 +1,16 @@ +package main + +type Webhook struct { + Urls []string `json:"urls"` + Verbose bool `json:"verbose"` + Auth BasicAuth `json:"auth"` + Headers map[string]string `json:"header"` + Method string `json:"method"` + Template string `json:"template"` + ContentType string `json:"content_type"` +} + +type BasicAuth struct { + Username string `json:"username"` + Password string `json:"password"` +}