Skip to content

Commit a2a006a

Browse files
shilchtechknowlogick
authored andcommitted
Add GET requests to webhook (#6771)
* Add GET requests to webhook * make fmt * Handle invalid http method on webhook * Uppercase http method in webhook * Rename v85.go to v86.go * make fmt
1 parent 55a8e12 commit a2a006a

File tree

8 files changed

+71
-15
lines changed

8 files changed

+71
-15
lines changed

models/migrations/migrations.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,8 @@ var migrations = []Migration{
225225
NewMigration("add table to store original imported gpg keys", addGPGKeyImport),
226226
// v85 -> v86
227227
NewMigration("hash application token", hashAppToken),
228+
// v86 -> v87
229+
NewMigration("add http method to webhook", addHTTPMethodToWebhook),
228230
}
229231

230232
// Migrate database to current version

models/migrations/v86.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2019 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package migrations
6+
7+
import (
8+
"github.com/go-xorm/xorm"
9+
)
10+
11+
func addHTTPMethodToWebhook(x *xorm.Engine) error {
12+
type Webhook struct {
13+
HTTPMethod string `xorm:"http_method DEFAULT 'POST'"`
14+
}
15+
16+
return x.Sync2(new(Webhook))
17+
}

models/webhook.go

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"encoding/json"
1414
"fmt"
1515
"io/ioutil"
16+
"net/http"
1617
"strings"
1718
"time"
1819

@@ -105,6 +106,7 @@ type Webhook struct {
105106
OrgID int64 `xorm:"INDEX"`
106107
URL string `xorm:"url TEXT"`
107108
Signature string `xorm:"TEXT"`
109+
HTTPMethod string `xorm:"http_method"`
108110
ContentType HookContentType
109111
Secret string `xorm:"TEXT"`
110112
Events string `xorm:"TEXT"`
@@ -553,6 +555,7 @@ type HookTask struct {
553555
Signature string `xorm:"TEXT"`
554556
api.Payloader `xorm:"-"`
555557
PayloadContent string `xorm:"TEXT"`
558+
HTTPMethod string `xorm:"http_method"`
556559
ContentType HookContentType
557560
EventType HookEventType
558561
IsSSL bool
@@ -707,6 +710,7 @@ func prepareWebhook(e Engine, w *Webhook, repo *Repository, event HookEventType,
707710
URL: w.URL,
708711
Signature: signature,
709712
Payloader: payloader,
713+
HTTPMethod: w.HTTPMethod,
710714
ContentType: w.ContentType,
711715
EventType: event,
712716
IsSSL: w.IsSSL,
@@ -751,9 +755,32 @@ func prepareWebhooks(e Engine, repo *Repository, event HookEventType, p api.Payl
751755

752756
func (t *HookTask) deliver() {
753757
t.IsDelivered = true
758+
t.RequestInfo = &HookRequest{
759+
Headers: map[string]string{},
760+
}
761+
t.ResponseInfo = &HookResponse{
762+
Headers: map[string]string{},
763+
}
754764

755765
timeout := time.Duration(setting.Webhook.DeliverTimeout) * time.Second
756-
req := httplib.Post(t.URL).SetTimeout(timeout, timeout).
766+
767+
var req *httplib.Request
768+
if t.HTTPMethod == http.MethodPost {
769+
req = httplib.Post(t.URL)
770+
switch t.ContentType {
771+
case ContentTypeJSON:
772+
req = req.Header("Content-Type", "application/json").Body(t.PayloadContent)
773+
case ContentTypeForm:
774+
req.Param("payload", t.PayloadContent)
775+
}
776+
} else if t.HTTPMethod == http.MethodGet {
777+
req = httplib.Get(t.URL).Param("payload", t.PayloadContent)
778+
} else {
779+
t.ResponseInfo.Body = fmt.Sprintf("Invalid http method: %v", t.HTTPMethod)
780+
return
781+
}
782+
783+
req = req.SetTimeout(timeout, timeout).
757784
Header("X-Gitea-Delivery", t.UUID).
758785
Header("X-Gitea-Event", string(t.EventType)).
759786
Header("X-Gitea-Signature", t.Signature).
@@ -764,25 +791,11 @@ func (t *HookTask) deliver() {
764791
HeaderWithSensitiveCase("X-GitHub-Event", string(t.EventType)).
765792
SetTLSClientConfig(&tls.Config{InsecureSkipVerify: setting.Webhook.SkipTLSVerify})
766793

767-
switch t.ContentType {
768-
case ContentTypeJSON:
769-
req = req.Header("Content-Type", "application/json").Body(t.PayloadContent)
770-
case ContentTypeForm:
771-
req.Param("payload", t.PayloadContent)
772-
}
773-
774794
// Record delivery information.
775-
t.RequestInfo = &HookRequest{
776-
Headers: map[string]string{},
777-
}
778795
for k, vals := range req.Headers() {
779796
t.RequestInfo.Headers[k] = strings.Join(vals, ",")
780797
}
781798

782-
t.ResponseInfo = &HookResponse{
783-
Headers: map[string]string{},
784-
}
785-
786799
defer func() {
787800
t.Delivered = time.Now().UnixNano()
788801
if t.IsSucceed {

modules/auth/repo_form.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ func (f WebhookForm) ChooseEvents() bool {
196196
// NewWebhookForm form for creating web hook
197197
type NewWebhookForm struct {
198198
PayloadURL string `binding:"Required;ValidUrl"`
199+
HTTPMethod string `binding:"Required;In(POST,GET)"`
199200
ContentType int `binding:"Required"`
200201
Secret string
201202
WebhookForm

options/locale/locale_en-US.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,6 +1192,7 @@ settings.githook_content = Hook Content
11921192
settings.update_githook = Update Hook
11931193
settings.add_webhook_desc = Gitea will send <code>POST</code> requests with a specified content type to the target URL. Read more in the <a target="_blank" rel="noopener noreferrer" href="%s">webhooks guide</a>.
11941194
settings.payload_url = Target URL
1195+
settings.http_method = HTTP Method
11951196
settings.content_type = POST Content Type
11961197
settings.secret = Secret
11971198
settings.slack_username = Username

public/js/index.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1430,6 +1430,15 @@ function initWebhook() {
14301430
}
14311431
});
14321432

1433+
var updateContentType = function () {
1434+
var visible = $('#http_method').val() === 'POST';
1435+
$('#content_type').parent().parent()[visible ? 'show' : 'hide']();
1436+
};
1437+
updateContentType();
1438+
$('#http_method').change(function () {
1439+
updateContentType();
1440+
});
1441+
14331442
// Test delivery
14341443
$('#test-delivery').click(function () {
14351444
var $this = $(this);

routers/repo/webhook.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ func WebHooksNewPost(ctx *context.Context, form auth.NewWebhookForm) {
176176
w := &models.Webhook{
177177
RepoID: orCtx.RepoID,
178178
URL: form.PayloadURL,
179+
HTTPMethod: form.HTTPMethod,
179180
ContentType: contentType,
180181
Secret: form.Secret,
181182
HookEvent: ParseHookEvent(form.WebhookForm),

templates/repo/settings/webhook/gitea.tmpl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,18 @@
66
<label for="payload_url">{{.i18n.Tr "repo.settings.payload_url"}}</label>
77
<input id="payload_url" name="payload_url" type="url" value="{{.Webhook.URL}}" autofocus required>
88
</div>
9+
<div class="field">
10+
<label>{{.i18n.Tr "repo.settings.http_method"}}</label>
11+
<div class="ui selection dropdown">
12+
<input type="hidden" id="http_method" name="http_method" value="{{if .Webhook.HTTPMethod}}{{.Webhook.HTTPMethod}}{{else}}POST{{end}}">
13+
<div class="default text"></div>
14+
<i class="dropdown icon"></i>
15+
<div class="menu">
16+
<div class="item" data-value="POST">POST</div>
17+
<div class="item" data-value="GET">GET</div>
18+
</div>
19+
</div>
20+
</div>
921
<div class="field">
1022
<label>{{.i18n.Tr "repo.settings.content_type"}}</label>
1123
<div class="ui selection dropdown">

0 commit comments

Comments
 (0)