Compare commits

..

1 Commits

Author SHA1 Message Date
Dean Karn 19138534b5 Add debugging 2017-04-25 11:11:43 -04:00
14 changed files with 219 additions and 420 deletions
-39
View File
@@ -1,39 +0,0 @@
language: go
go:
- 1.7.6
- 1.8.3
- tip
matrix:
allow_failures:
- go: tip
notifications:
email:
recipients: dean.karn@gmail.com
on_success: change
on_failure: always
before_install:
- go get -u github.com/go-playground/overalls
- go get -u github.com/mattn/goveralls
- go get -u golang.org/x/tools/cmd/cover
- go get -u github.com/golang/lint/golint
- go get -u github.com/gordonklaus/ineffassign
- mkdir -p $GOPATH/src/gopkg.in
- ln -s $GOPATH/src/github.com/$TRAVIS_REPO_SLUG $GOPATH/src/gopkg.in/webhooks.v2
- ln -s $GOPATH/src/github.com/$TRAVIS_REPO_SLUG $GOPATH/src/gopkg.in/webhooks.v3
before_script:
- go vet ./...
script:
- gofmt -d -s .
- golint ./...
- ineffassign ./
- go test -v ./...
- go test -race
after_success: |
[ $TRAVIS_GO_VERSION = 1.8.3 ] &&
overalls -project="github.com/go-playground/webhooks" -covermode=count -ignore=.git,examples -debug &&
goveralls -coverprofile=overalls.coverprofile -service travis-ci -repotoken $COVERALLS_TOKEN
+2 -2
View File
@@ -1,7 +1,7 @@
Library webhooks
================
<img align="right" src="https://raw.githubusercontent.com/go-playground/webhooks/v3/logo.png">![Project status](https://img.shields.io/badge/version-3.3.1-green.svg)
[![Build Status](https://travis-ci.org/go-playground/webhooks.svg?branch=v3)](https://travis-ci.org/go-playground/webhooks)
<img align="right" src="https://raw.githubusercontent.com/go-playground/webhooks/v3/logo.png">![Project status](https://img.shields.io/badge/version-3.0.0-green.svg)
[![Build Status](https://semaphoreci.com/api/v1/joeybloggs/webhooks/branches/v3/badge.svg)](https://semaphoreci.com/joeybloggs/webhooks)
[![Coverage Status](https://coveralls.io/repos/go-playground/webhooks/badge.svg?branch=v3&service=github)](https://coveralls.io/github/go-playground/webhooks?branch=v3)
[![Go Report Card](https://goreportcard.com/badge/go-playground/webhooks)](https://goreportcard.com/report/go-playground/webhooks)
[![GoDoc](https://godoc.org/gopkg.in/go-playground/webhooks.v3?status.svg)](https://godoc.org/gopkg.in/go-playground/webhooks.v3)
+3 -12
View File
@@ -2,7 +2,6 @@ package bitbucket
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
@@ -70,46 +69,38 @@ func (hook Webhook) RegisterEvents(fn webhooks.ProcessPayloadFunc, events ...Eve
// ParsePayload parses and verifies the payload and fires off the mapped function, if it exists.
func (hook Webhook) ParsePayload(w http.ResponseWriter, r *http.Request) {
webhooks.DefaultLog.Info("Parsing Payload...")
uuid := r.Header.Get("X-Hook-UUID")
if uuid == "" {
webhooks.DefaultLog.Error("Missing X-Hook-UUID Header")
http.Error(w, "400 Bad Request - Missing X-Hook-UUID Header", http.StatusBadRequest)
return
}
webhooks.DefaultLog.Debug(fmt.Sprintf("X-Hook-UUID:%s", uuid))
if uuid != hook.uuid {
webhooks.DefaultLog.Error(fmt.Sprintf("X-Hook-UUID does not match configured uuid of %s", hook.uuid))
http.Error(w, "403 Forbidden - X-Hook-UUID does not match", http.StatusForbidden)
http.Error(w, "403 Forbidden - Missing X-Hook-UUID does not match", http.StatusForbidden)
return
}
event := r.Header.Get("X-Event-Key")
if event == "" {
webhooks.DefaultLog.Error("Missing X-Event-Key Header")
http.Error(w, "400 Bad Request - Missing X-Event-Key Header", http.StatusBadRequest)
return
}
webhooks.DefaultLog.Debug(fmt.Sprintf("X-Event-Key:%s", event))
bitbucketEvent := Event(event)
fn, ok := hook.eventFuncs[bitbucketEvent]
// if no event registered
if !ok {
webhooks.DefaultLog.Info(fmt.Sprintf("Webhook Event %s not registered, it is recommended to setup only events in bitbucket that will be registered in the webhook to avoid unnecessary traffic and reduce potential attack vectors.", event))
return
}
payload, err := ioutil.ReadAll(r.Body)
if err != nil || len(payload) == 0 {
webhooks.DefaultLog.Error("Issue reading Payload")
http.Error(w, "Issue reading Payload", http.StatusInternalServerError)
http.Error(w, "Error reading Body", http.StatusInternalServerError)
return
}
webhooks.DefaultLog.Debug(fmt.Sprintf("Payload:%s", string(payload)))
hd := webhooks.Header(r.Header)
switch bitbucketEvent {
-67
View File
@@ -1,67 +0,0 @@
package main
import (
"fmt"
"log"
"strconv"
"gopkg.in/go-playground/webhooks.v3"
"gopkg.in/go-playground/webhooks.v3/github"
)
const (
path = "/webhooks"
port = 3016
)
type myLogger struct {
PrintDebugs bool
}
func (l *myLogger) Info(msg string) {
log.Println(msg)
}
func (l *myLogger) Error(msg string) {
log.Println(msg)
}
func (l *myLogger) Debug(msg string) {
if !l.PrintDebugs {
return
}
log.Println(msg)
}
func main() {
// webhooks.DefaultLog=webhooks.NewLogger(true)
//
// or override with your own
webhooks.DefaultLog = &myLogger{PrintDebugs: true}
hook := github.New(&github.Config{Secret: "MyGitHubSuperSecretSecrect...?"})
hook.RegisterEvents(HandleMultiple, github.ReleaseEvent, github.PullRequestEvent) // Add as many as you want
err := webhooks.Run(hook, ":"+strconv.Itoa(port), path)
if err != nil {
fmt.Println(err)
}
}
// HandleMultiple handles multiple GitHub events
func HandleMultiple(payload interface{}, header webhooks.Header) {
fmt.Println("Handling Payload..")
switch payload.(type) {
case github.ReleasePayload:
release := payload.(github.ReleasePayload)
// Do whatever you want from here...
fmt.Printf("%+v", release)
case github.PullRequestPayload:
pullRequest := payload.(github.PullRequestPayload)
// Do whatever you want from here...
fmt.Printf("%+v", pullRequest)
}
}
+2
View File
@@ -14,6 +14,7 @@ const (
)
func main() {
hook := github.New(&github.Config{Secret: "MyGitHubSuperSecretSecrect...?"})
hook.RegisterEvents(HandleRelease, github.ReleaseEvent)
hook.RegisterEvents(HandlePullRequest, github.PullRequestEvent)
@@ -26,6 +27,7 @@ func main() {
// HandleRelease handles GitHub release events
func HandleRelease(payload interface{}, header webhooks.Header) {
fmt.Println("Handling Release")
pl := payload.(github.ReleasePayload)
+2
View File
@@ -14,6 +14,7 @@ const (
)
func main() {
hook := github.New(&github.Config{Secret: "MyGitHubSuperSecretSecrect...?"})
hook.RegisterEvents(HandleMultiple, github.ReleaseEvent, github.PullRequestEvent) // Add as many as you want
@@ -25,6 +26,7 @@ func main() {
// HandleMultiple handles multiple GitHub events
func HandleMultiple(payload interface{}, header webhooks.Header) {
fmt.Println("Handling Payload..")
switch payload.(type) {
+173 -70
View File
@@ -5,8 +5,8 @@ import (
"crypto/sha1"
"encoding/hex"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"gopkg.in/go-playground/webhooks.v3"
@@ -97,185 +97,288 @@ func (hook Webhook) RegisterEvents(fn webhooks.ProcessPayloadFunc, events ...Eve
// ParsePayload parses and verifies the payload and fires off the mapped function, if it exists.
func (hook Webhook) ParsePayload(w http.ResponseWriter, r *http.Request) {
webhooks.DefaultLog.Info("Parsing Payload...")
log.Println("Gettting X-GitHub-Event")
event := r.Header.Get("X-GitHub-Event")
if len(event) == 0 {
webhooks.DefaultLog.Error("Missing X-GitHub-Event Header")
http.Error(w, "400 Bad Request - Missing X-GitHub-Event Header", http.StatusBadRequest)
return
}
webhooks.DefaultLog.Debug(fmt.Sprintf("X-GitHub-Event:%s", event))
gitHubEvent := Event(event)
log.Println("Looking for Hook:", gitHubEvent)
fn, ok := hook.eventFuncs[gitHubEvent]
// if no event registered
if !ok {
webhooks.DefaultLog.Info(fmt.Sprintf("Webhook Event %s not registered, it is recommended to setup only events in github that will be registered in the webhook to avoid unnecessary traffic and reduce potential attack vectors.", event))
return
}
log.Println("READING PAYLOAD FROM BODY")
payload, err := ioutil.ReadAll(r.Body)
if err != nil || len(payload) == 0 {
webhooks.DefaultLog.Error("Issue reading Payload")
http.Error(w, "Issue reading Payload", http.StatusInternalServerError)
http.Error(w, "Error reading Body", http.StatusInternalServerError)
return
}
webhooks.DefaultLog.Debug(fmt.Sprintf("Payload:%s", string(payload)))
log.Println("Checking GitHub secret")
// If we have a Secret set, we should check the MAC
if len(hook.secret) > 0 {
webhooks.DefaultLog.Info("Checking secret")
log.Println("Get GitHub signature")
signature := r.Header.Get("X-Hub-Signature")
if len(signature) == 0 {
webhooks.DefaultLog.Error("Missing X-Hub-Signature required for HMAC verification")
http.Error(w, "403 Forbidden - Missing X-Hub-Signature required for HMAC verification", http.StatusForbidden)
return
}
webhooks.DefaultLog.Debug(fmt.Sprintf("X-Hub-Signature:%s", signature))
mac := hmac.New(sha1.New, []byte(hook.secret))
mac.Write(payload)
expectedMAC := hex.EncodeToString(mac.Sum(nil))
log.Println("Checking HMAC Equality")
if !hmac.Equal([]byte(signature[5:]), []byte(expectedMAC)) {
webhooks.DefaultLog.Error("HMAC verification failed")
http.Error(w, "403 Forbidden - HMAC verification failed", http.StatusForbidden)
return
}
log.Println("HMAC Equal")
}
// Make headers available to ProcessPayloadFunc as a webhooks type
hd := webhooks.Header(r.Header)
var pl interface{}
log.Println("Unmarshal based on GitHub event:", gitHubEvent)
switch gitHubEvent {
case CommitCommentEvent:
var cc CommitCommentPayload
json.Unmarshal([]byte(payload), &cc)
hook.runProcessPayloadFunc(fn, cc, hd)
err = json.Unmarshal([]byte(payload), &cc)
pl = cc
case CreateEvent:
var c CreatePayload
json.Unmarshal([]byte(payload), &c)
hook.runProcessPayloadFunc(fn, c, hd)
err = json.Unmarshal([]byte(payload), &c)
pl = c
case DeleteEvent:
var d DeletePayload
json.Unmarshal([]byte(payload), &d)
hook.runProcessPayloadFunc(fn, d, hd)
case DeploymentEvent:
var d DeploymentPayload
json.Unmarshal([]byte(payload), &d)
hook.runProcessPayloadFunc(fn, d, hd)
err = json.Unmarshal([]byte(payload), &d)
pl = d
case DeploymentStatusEvent:
var d DeploymentStatusPayload
json.Unmarshal([]byte(payload), &d)
hook.runProcessPayloadFunc(fn, d, hd)
err = json.Unmarshal([]byte(payload), &d)
pl = d
case ForkEvent:
var f ForkPayload
json.Unmarshal([]byte(payload), &f)
hook.runProcessPayloadFunc(fn, f, hd)
err = json.Unmarshal([]byte(payload), &f)
pl = f
case GollumEvent:
var g GollumPayload
json.Unmarshal([]byte(payload), &g)
hook.runProcessPayloadFunc(fn, g, hd)
err = json.Unmarshal([]byte(payload), &g)
pl = g
case IssueCommentEvent:
var i IssueCommentPayload
json.Unmarshal([]byte(payload), &i)
hook.runProcessPayloadFunc(fn, i, hd)
err = json.Unmarshal([]byte(payload), &i)
pl = i
case IssuesEvent:
var i IssuesPayload
json.Unmarshal([]byte(payload), &i)
hook.runProcessPayloadFunc(fn, i, hd)
err = json.Unmarshal([]byte(payload), &i)
pl = i
case LabelEvent:
var l LabelPayload
json.Unmarshal([]byte(payload), &l)
hook.runProcessPayloadFunc(fn, l, hd)
err = json.Unmarshal([]byte(payload), &l)
pl = l
case MemberEvent:
var m MemberPayload
json.Unmarshal([]byte(payload), &m)
hook.runProcessPayloadFunc(fn, m, hd)
err = json.Unmarshal([]byte(payload), &m)
pl = m
case MembershipEvent:
var m MembershipPayload
json.Unmarshal([]byte(payload), &m)
hook.runProcessPayloadFunc(fn, m, hd)
err = json.Unmarshal([]byte(payload), &m)
pl = m
case MilestoneEvent:
var m MilestonePayload
json.Unmarshal([]byte(payload), &m)
hook.runProcessPayloadFunc(fn, m, hd)
err = json.Unmarshal([]byte(payload), &m)
pl = m
case OrganizationEvent:
var o OrganizationPayload
json.Unmarshal([]byte(payload), &o)
hook.runProcessPayloadFunc(fn, o, hd)
err = json.Unmarshal([]byte(payload), &o)
pl = o
case OrgBlockEvent:
var o OrgBlockPayload
json.Unmarshal([]byte(payload), &o)
hook.runProcessPayloadFunc(fn, o, hd)
err = json.Unmarshal([]byte(payload), &o)
pl = o
case PageBuildEvent:
var p PageBuildPayload
json.Unmarshal([]byte(payload), &p)
hook.runProcessPayloadFunc(fn, p, hd)
err = json.Unmarshal([]byte(payload), &p)
pl = p
case ProjectCardEvent:
var p ProjectCardPayload
json.Unmarshal([]byte(payload), &p)
hook.runProcessPayloadFunc(fn, p, hd)
err = json.Unmarshal([]byte(payload), &p)
pl = p
case ProjectColumnEvent:
var p ProjectColumnPayload
json.Unmarshal([]byte(payload), &p)
hook.runProcessPayloadFunc(fn, p, hd)
err = json.Unmarshal([]byte(payload), &p)
pl = p
case ProjectEvent:
var p ProjectPayload
json.Unmarshal([]byte(payload), &p)
hook.runProcessPayloadFunc(fn, p, hd)
err = json.Unmarshal([]byte(payload), &p)
pl = p
case PublicEvent:
var p PublicPayload
json.Unmarshal([]byte(payload), &p)
hook.runProcessPayloadFunc(fn, p, hd)
err = json.Unmarshal([]byte(payload), &p)
pl = p
case PullRequestEvent:
var p PullRequestPayload
json.Unmarshal([]byte(payload), &p)
hook.runProcessPayloadFunc(fn, p, hd)
err = json.Unmarshal([]byte(payload), &p)
pl = p
case PullRequestReviewEvent:
var p PullRequestReviewPayload
json.Unmarshal([]byte(payload), &p)
hook.runProcessPayloadFunc(fn, p, hd)
err = json.Unmarshal([]byte(payload), &p)
pl = p
case PullRequestReviewCommentEvent:
var p PullRequestReviewCommentPayload
json.Unmarshal([]byte(payload), &p)
hook.runProcessPayloadFunc(fn, p, hd)
err = json.Unmarshal([]byte(payload), &p)
pl = p
case PushEvent:
var p PushPayload
json.Unmarshal([]byte(payload), &p)
hook.runProcessPayloadFunc(fn, p, hd)
err = json.Unmarshal([]byte(payload), &p)
pl = p
case ReleaseEvent:
var r ReleasePayload
json.Unmarshal([]byte(payload), &r)
hook.runProcessPayloadFunc(fn, r, hd)
err = json.Unmarshal([]byte(payload), &r)
pl = r
case RepositoryEvent:
var r RepositoryPayload
json.Unmarshal([]byte(payload), &r)
hook.runProcessPayloadFunc(fn, r, hd)
err = json.Unmarshal([]byte(payload), &r)
pl = r
case StatusEvent:
var s StatusPayload
json.Unmarshal([]byte(payload), &s)
hook.runProcessPayloadFunc(fn, s, hd)
err = json.Unmarshal([]byte(payload), &s)
pl = s
case TeamEvent:
var t TeamPayload
json.Unmarshal([]byte(payload), &t)
hook.runProcessPayloadFunc(fn, t, hd)
err = json.Unmarshal([]byte(payload), &t)
pl = t
case TeamAddEvent:
var t TeamAddPayload
json.Unmarshal([]byte(payload), &t)
hook.runProcessPayloadFunc(fn, t, hd)
err = json.Unmarshal([]byte(payload), &t)
pl = t
case WatchEvent:
var w WatchPayload
json.Unmarshal([]byte(payload), &w)
hook.runProcessPayloadFunc(fn, w, hd)
err = json.Unmarshal([]byte(payload), &w)
pl = w
}
if err != nil {
log.Println("There was an erro parsing JSON:", err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
log.Println("Running runProcessPayloadFunc")
hook.runProcessPayloadFunc(fn, pl, hd)
}
func (hook Webhook) runProcessPayloadFunc(fn webhooks.ProcessPayloadFunc, results interface{}, header webhooks.Header) {
go func(fn webhooks.ProcessPayloadFunc, results interface{}, header webhooks.Header) {
log.Println("Calling hook function")
fn(results, header)
}(fn, results, header)
}
+2 -8
View File
@@ -2,6 +2,8 @@ package github
import "time"
// PushPayload contains the information for GitHub's push hook event
// CommitCommentPayload contains the information for GitHub's commit_comment hook event
type CommitCommentPayload struct {
Action string `json:"action"`
@@ -2940,13 +2942,6 @@ type PullRequestPayload struct {
Deletions int64 `json:"deletions"`
ChangedFiles int64 `json:"changed_files"`
} `json:"pull_request"`
Label struct {
ID int64 `json:"id"`
URL string `json:"url"`
Name string `json:"name"`
Color string `json:"color"`
Default bool `json:"default"`
} `json:"label"`
Repository struct {
ID int64 `json:"id"`
Name string `json:"name"`
@@ -3959,7 +3954,6 @@ type PushPayload struct {
BaseRef *string `json:"base_ref"`
Compare string `json:"compare"`
Commits []struct {
Sha string `json:"sha"`
ID string `json:"id"`
TreeID string `json:"tree_id"`
Distinct bool `json:"distinct"`
+11 -24
View File
@@ -2,7 +2,6 @@ package gitlab
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
@@ -26,15 +25,14 @@ type Event string
// GitLab hook types
const (
PushEvents Event = "Push Hook"
TagEvents Event = "Tag Push Hook"
IssuesEvents Event = "Issue Hook"
ConfidentialIssuesEvents Event = "Confidential Issue Hook"
CommentEvents Event = "Note Hook"
MergeRequestEvents Event = "Merge Request Hook"
WikiPageEvents Event = "Wiki Page Hook"
PipelineEvents Event = "Pipeline Hook"
BuildEvents Event = "Build Hook"
PushEvents Event = "Push Hook"
TagEvents Event = "Tag Push Hook"
IssuesEvents Event = "Issue Hook"
CommentEvents Event = "Note Hook"
MergeRequestEvents Event = "Merge Request Hook"
WikiPageEvents Event = "Wiki Page Hook"
PipelineEvents Event = "Pipeline Hook"
BuildEvents Event = "Build Hook"
)
// New creates and returns a WebHook instance denoted by the Provider type
@@ -61,39 +59,33 @@ func (hook Webhook) RegisterEvents(fn webhooks.ProcessPayloadFunc, events ...Eve
// ParsePayload parses and verifies the payload and fires off the mapped function, if it exists.
func (hook Webhook) ParsePayload(w http.ResponseWriter, r *http.Request) {
webhooks.DefaultLog.Info("Parsing Payload...")
event := r.Header.Get("X-Gitlab-Event")
if len(event) == 0 {
webhooks.DefaultLog.Error("Missing X-Gitlab-Event Header")
http.Error(w, "400 Bad Request - Missing X-Gitlab-Event Header", http.StatusBadRequest)
return
}
webhooks.DefaultLog.Debug(fmt.Sprintf("X-Gitlab-Event:%s", event))
gitLabEvent := Event(event)
fn, ok := hook.eventFuncs[gitLabEvent]
// if no event registered
if !ok {
webhooks.DefaultLog.Info(fmt.Sprintf("Webhook Event %s not registered, it is recommended to setup only events in gitlab that will be registered in the webhook to avoid unnecessary traffic and reduce potential attack vectors.", event))
return
}
payload, err := ioutil.ReadAll(r.Body)
if err != nil || len(payload) == 0 {
webhooks.DefaultLog.Error("Issue reading Payload")
http.Error(w, "Error reading Payload", http.StatusInternalServerError)
http.Error(w, "Error reading Body", http.StatusInternalServerError)
return
}
webhooks.DefaultLog.Debug(fmt.Sprintf("Payload:%s", string(payload)))
// If we have a Secret set, we should check the MAC
if len(hook.secret) > 0 {
webhooks.DefaultLog.Info("Checking secret")
signature := r.Header.Get("X-Gitlab-Token")
if signature != hook.secret {
webhooks.DefaultLog.Error(fmt.Sprintf("Invalid X-Gitlab-Token of '%s'", signature))
http.Error(w, "403 Forbidden - Token missmatch", http.StatusForbidden)
return
}
@@ -113,11 +105,6 @@ func (hook Webhook) ParsePayload(w http.ResponseWriter, r *http.Request) {
json.Unmarshal([]byte(payload), &te)
hook.runProcessPayloadFunc(fn, te, hd)
case ConfidentialIssuesEvents:
var cie ConfidentialIssueEventPayload
json.Unmarshal([]byte(payload), &cie)
hook.runProcessPayloadFunc(fn, cie, hd)
case IssuesEvents:
var ie IssueEventPayload
json.Unmarshal([]byte(payload), &ie)
-73
View File
@@ -43,7 +43,6 @@ func TestMain(m *testing.M) {
PushEvents,
TagEvents,
IssuesEvents,
ConfidentialIssuesEvents,
CommentEvents,
MergeRequestEvents,
WikiPageEvents,
@@ -350,78 +349,6 @@ func TestIssueEvent(t *testing.T) {
Equal(t, resp.StatusCode, http.StatusOK)
}
func TestConfidentialIssueEvent(t *testing.T) {
payload := `{
"object_kind": "issue",
"user": {
"name": "Administrator",
"username": "root",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
},
"project":{
"name":"Gitlab Test",
"description":"Aut reprehenderit ut est.",
"web_url":"http://example.com/gitlabhq/gitlab-test",
"avatar_url":null,
"git_ssh_url":"git@example.com:gitlabhq/gitlab-test.git",
"git_http_url":"http://example.com/gitlabhq/gitlab-test.git",
"namespace":"GitlabHQ",
"visibility_level":20,
"path_with_namespace":"gitlabhq/gitlab-test",
"default_branch":"master",
"homepage":"http://example.com/gitlabhq/gitlab-test",
"url":"http://example.com/gitlabhq/gitlab-test.git",
"ssh_url":"git@example.com:gitlabhq/gitlab-test.git",
"http_url":"http://example.com/gitlabhq/gitlab-test.git"
},
"repository":{
"name": "Gitlab Test",
"url": "http://example.com/gitlabhq/gitlab-test.git",
"description": "Aut reprehenderit ut est.",
"homepage": "http://example.com/gitlabhq/gitlab-test"
},
"object_attributes": {
"id": 301,
"title": "New API: create/update/delete file",
"assignee_id": 51,
"author_id": 51,
"project_id": 14,
"created_at": "2013-12-03T17:15:43Z",
"updated_at": "2013-12-03T17:15:43Z",
"position": 0,
"branch_name": null,
"description": "Create new API for manipulations with repository",
"milestone_id": null,
"state": "opened",
"iid": 23,
"url": "http://example.com/diaspora/issues/23",
"action": "open"
},
"assignee": {
"name": "User1",
"username": "user1",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
}
}
`
req, err := http.NewRequest("POST", "http://127.0.0.1:3011/webhooks", bytes.NewBuffer([]byte(payload)))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Gitlab-Event", "Confidential Issue Hook")
req.Header.Set("X-Gitlab-Token", "sampleToken!")
Equal(t, err, nil)
client := &http.Client{}
resp, err := client.Do(req)
Equal(t, err, nil)
defer resp.Body.Close()
Equal(t, resp.StatusCode, http.StatusOK)
}
func TestCommentCommitEvent(t *testing.T) {
payload := `{
+1 -8
View File
@@ -40,13 +40,6 @@ type IssueEventPayload struct {
Assignee Assignee `json:"assignee"`
}
// ConfidentialIssueEventPayload contains the information for GitLab's confidential issue event
type ConfidentialIssueEventPayload struct {
// The data for confidential issues is currently the same as normal issues,
// so we can just embed the normal issue payload type here.
IssueEventPayload
}
// MergeRequestEventPayload contains the information for GitLab's merge request event
type MergeRequestEventPayload struct {
ObjectKind string `json:"object_kind"`
@@ -319,7 +312,7 @@ type MergeRequest struct {
ID int64 `json:"id"`
TargetBranch string `json:"target_branch"`
SourceBranch string `json:"source_branch"`
SourceProjectID int64 `json:"source_project_id"`
SourceProjectID string `json:"source_project_id"`
AssigneeID int64 `json:"assignee_id"`
AuthorID int64 `json:"author_id"`
Title string `json:"title"`
-44
View File
@@ -1,44 +0,0 @@
package webhooks
import "log"
// DefaultLog contains the default logger for webhooks, and prints only info and error messages by default
// for debugs override DefaultLog or see NewLogger for creating one without debugs.
var DefaultLog Logger = new(logger)
// Logger allows for customizable logging
type Logger interface {
// Info prints basic information.
Info(string)
// Error prints error information.
Error(string)
// Debug prints information usefull for debugging.
Debug(string)
}
// NewLogger returns a new logger for use.
func NewLogger(debug bool) Logger {
return &logger{PrintDebugs: debug}
}
type logger struct {
PrintDebugs bool
}
// Info prints basic information.
func (l *logger) Info(msg string) {
log.Println("INFO:", msg)
}
// v prints error information.
func (l *logger) Error(msg string) {
log.Println("ERROR:", msg)
}
// Debug prints information usefull for debugging.
func (l *logger) Debug(msg string) {
if !l.PrintDebugs {
return
}
log.Println("DEBUG:", msg)
}
+22 -33
View File
@@ -1,7 +1,7 @@
package webhooks
import (
"fmt"
"log"
"net/http"
)
@@ -38,31 +38,22 @@ type Webhook interface {
}
type server struct {
hook Webhook
path string
includePathCheck bool
hook Webhook
path string
}
// 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,
hook: hook,
path: path,
}
s := &http.Server{Addr: addr, Handler: srv}
DefaultLog.Info(fmt.Sprintf("Listening on addr: %s path: %s", addr, path))
return s.ListenAndServe()
}
@@ -70,13 +61,12 @@ func Run(hook Webhook, addr string, path string) error {
func RunServer(s *http.Server, hook Webhook, path string) error {
srv := &server{
hook: hook,
path: path,
includePathCheck: true,
hook: hook,
path: path,
}
s.Handler = srv
DefaultLog.Info(fmt.Sprintf("Listening on addr: %s path: %s", s.Addr, path))
return s.ListenAndServe()
}
@@ -87,35 +77,34 @@ func RunServer(s *http.Server, hook Webhook, path string) error {
func RunTLSServer(s *http.Server, hook Webhook, path string) error {
srv := &server{
hook: hook,
path: path,
includePathCheck: true,
hook: hook,
path: path,
}
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")
defer func() {
log.Println("Closing Request Body")
r.Body.Close()
}()
log.Println("HTTP METHOD:", r.Method)
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
}
log.Println("Chking that paths match:", r.URL.Path == s.path)
if r.URL.Path != s.path {
http.Error(w, "404 Not found", http.StatusNotFound)
return
}
log.Println("Parsing Payload")
s.hook.ParsePayload(w, r)
}
+1 -40
View File
@@ -8,8 +8,6 @@ import (
"testing"
"time"
"net/http/httptest"
. "gopkg.in/go-playground/assert.v1"
)
@@ -49,43 +47,6 @@ func TestMain(m *testing.M) {
// teardown
}
func TestHandler(t *testing.T) {
mux := http.NewServeMux()
mux.Handle("/webhooks", Handler(fakeHook))
s := httptest.NewServer(Handler(fakeHook))
defer s.Close()
payload := "{}"
req, err := http.NewRequest("POST", s.URL+"/webhooks", bytes.NewBuffer([]byte(payload)))
req.Header.Set("Content-Type", "application/json")
Equal(t, err, nil)
client := &http.Client{}
resp, err := client.Do(req)
Equal(t, err, nil)
defer resp.Body.Close()
Equal(t, resp.StatusCode, http.StatusOK)
// Test BAD METHOD
req, err = http.NewRequest("GET", s.URL+"/webhooks", bytes.NewBuffer([]byte(payload)))
req.Header.Set("Content-Type", "application/json")
Equal(t, err, nil)
resp, err = client.Do(req)
Equal(t, err, nil)
defer resp.Body.Close()
Equal(t, resp.StatusCode, http.StatusMethodNotAllowed)
}
func TestRun(t *testing.T) {
go Run(fakeHook, "127.0.0.1:3006", "/webhooks")
@@ -136,7 +97,7 @@ func TestRun(t *testing.T) {
}
func TestRunServer(t *testing.T) {
DefaultLog = NewLogger(true)
server := &http.Server{Addr: "127.0.0.1:3007", Handler: nil}
go RunServer(server, fakeHook, "/webhooks")
time.Sleep(5000)