Skip to content

Commit f79c441

Browse files
Allow parsing non-HTTP payloads (#1)
1 parent 1751865 commit f79c441

File tree

6 files changed

+250
-260
lines changed

6 files changed

+250
-260
lines changed

bitbucket-server/bitbucketserver.go

Lines changed: 46 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -83,26 +83,48 @@ func New(options ...Option) (*Webhook, error) {
8383
return hook, nil
8484
}
8585

86+
// Parse verifies and parses the events specified and returns the payload object or an error
8687
func (hook *Webhook) Parse(r *http.Request, events ...Event) (interface{}, error) {
8788
defer func() {
8889
_, _ = io.Copy(ioutil.Discard, r.Body)
8990
_ = r.Body.Close()
9091
}()
9192

92-
if len(events) == 0 {
93-
return nil, ErrEventNotSpecifiedToParse
94-
}
95-
9693
if r.Method != http.MethodPost {
9794
return nil, ErrInvalidHTTPMethod
9895
}
9996

100-
event := r.Header.Get("X-Event-Key")
97+
payload, err := ioutil.ReadAll(r.Body)
98+
if err != nil || len(payload) == 0 {
99+
return nil, ErrParsingPayload
100+
}
101+
102+
return hook.ParsePayload(
103+
payload,
104+
r.Header.Get("X-Event-Key"),
105+
r.Header.Get("X-Hub-Signature"),
106+
events...,
107+
)
108+
}
109+
110+
// ParsePayload verifies and parses the events from a payload and string
111+
// metadata (event type and signature), and returns the payload object or an
112+
// error.
113+
//
114+
// Similar to Parse (which uses this method under the hood), this is useful in
115+
// cases where payloads are not represented as HTTP requests - for example are
116+
// put on a queue for pull processing.
117+
func (hook Webhook) ParsePayload(payload []byte, eventType, signature string, events ...Event) (interface{}, error) {
118+
if len(events) == 0 {
119+
return nil, ErrEventNotSpecifiedToParse
120+
}
121+
122+
event := eventType
101123
if event == "" {
102124
return nil, ErrMissingEventKeyHeader
103125
}
104126

105-
bitbucketEvent := Event(event)
127+
bitbucketEvent := Event(eventType)
106128

107129
var found bool
108130
for _, evt := range events {
@@ -120,13 +142,7 @@ func (hook *Webhook) Parse(r *http.Request, events ...Event) (interface{}, error
120142
return DiagnosticsPingPayload{}, nil
121143
}
122144

123-
payload, err := ioutil.ReadAll(r.Body)
124-
if err != nil || len(payload) == 0 {
125-
return nil, ErrParsingPayload
126-
}
127-
128145
if len(hook.secret) > 0 {
129-
signature := r.Header.Get("X-Hub-Signature")
130146
if len(signature) == 0 {
131147
return nil, ErrMissingHubSignatureHeader
132148
}
@@ -142,76 +158,58 @@ func (hook *Webhook) Parse(r *http.Request, events ...Event) (interface{}, error
142158
switch bitbucketEvent {
143159
case RepositoryReferenceChangedEvent:
144160
var pl RepositoryReferenceChangedPayload
145-
err = json.Unmarshal([]byte(payload), &pl)
146-
return pl, err
161+
return pl, json.Unmarshal(payload, &pl)
147162
case RepositoryModifiedEvent:
148163
var pl RepositoryModifiedPayload
149-
err = json.Unmarshal([]byte(payload), &pl)
150-
return pl, err
164+
return pl, json.Unmarshal(payload, &pl)
151165
case RepositoryForkedEvent:
152166
var pl RepositoryForkedPayload
153-
err = json.Unmarshal([]byte(payload), &pl)
154-
return pl, err
167+
return pl, json.Unmarshal(payload, &pl)
155168
case RepositoryCommentAddedEvent:
156169
var pl RepositoryCommentAddedPayload
157-
err = json.Unmarshal([]byte(payload), &pl)
158-
return pl, err
170+
return pl, json.Unmarshal(payload, &pl)
159171
case RepositoryCommentEditedEvent:
160172
var pl RepositoryCommentEditedPayload
161-
err = json.Unmarshal([]byte(payload), &pl)
162-
return pl, err
173+
return pl, json.Unmarshal(payload, &pl)
163174
case RepositoryCommentDeletedEvent:
164175
var pl RepositoryCommentDeletedPayload
165-
err = json.Unmarshal([]byte(payload), &pl)
166-
return pl, err
176+
return pl, json.Unmarshal(payload, &pl)
167177
case PullRequestOpenedEvent:
168178
var pl PullRequestOpenedPayload
169-
err = json.Unmarshal([]byte(payload), &pl)
170-
return pl, err
179+
return pl, json.Unmarshal(payload, &pl)
171180
case PullRequestModifiedEvent:
172181
var pl PullRequestModifiedPayload
173-
err = json.Unmarshal([]byte(payload), &pl)
174-
return pl, err
182+
return pl, json.Unmarshal(payload, &pl)
175183
case PullRequestMergedEvent:
176184
var pl PullRequestMergedPayload
177-
err = json.Unmarshal([]byte(payload), &pl)
178-
return pl, err
185+
return pl, json.Unmarshal(payload, &pl)
179186
case PullRequestDeclinedEvent:
180187
var pl PullRequestDeclinedPayload
181-
err = json.Unmarshal([]byte(payload), &pl)
182-
return pl, err
188+
return pl, json.Unmarshal(payload, &pl)
183189
case PullRequestDeletedEvent:
184190
var pl PullRequestDeletedPayload
185-
err = json.Unmarshal([]byte(payload), &pl)
186-
return pl, err
191+
return pl, json.Unmarshal(payload, &pl)
187192
case PullRequestReviewerUpdatedEvent:
188193
var pl PullRequestReviewerUpdatedPayload
189-
err = json.Unmarshal([]byte(payload), &pl)
190-
return pl, err
194+
return pl, json.Unmarshal(payload, &pl)
191195
case PullRequestReviewerApprovedEvent:
192196
var pl PullRequestReviewerApprovedPayload
193-
err = json.Unmarshal([]byte(payload), &pl)
194-
return pl, err
197+
return pl, json.Unmarshal(payload, &pl)
195198
case PullRequestReviewerUnapprovedEvent:
196199
var pl PullRequestReviewerUnapprovedPayload
197-
err = json.Unmarshal([]byte(payload), &pl)
198-
return pl, err
200+
return pl, json.Unmarshal(payload, &pl)
199201
case PullRequestReviewerNeedsWorkEvent:
200202
var pl PullRequestReviewerNeedsWorkPayload
201-
err = json.Unmarshal([]byte(payload), &pl)
202-
return pl, err
203+
return pl, json.Unmarshal(payload, &pl)
203204
case PullRequestCommentAddedEvent:
204205
var pl PullRequestCommentAddedPayload
205-
err = json.Unmarshal([]byte(payload), &pl)
206-
return pl, err
206+
return pl, json.Unmarshal(payload, &pl)
207207
case PullRequestCommentEditedEvent:
208208
var pl PullRequestCommentEditedPayload
209-
err = json.Unmarshal([]byte(payload), &pl)
210-
return pl, err
209+
return pl, json.Unmarshal(payload, &pl)
211210
case PullRequestCommentDeletedEvent:
212211
var pl PullRequestCommentDeletedPayload
213-
err = json.Unmarshal([]byte(payload), &pl)
214-
return pl, err
212+
return pl, json.Unmarshal(payload, &pl)
215213
default:
216214
return nil, fmt.Errorf("unknown event %s", bitbucketEvent)
217215
}

bitbucket/bitbucket.go

Lines changed: 45 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -85,28 +85,48 @@ func (hook Webhook) Parse(r *http.Request, events ...Event) (interface{}, error)
8585
_ = r.Body.Close()
8686
}()
8787

88-
if len(events) == 0 {
89-
return nil, ErrEventNotSpecifiedToParse
90-
}
9188
if r.Method != http.MethodPost {
9289
return nil, ErrInvalidHTTPMethod
9390
}
9491

95-
uuid := r.Header.Get("X-Hook-UUID")
92+
payload, err := ioutil.ReadAll(r.Body)
93+
if err != nil || len(payload) == 0 {
94+
return nil, ErrParsingPayload
95+
}
96+
97+
return hook.ParsePayload(
98+
payload,
99+
r.Header.Get("X-Event-Key"),
100+
r.Header.Get("X-Hook-UUID"),
101+
events...,
102+
)
103+
}
104+
105+
// ParsePayload verifies and parses the events from a payload and string
106+
// metadata (event type and UUID), and returns the payload object or an
107+
// error.
108+
//
109+
// Similar to Parse (which uses this method under the hood), this is useful in
110+
// cases where payloads are not represented as HTTP requests - for example are
111+
// put on a queue for pull processing.
112+
func (hook Webhook) ParsePayload(payload []byte, eventType, uuid string, events ...Event) (interface{}, error) {
113+
if len(events) == 0 {
114+
return nil, ErrEventNotSpecifiedToParse
115+
}
116+
96117
if hook.uuid != "" && uuid == "" {
97118
return nil, ErrMissingHookUUIDHeader
98119
}
99120

100-
event := r.Header.Get("X-Event-Key")
101-
if event == "" {
121+
if eventType == "" {
102122
return nil, ErrMissingEventKeyHeader
103123
}
104124

105125
if len(hook.uuid) > 0 && uuid != hook.uuid {
106126
return nil, ErrUUIDVerificationFailed
107127
}
108128

109-
bitbucketEvent := Event(event)
129+
bitbucketEvent := Event(eventType)
110130

111131
var found bool
112132
for _, evt := range events {
@@ -120,84 +140,61 @@ func (hook Webhook) Parse(r *http.Request, events ...Event) (interface{}, error)
120140
return nil, ErrEventNotFound
121141
}
122142

123-
payload, err := ioutil.ReadAll(r.Body)
124-
if err != nil || len(payload) == 0 {
125-
return nil, ErrParsingPayload
126-
}
127-
128143
switch bitbucketEvent {
129144
case RepoPushEvent:
130145
var pl RepoPushPayload
131-
err = json.Unmarshal([]byte(payload), &pl)
132-
return pl, err
146+
return pl, json.Unmarshal(payload, &pl)
133147
case RepoForkEvent:
134148
var pl RepoForkPayload
135-
err = json.Unmarshal([]byte(payload), &pl)
136-
return pl, err
149+
return pl, json.Unmarshal(payload, &pl)
137150
case RepoUpdatedEvent:
138151
var pl RepoUpdatedPayload
139-
err = json.Unmarshal([]byte(payload), &pl)
140-
return pl, err
152+
return pl, json.Unmarshal(payload, &pl)
141153
case RepoCommitCommentCreatedEvent:
142154
var pl RepoCommitCommentCreatedPayload
143-
err = json.Unmarshal([]byte(payload), &pl)
144-
return pl, err
155+
return pl, json.Unmarshal(payload, &pl)
145156
case RepoCommitStatusCreatedEvent:
146157
var pl RepoCommitStatusCreatedPayload
147-
err = json.Unmarshal([]byte(payload), &pl)
148-
return pl, err
158+
return pl, json.Unmarshal(payload, &pl)
149159
case RepoCommitStatusUpdatedEvent:
150160
var pl RepoCommitStatusUpdatedPayload
151-
err = json.Unmarshal([]byte(payload), &pl)
152-
return pl, err
161+
return pl, json.Unmarshal(payload, &pl)
153162
case IssueCreatedEvent:
154163
var pl IssueCreatedPayload
155-
err = json.Unmarshal([]byte(payload), &pl)
156-
return pl, err
164+
return pl, json.Unmarshal(payload, &pl)
157165
case IssueUpdatedEvent:
158166
var pl IssueUpdatedPayload
159-
err = json.Unmarshal([]byte(payload), &pl)
160-
return pl, err
167+
return pl, json.Unmarshal(payload, &pl)
161168
case IssueCommentCreatedEvent:
162169
var pl IssueCommentCreatedPayload
163-
err = json.Unmarshal([]byte(payload), &pl)
164-
return pl, err
170+
return pl, json.Unmarshal(payload, &pl)
165171
case PullRequestCreatedEvent:
166172
var pl PullRequestCreatedPayload
167-
err = json.Unmarshal([]byte(payload), &pl)
168-
return pl, err
173+
return pl, json.Unmarshal(payload, &pl)
169174
case PullRequestUpdatedEvent:
170175
var pl PullRequestUpdatedPayload
171-
err = json.Unmarshal([]byte(payload), &pl)
172-
return pl, err
176+
return pl, json.Unmarshal(payload, &pl)
173177
case PullRequestApprovedEvent:
174178
var pl PullRequestApprovedPayload
175-
err = json.Unmarshal([]byte(payload), &pl)
176-
return pl, err
179+
return pl, json.Unmarshal(payload, &pl)
177180
case PullRequestUnapprovedEvent:
178181
var pl PullRequestUnapprovedPayload
179-
err = json.Unmarshal([]byte(payload), &pl)
180-
return pl, err
182+
return pl, json.Unmarshal(payload, &pl)
181183
case PullRequestMergedEvent:
182184
var pl PullRequestMergedPayload
183-
err = json.Unmarshal([]byte(payload), &pl)
184-
return pl, err
185+
return pl, json.Unmarshal(payload, &pl)
185186
case PullRequestDeclinedEvent:
186187
var pl PullRequestDeclinedPayload
187-
err = json.Unmarshal([]byte(payload), &pl)
188-
return pl, err
188+
return pl, json.Unmarshal(payload, &pl)
189189
case PullRequestCommentCreatedEvent:
190190
var pl PullRequestCommentCreatedPayload
191-
err = json.Unmarshal([]byte(payload), &pl)
192-
return pl, err
191+
return pl, json.Unmarshal(payload, &pl)
193192
case PullRequestCommentUpdatedEvent:
194193
var pl PullRequestCommentUpdatedPayload
195-
err = json.Unmarshal([]byte(payload), &pl)
196-
return pl, err
194+
return pl, json.Unmarshal(payload, &pl)
197195
case PullRequestCommentDeletedEvent:
198196
var pl PullRequestCommentDeletedPayload
199-
err = json.Unmarshal([]byte(payload), &pl)
200-
return pl, err
197+
return pl, json.Unmarshal(payload, &pl)
201198
default:
202199
return nil, fmt.Errorf("unknown event %s", bitbucketEvent)
203200
}

docker/docker.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,20 @@ func (hook Webhook) Parse(r *http.Request, events ...Event) (interface{}, error)
8383
return nil, ErrParsingPayload
8484
}
8585

86+
return hook.ParsePayload(payload, events...)
87+
}
88+
89+
// ParsePayload verifies and parses the Build event from a payload, and returns
90+
// the payload object or an error.
91+
//
92+
// Similar to Parse (which uses this method under the hood), this is useful in
93+
// cases where payloads are not represented as HTTP requests - for example are
94+
// put on a queue for pull processing.
95+
func (hook Webhook) ParsePayload(payload []byte, events ...Event) (interface{}, error) {
8696
var pl BuildPayload
87-
err = json.Unmarshal([]byte(payload), &pl)
88-
if err != nil {
97+
if err := json.Unmarshal(payload, &pl); err != nil {
8998
return nil, ErrParsingPayload
9099
}
91-
return pl, err
92100

101+
return pl, nil
93102
}

0 commit comments

Comments
 (0)