Unverified Commit 578a3df0 authored by Sander van Harmelen's avatar Sander van Harmelen Committed by GitHub

Tweak the webhook parsing logic a bit (#514)

parent 93f906f8
...@@ -6,11 +6,40 @@ import ( ...@@ -6,11 +6,40 @@ import (
"net/http" "net/http"
) )
// EventType represents a Gitlab event type.
type EventType string
// List of available event types.
const (
EventTypeBuild EventType = "Build Hook"
EventTypeIssue EventType = "Issue Hook"
EventTypeMergeRequest EventType = "Merge Request Hook"
EventTypeNote EventType = "Note Hook"
EventTypePipeline EventType = "Pipeline Hook"
EventTypePush EventType = "Push Hook"
EventTypeTagPush EventType = "Tag Push Hook"
EventTypeWikiPage EventType = "Wiki Page Hook"
)
const (
noteableTypeCommit = "Commit"
noteableTypeMergeRequest = "MergeRequest"
noteableTypeIssue = "Issue"
noteableTypeSnippet = "Snippet"
)
type noteEvent struct {
ObjectKind string `json:"object_kind"`
ObjectAttributes struct {
NoteableType string `json:"noteable_type"`
} `json:"object_attributes"`
}
const eventTypeHeader = "X-Gitlab-Event" const eventTypeHeader = "X-Gitlab-Event"
// WebhookEventType returns the event type for the given request. // WebhookEventType returns the event type for the given request.
func WebhookEventType(r *http.Request) string { func WebhookEventType(r *http.Request) EventType {
return r.Header.Get(eventTypeHeader) return EventType(r.Header.Get(eventTypeHeader))
} }
// ParseWebhook parses the event payload. For recognized event types, a // ParseWebhook parses the event payload. For recognized event types, a
...@@ -33,80 +62,34 @@ func WebhookEventType(r *http.Request) string { ...@@ -33,80 +62,34 @@ func WebhookEventType(r *http.Request) string {
// } // }
// } // }
// //
func ParseWebhook(typeHeaderValue string, payload []byte) (interface{}, error) { func ParseWebhook(eventType EventType, payload []byte) (event interface{}, err error) {
t, ok := eventTypeMapping[typeHeaderValue] switch eventType {
if !ok { case EventTypeBuild:
return nil, fmt.Errorf("unexpected value for %s header: %s", eventTypeHeader, typeHeaderValue) event = &BuildEvent{}
} case EventTypeIssue:
event = &IssueEvent{}
event := rawWebhookEvent{ case EventTypeMergeRequest:
Type: t, event = &MergeEvent{}
RawPayload: payload, case EventTypePipeline:
} event = &PipelineEvent{}
return event.ParsePayload() case EventTypePush:
}
type eventStructType string
const (
eventStructTypePushEvent eventStructType = "PushEvent"
eventStructTypeTagEvent eventStructType = "TagEvent"
eventStructTypeIssueEvent eventStructType = "IssueEvent"
eventStructTypeAmbiguousCommentEvent eventStructType = "ambiguousCommentEvent"
eventStructTypeMergeEvent eventStructType = "MergeEvent"
eventStructTypeWikiPageEvent eventStructType = "WikiPageEvent"
eventStructTypePipelineEvent eventStructType = "PipelineEvent"
eventStructTypeBuildEvent eventStructType = "BuildEvent"
)
// Keys here are possible values for the X-Gitlab-Event header.
var eventTypeMapping = map[string]eventStructType{
"Push Hook": eventStructTypePushEvent,
"Tag Push Hook": eventStructTypeTagEvent,
"Issue Hook": eventStructTypeIssueEvent,
"Note Hook": eventStructTypeAmbiguousCommentEvent,
"Merge Request Hook": eventStructTypeMergeEvent,
"Wiki Page Hook": eventStructTypeWikiPageEvent,
"Pipeline Hook": eventStructTypePipelineEvent,
"Build Hook": eventStructTypeBuildEvent,
}
type rawWebhookEvent struct {
Type eventStructType
RawPayload json.RawMessage
}
const (
noteableTypeCommit = "Commit"
noteableTypeMergeRequest = "MergeRequest"
noteableTypeIssue = "Issue"
noteableTypeSnippet = "Snippet"
)
type ambiguousCommentEvent struct {
ObjectKind string `json:"object_kind"`
ObjectAttributes struct {
NoteableType string `json:"noteable_type"`
} `json:"object_attributes"`
}
func (e *rawWebhookEvent) ParsePayload() (event interface{}, err error) {
switch e.Type {
case eventStructTypePushEvent:
event = &PushEvent{} event = &PushEvent{}
case eventStructTypeTagEvent: case EventTypeTagPush:
event = &TagEvent{} event = &TagEvent{}
case eventStructTypeIssueEvent: case EventTypeWikiPage:
event = &IssueEvent{} event = &WikiPageEvent{}
case eventStructTypeAmbiguousCommentEvent: case EventTypeNote:
ambi := &ambiguousCommentEvent{} note := &noteEvent{}
err := json.Unmarshal(e.RawPayload, ambi) err := json.Unmarshal(payload, note)
if err != nil { if err != nil {
return nil, err return nil, err
} else if ambi.ObjectKind != "note" {
return nil, fmt.Errorf("unexpected object kind %s", ambi.ObjectKind)
} }
switch ambi.ObjectAttributes.NoteableType {
if note.ObjectKind != "note" {
return nil, fmt.Errorf("unexpected object kind %s", note.ObjectKind)
}
switch note.ObjectAttributes.NoteableType {
case noteableTypeCommit: case noteableTypeCommit:
event = &CommitCommentEvent{} event = &CommitCommentEvent{}
case noteableTypeMergeRequest: case noteableTypeMergeRequest:
...@@ -116,20 +99,16 @@ func (e *rawWebhookEvent) ParsePayload() (event interface{}, err error) { ...@@ -116,20 +99,16 @@ func (e *rawWebhookEvent) ParsePayload() (event interface{}, err error) {
case noteableTypeSnippet: case noteableTypeSnippet:
event = &SnippetCommentEvent{} event = &SnippetCommentEvent{}
default: default:
return nil, fmt.Errorf("unexpected noteable type %s", ambi.ObjectAttributes.NoteableType) return nil, fmt.Errorf("unexpected noteable type %s", note.ObjectAttributes.NoteableType)
} }
case eventStructTypeMergeEvent:
event = &MergeEvent{}
case eventStructTypeWikiPageEvent:
event = &WikiPageEvent{}
case eventStructTypePipelineEvent:
event = &PipelineEvent{}
case eventStructTypeBuildEvent:
event = &BuildEvent{}
default: default:
return nil, fmt.Errorf("unexpected event type: %s", e.Type) return nil, fmt.Errorf("unexpected event type: %s", eventType)
}
if err := json.Unmarshal(payload, event); err != nil {
return nil, err
} }
err = json.Unmarshal(e.RawPayload, event) return event, nil
return event, err
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment