gitea webhook empty POST variable #3710

Closed
opened 2025-11-02 05:22:35 -06:00 by GiteaMirror · 6 comments
Owner

Originally created by @8ctopus on GitHub (Aug 1, 2019).

Description

Upgrading from gitea 1.8.3 to 1.9.0 breaks gitea webhooks of type application/x-www-form-urlencoded: the POST variable is empty and therefore doesn't contain the payload.

sample hook on receiver side:
<?php
file_put_contents('/var/tmp/gitea-debug.log', var_export($_POST, true));
exit();

result in 1.9.0:
array ( )

result in 1.8.3:
array ( 'payload' => '{ "secret": "***********", "ref": "refs/heads/master", "before": "3bc52c056257af7ae79fe5399f59f5de506b877c", "after": "3bc52c056257af7ae79fe5399f59f5de506b877c", "compare_url": "", "commits": [ ... }', )

UPDATE: It looks like the same issue as this one https://github.com/go-gitea/gitea/issues/7692

Screenshots

2019-08-01_152635

Originally created by @8ctopus on GitHub (Aug 1, 2019). - Gitea version (or commit ref): 1.9.0 (https://github.com/go-gitea/gitea/releases/tag/v1.9.0) - Git version: 2.16.5 - Operating system: Centos 7 - Database (use `[x]`): - [ ] PostgreSQL - [x] MySQL - [ ] MSSQL - [ ] SQLite - Can you reproduce the bug at https://try.gitea.io: - [x] Yes (provide example URL) - [ ] No - [ ] Not relevant - Log gist: ## Description Upgrading from gitea 1.8.3 to 1.9.0 breaks gitea webhooks of type application/x-www-form-urlencoded: the POST variable is empty and therefore doesn't contain the payload. sample hook on receiver side: `<?php` `file_put_contents('/var/tmp/gitea-debug.log', var_export($_POST, true));` `exit();` result in 1.9.0: `array ( )` result in 1.8.3: `array ( 'payload' => '{ "secret": "***********", "ref": "refs/heads/master", "before": "3bc52c056257af7ae79fe5399f59f5de506b877c", "after": "3bc52c056257af7ae79fe5399f59f5de506b877c", "compare_url": "", "commits": [ ... }', )` UPDATE: It looks like the same issue as this one [https://github.com/go-gitea/gitea/issues/7692](https://github.com/go-gitea/gitea/issues/7692) ## Screenshots ![2019-08-01_152635](https://user-images.githubusercontent.com/13252042/62286775-daff9d80-b471-11e9-808d-745893aa10ce.png)
GiteaMirror added the issue/confirmedtype/bug labels 2025-11-02 05:22:35 -06:00
Author
Owner

@stale[bot] commented on GitHub (Oct 1, 2019):

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs during the next 2 weeks. Thank you for your contributions.

@stale[bot] commented on GitHub (Oct 1, 2019): This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs during the next 2 weeks. Thank you for your contributions.
Author
Owner

@8ctopus commented on GitHub (Oct 1, 2019):

Problem is still present in version 1.9.3...
switching the webhook POST content type from application/x-www-form-urlencoded to application/json fixes the problem if the recipient php code is updated accordingly.

...

$content_type = isset($_SERVER['CONTENT_TYPE']) ? strtolower(trim($_SERVER['CONTENT_TYPE'])) : '';

switch ($content_type)
{
    case 'application/json':
        // get RAW post data
        $payload = trim(file_get_contents("php://input"));
        break;

    case '':
        // get payload
        $payload = @$_POST['payload'];
        break;

    default:
        error_log($log_base .' - FAILED - unknown content type - '. $content_type);
        header('HTTP/1.0 401 Unauthorized');
        exit();
}

// check payload exists
if (empty($payload))
{
    error_log($log_base .' - FAILED - no payload');
    header('HTTP/1.0 401 Unauthorized');
    exit();
}

// convert json to array
$decoded = json_decode($payload, true);

...
@8ctopus commented on GitHub (Oct 1, 2019): Problem is still present in version 1.9.3... switching the webhook POST content type from application/x-www-form-urlencoded to application/json fixes the problem if the recipient php code is updated accordingly. ``` ... $content_type = isset($_SERVER['CONTENT_TYPE']) ? strtolower(trim($_SERVER['CONTENT_TYPE'])) : ''; switch ($content_type) { case 'application/json': // get RAW post data $payload = trim(file_get_contents("php://input")); break; case '': // get payload $payload = @$_POST['payload']; break; default: error_log($log_base .' - FAILED - unknown content type - '. $content_type); header('HTTP/1.0 401 Unauthorized'); exit(); } // check payload exists if (empty($payload)) { error_log($log_base .' - FAILED - no payload'); header('HTTP/1.0 401 Unauthorized'); exit(); } // convert json to array $decoded = json_decode($payload, true); ... ```
Author
Owner

@8ctopus commented on GitHub (Oct 2, 2019):

looks like the payload is no longer passed correctly.

models/webhook.go deliver() function code in 1.8.3

func (t *HookTask) deliver() {
	...
	req := httplib.Post(t.URL).SetTimeout(timeout, timeout).
		Header("X-Gitea-Delivery", t.UUID).
		Header("X-Gitea-Event", string(t.EventType)).
		Header("X-Gogs-Delivery", t.UUID).
		Header("X-Gogs-Event", string(t.EventType)).
		HeaderWithSensitiveCase("X-GitHub-Delivery", t.UUID).
		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)
	}

and code in HEAD revision on master

