123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- package webhooks
-
- import (
- "fmt"
- "net/http"
- )
-
- // Header provides http.Header to minimize imports
- type Header http.Header
-
- // Provider defines the type of webhook
- type Provider int
-
- func (p Provider) String() string {
- switch p {
- case GitHub:
- return "GitHub"
- case Bitbucket:
- return "Bitbucket"
- case GitLab:
- return "GitLab"
- default:
- return "Unknown"
- }
- }
-
- // webhooks available providers
- const (
- GitHub Provider = iota
- Bitbucket
- GitLab
- )
-
- // Webhook interface defines a webhook to receive events
- type Webhook interface {
- Provider() Provider
- ParsePayload(w http.ResponseWriter, r *http.Request)
- }
-
- type server struct {
- hook Webhook
- path string
- includePathCheck bool
- }
-
- // ProcessPayloadFunc is a common function for payload return values
- type ProcessPayloadFunc func(payload interface{}, header Header)
-
- // Handler returns the webhook http.Handler for use in your own Mux implementation
- func Handler(hook Webhook) http.Handler {
- return &server{
- hook: hook,
- }
- }
-
- // Run runs a server
- func Run(hook Webhook, addr string, path string) error {
- srv := &server{
- hook: hook,
- path: path,
- includePathCheck: true,
- }
- s := &http.Server{Addr: addr, Handler: srv}
-
- DefaultLog.Info(fmt.Sprintf("Listening on addr: %s path: %s", addr, path))
- return s.ListenAndServe()
- }
-
- // RunServer runs a custom server.
- func RunServer(s *http.Server, hook Webhook, path string) error {
-
- srv := &server{
- hook: hook,
- path: path,
- includePathCheck: true,
- }
-
- s.Handler = srv
- DefaultLog.Info(fmt.Sprintf("Listening on addr: %s path: %s", s.Addr, path))
- return s.ListenAndServe()
- }
-
- // RunTLSServer runs a custom server with TLS configuration.
- // NOTE: http.Server Handler will be overridden by this library, just set it to nil.
- // Setting the Certificates can be done in the http.Server.TLSConfig.Certificates
- // see example here: https://github.com/go-playground/webhooks/blob/v2/webhooks_test.go#L178
- func RunTLSServer(s *http.Server, hook Webhook, path string) error {
-
- srv := &server{
- hook: hook,
- path: path,
- includePathCheck: true,
- }
-
- s.Handler = srv
- DefaultLog.Info(fmt.Sprintf("Listening on addr: %s path: %s", s.Addr, path))
- return s.ListenAndServeTLS("", "")
- }
-
- // ServeHTTP is the Handler for every posted WebHook Event
- func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
- defer r.Body.Close()
- DefaultLog.Info("Webhook received")
-
- if r.Method != "POST" {
- DefaultLog.Error(fmt.Sprintf("405 Method not allowed, attempt made using Method: %s", r.Method))
- http.Error(w, "405 Method not allowed", http.StatusMethodNotAllowed)
- return
- }
-
- DefaultLog.Debug(fmt.Sprintf("Include path check: %t", s.includePathCheck))
- if s.includePathCheck {
- if r.URL.Path != s.path {
- DefaultLog.Error(fmt.Sprintf("404 Not found, POST made using path: %s, but expected %s", r.URL.Path, s.path))
- http.Error(w, "404 Not found", http.StatusNotFound)
- return
- }
- }
-
- s.hook.ParsePayload(w, r)
- }
|