From a2a006a5d5a542c5c31bdce4647d2401eab88475 Mon Sep 17 00:00:00 2001 From: Simon Date: Sun, 5 May 2019 20:09:02 +0200 Subject: [PATCH] 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 --- models/migrations/migrations.go | 2 + models/migrations/v86.go | 17 +++++++++ models/webhook.go | 43 ++++++++++++++-------- modules/auth/repo_form.go | 1 + options/locale/locale_en-US.ini | 1 + public/js/index.js | 9 +++++ routers/repo/webhook.go | 1 + templates/repo/settings/webhook/gitea.tmpl | 12 ++++++ 8 files changed, 71 insertions(+), 15 deletions(-) create mode 100644 models/migrations/v86.go diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index 1d8cf6578..b86c20576 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -225,6 +225,8 @@ var migrations = []Migration{ NewMigration("add table to store original imported gpg keys", addGPGKeyImport), // v85 -> v86 NewMigration("hash application token", hashAppToken), + // v86 -> v87 + NewMigration("add http method to webhook", addHTTPMethodToWebhook), } // Migrate database to current version diff --git a/models/migrations/v86.go b/models/migrations/v86.go new file mode 100644 index 000000000..492a08c71 --- /dev/null +++ b/models/migrations/v86.go @@ -0,0 +1,17 @@ +// Copyright 2019 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package migrations + +import ( + "github.com/go-xorm/xorm" +) + +func addHTTPMethodToWebhook(x *xorm.Engine) error { + type Webhook struct { + HTTPMethod string `xorm:"http_method DEFAULT 'POST'"` + } + + return x.Sync2(new(Webhook)) +} diff --git a/models/webhook.go b/models/webhook.go index 9be89241a..8a7350bb6 100644 --- a/models/webhook.go +++ b/models/webhook.go @@ -13,6 +13,7 @@ import ( "encoding/json" "fmt" "io/ioutil" + "net/http" "strings" "time" @@ -105,6 +106,7 @@ type Webhook struct { OrgID int64 `xorm:"INDEX"` URL string `xorm:"url TEXT"` Signature string `xorm:"TEXT"` + HTTPMethod string `xorm:"http_method"` ContentType HookContentType Secret string `xorm:"TEXT"` Events string `xorm:"TEXT"` @@ -553,6 +555,7 @@ type HookTask struct { Signature string `xorm:"TEXT"` api.Payloader `xorm:"-"` PayloadContent string `xorm:"TEXT"` + HTTPMethod string `xorm:"http_method"` ContentType HookContentType EventType HookEventType IsSSL bool @@ -707,6 +710,7 @@ func prepareWebhook(e Engine, w *Webhook, repo *Repository, event HookEventType, URL: w.URL, Signature: signature, Payloader: payloader, + HTTPMethod: w.HTTPMethod, ContentType: w.ContentType, EventType: event, IsSSL: w.IsSSL, @@ -751,9 +755,32 @@ func prepareWebhooks(e Engine, repo *Repository, event HookEventType, p api.Payl func (t *HookTask) deliver() { t.IsDelivered = true + t.RequestInfo = &HookRequest{ + Headers: map[string]string{}, + } + t.ResponseInfo = &HookResponse{ + Headers: map[string]string{}, + } timeout := time.Duration(setting.Webhook.DeliverTimeout) * time.Second - req := httplib.Post(t.URL).SetTimeout(timeout, timeout). + + var req *httplib.Request + if t.HTTPMethod == http.MethodPost { + req = httplib.Post(t.URL) + switch t.ContentType { + case ContentTypeJSON: + req = req.Header("Content-Type", "application/json").Body(t.PayloadContent) + case ContentTypeForm: + req.Param("payload", t.PayloadContent) + } + } else if t.HTTPMethod == http.MethodGet { + req = httplib.Get(t.URL).Param("payload", t.PayloadContent) + } else { + t.ResponseInfo.Body = fmt.Sprintf("Invalid http method: %v", t.HTTPMethod) + return + } + + req = req.SetTimeout(timeout, timeout). Header("X-Gitea-Delivery", t.UUID). Header("X-Gitea-Event", string(t.EventType)). Header("X-Gitea-Signature", t.Signature). @@ -764,25 +791,11 @@ func (t *HookTask) deliver() { HeaderWithSensitiveCase("X-GitHub-Event", string(t.EventType)). SetTLSClientConfig(&tls.Config{InsecureSkipVerify: setting.Webhook.SkipTLSVerify}) - switch t.ContentType { - case ContentTypeJSON: - req = req.Header("Content-Type", "application/json").Body(t.PayloadContent) - case ContentTypeForm: - req.Param("payload", t.PayloadContent) - } - // Record delivery information. - t.RequestInfo = &HookRequest{ - Headers: map[string]string{}, - } for k, vals := range req.Headers() { t.RequestInfo.Headers[k] = strings.Join(vals, ",") } - t.ResponseInfo = &HookResponse{ - Headers: map[string]string{}, - } - defer func() { t.Delivered = time.Now().UnixNano() if t.IsSucceed { diff --git a/modules/auth/repo_form.go b/modules/auth/repo_form.go index fd6891288..f48f2f5e6 100644 --- a/modules/auth/repo_form.go +++ b/modules/auth/repo_form.go @@ -196,6 +196,7 @@ func (f WebhookForm) ChooseEvents() bool { // NewWebhookForm form for creating web hook type NewWebhookForm struct { PayloadURL string `binding:"Required;ValidUrl"` + HTTPMethod string `binding:"Required;In(POST,GET)"` ContentType int `binding:"Required"` Secret string WebhookForm diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 4e2ae5153..9af1f8066 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -1192,6 +1192,7 @@ settings.githook_content = Hook Content settings.update_githook = Update Hook settings.add_webhook_desc = Gitea will send POST requests with a specified content type to the target URL. Read more in the webhooks guide. settings.payload_url = Target URL +settings.http_method = HTTP Method settings.content_type = POST Content Type settings.secret = Secret settings.slack_username = Username diff --git a/public/js/index.js b/public/js/index.js index 062ed7ce4..9a9052eba 100644 --- a/public/js/index.js +++ b/public/js/index.js @@ -1430,6 +1430,15 @@ function initWebhook() { } }); + var updateContentType = function () { + var visible = $('#http_method').val() === 'POST'; + $('#content_type').parent().parent()[visible ? 'show' : 'hide'](); + }; + updateContentType(); + $('#http_method').change(function () { + updateContentType(); + }); + // Test delivery $('#test-delivery').click(function () { var $this = $(this); diff --git a/routers/repo/webhook.go b/routers/repo/webhook.go index 6cf636f24..2e76cbfe0 100644 --- a/routers/repo/webhook.go +++ b/routers/repo/webhook.go @@ -176,6 +176,7 @@ func WebHooksNewPost(ctx *context.Context, form auth.NewWebhookForm) { w := &models.Webhook{ RepoID: orCtx.RepoID, URL: form.PayloadURL, + HTTPMethod: form.HTTPMethod, ContentType: contentType, Secret: form.Secret, HookEvent: ParseHookEvent(form.WebhookForm), diff --git a/templates/repo/settings/webhook/gitea.tmpl b/templates/repo/settings/webhook/gitea.tmpl index 605022256..ff52158cb 100644 --- a/templates/repo/settings/webhook/gitea.tmpl +++ b/templates/repo/settings/webhook/gitea.tmpl @@ -6,6 +6,18 @@ +
+ + +