func (t *HookTask) deliver() error {
	t.IsDelivered = true

	var req *http.Request
	var err error

	switch t.HTTPMethod {
	case "":
		log.Info("HTTP Method for webhook %d empty, setting to POST as default", t.ID)
		fallthrough
	case http.MethodPost:
		switch t.ContentType {
		case ContentTypeJSON:
			req, err = http.NewRequest("POST", t.URL, strings.NewReader(t.PayloadContent))
			if err != nil {
				return err
			}

			req.Header.Set("Content-Type", "application/json")

		case ContentTypeForm:
			var forms = url.Values{
				"payload": []string{t.PayloadContent},
			}

			req, err = http.NewRequest("POST", t.URL, strings.NewReader(forms.Encode()))
			if err != nil {

				return err
			}
		}
@8ctopus commented on GitHub (Oct 2, 2019): looks like the payload is no longer passed correctly. models/webhook.go deliver() function code in 1.8.3 ``` func (t *HookTask) deliver() { ... req := httplib.Post(t.URL).SetTimeout(timeout, timeout). Header("X-Gitea-Delivery", t.UUID). Header("X-Gitea-Event", string(t.EventType)). Header("X-Gogs-Delivery", t.UUID). Header("X-Gogs-Event", string(t.EventType)). HeaderWithSensitiveCase("X-GitHub-Delivery", t.UUID). 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) } ``` and code in HEAD revision on master ``` func (t *HookTask) deliver() error { t.IsDelivered = true var req *http.Request var err error switch t.HTTPMethod { case "": log.Info("HTTP Method for webhook %d empty, setting to POST as default", t.ID) fallthrough case http.MethodPost: switch t.ContentType { case ContentTypeJSON: req, err = http.NewRequest("POST", t.URL, strings.NewReader(t.PayloadContent)) if err != nil { return err } req.Header.Set("Content-Type", "application/json") case ContentTypeForm: var forms = url.Values{ "payload": []string{t.PayloadContent}, } req, err = http.NewRequest("POST", t.URL, strings.NewReader(forms.Encode())) if err != nil { return err } } ```
Author
Owner

@vszakats commented on GitHub (Oct 20, 2019):

As of v1.9.4, the issue is still there. It seems that the Content-Type: application/x-www-form-urlencoded header is missing from the POST request.

May be related to changing the http client from GiteaServer to Go-http-client/1.1 between 1.8.3 and 1.9.x. Maybe the former set this by default, but the new client needs to have it set explicitly [UPDATE: Yes, confirmed, see PR]:

POST / HTTP/1.1
Host: localhost:9090
User-Agent: Go-http-client/1.1
Content-Length: 4224
X-GitHub-Delivery: ffffffff-0000-0000-0000-ffffffffffff
X-GitHub-Event: push
X-Gitea-Delivery: ffffffff-0000-0000-0000-ffffffffffff
X-Gitea-Event: push
X-Gitea-Signature: 
X-Gogs-Delivery: ffffffff-0000-0000-0000-ffffffffffff
X-Gogs-Event: push
X-Gogs-Signature: 
Accept-Encoding: gzip

payload=[...]

Compared to application/json mode, where Content-Type is there:

POST / HTTP/1.1
Host: localhost:9090
User-Agent: Go-http-client/1.1
Content-Length: 2916
Content-Type: application/json
X-GitHub-Delivery: ffffffff-0000-0000-0000-ffffffffffff
X-GitHub-Event: push
X-Gitea-Delivery: ffffffff-0000-0000-0000-ffffffffffff
X-Gitea-Event: push
X-Gitea-Signature: 
X-Gogs-Delivery: ffffffff-0000-0000-0000-ffffffffffff
X-Gogs-Event: push
X-Gogs-Signature: 
Accept-Encoding: gzip

{
  "secret": [...]
@vszakats commented on GitHub (Oct 20, 2019): As of v1.9.4, the issue is still there. It seems that the `Content-Type: application/x-www-form-urlencoded` header is missing from the `POST` request. May be related to changing the http client from `GiteaServer` to `Go-http-client/1.1` between 1.8.3 and 1.9.x. Maybe the former set this by default, but the new client needs to have it set explicitly [UPDATE: Yes, confirmed, see PR]: ```http POST / HTTP/1.1 Host: localhost:9090 User-Agent: Go-http-client/1.1 Content-Length: 4224 X-GitHub-Delivery: ffffffff-0000-0000-0000-ffffffffffff X-GitHub-Event: push X-Gitea-Delivery: ffffffff-0000-0000-0000-ffffffffffff X-Gitea-Event: push X-Gitea-Signature: X-Gogs-Delivery: ffffffff-0000-0000-0000-ffffffffffff X-Gogs-Event: push X-Gogs-Signature: Accept-Encoding: gzip payload=[...] ``` Compared to `application/json` mode, where `Content-Type` is there: ```http POST / HTTP/1.1 Host: localhost:9090 User-Agent: Go-http-client/1.1 Content-Length: 2916 Content-Type: application/json X-GitHub-Delivery: ffffffff-0000-0000-0000-ffffffffffff X-GitHub-Event: push X-Gitea-Delivery: ffffffff-0000-0000-0000-ffffffffffff X-Gitea-Event: push X-Gitea-Signature: X-Gogs-Delivery: ffffffff-0000-0000-0000-ffffffffffff X-Gogs-Event: push X-Gogs-Signature: Accept-Encoding: gzip { "secret": [...] ```
Author
Owner

@vszakats commented on GitHub (Oct 20, 2019):

It looks like this is what happened. Issued a PR to fix it.

@vszakats commented on GitHub (Oct 20, 2019): It looks like this is what happened. Issued a PR to fix it.
Author
Owner

@adelowo commented on GitHub (Oct 20, 2019):

Can we close this issue?

@adelowo commented on GitHub (Oct 20, 2019): Can we close this issue?
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/gitea#3710