From 14b76120b43eab1deeae5a7c95821f60a75d5abc Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 1 May 2026 16:40:27 +0000 Subject: [PATCH] update webhook documentation (#393) Reviewed-on: https://gitea.com/gitea/docs/pulls/393 --- docs/usage/repository/webhooks.md | 816 +++++++++++++++--- .../current/usage/repository/webhooks.md | 807 ++++++++++++++--- .../version-1.25/usage/repository/webhooks.md | 807 ++++++++++++++--- .../version-1.26/usage/repository/webhooks.md | 807 ++++++++++++++--- .../current/usage/repository/webhooks.md | 807 ++++++++++++++--- .../version-1.25/usage/repository/webhooks.md | 807 ++++++++++++++--- .../version-1.26/usage/repository/webhooks.md | 807 ++++++++++++++--- .../version-1.25/usage/repository/webhooks.md | 816 +++++++++++++++--- .../version-1.26/usage/repository/webhooks.md | 816 +++++++++++++++--- 9 files changed, 6063 insertions(+), 1227 deletions(-) diff --git a/docs/usage/repository/webhooks.md b/docs/usage/repository/webhooks.md index c65e6e19..4a6e88c4 100644 --- a/docs/usage/repository/webhooks.md +++ b/docs/usage/repository/webhooks.md @@ -9,11 +9,26 @@ aliases: # Webhooks -Gitea supports webhooks for repository events. This can be configured in the settings -page `/:username/:reponame/settings/hooks` by a repository admin. Webhooks can also be configured on a per-organization and whole system basis. -All event pushes are POST requests. The methods currently supported are: +Gitea can send outbound webhooks for repository activity. Repository webhooks are +configured at `/:username/:reponame/settings/hooks` by a repository admin. +Equivalent webhook pages also exist for organizations, users, and system +administration. -- Gitea (can also be a GET request) +Webhook configuration is available at four scopes: + +- `Repository webhooks`: Trigger only for activity in one repository. +- `Organization webhooks`: Trigger for activity in repositories owned by that + organization. +- `User webhooks`: Trigger for activity in repositories owned by that user. +- `System webhooks`: Trigger for all eligible activity on the instance. + +Gitea also supports admin-defined `default webhooks`. These are not an extra +delivery scope. Instead, they are copied into newly created repositories and +then behave like ordinary repository webhooks. + +Gitea supports these outgoing webhook integrations: + +- Gitea - Gogs - Slack - Discord @@ -21,170 +36,697 @@ All event pushes are POST requests. The methods currently supported are: - Telegram - Microsoft Teams - Feishu +- Matrix - Wechatwork - Packagist -### Event information +The `Gitea` and `Gogs` webhook types send generic webhook payloads. The chat and +service integrations listed above transform the same internal event into a +service-specific request body. -:::warning -The `secret` field in the payload is deprecated as of Gitea 1.13.0 and will be removed in 1.14.0: https://github.com/go-gitea/gitea/issues/11755 +## Configuration + +This section covers the webhook settings you choose when creating or editing a +webhook. + +### Configuring a webhook + +When creating a webhook, the main options are: + +- `Target URL`: The endpoint that receives the delivery. +- `HTTP Method`: Usually `POST` for generic webhooks. +- `POST Content Type`: `application/json` or + `application/x-www-form-urlencoded` for generic webhooks. +- `Secret`: Used to sign the raw request body with HMAC. +- `Authorization Header`: Optional custom `Authorization` header to send with + each request. +- `Branch Filter`: Optional glob filter for branch and tag related events. +- `Trigger On`: `Push Events`, `All Events`, or a custom event selection. +- `Active`: Whether the webhook is enabled. + +:::note +Older examples may still show a `secret` field inside the JSON payload. Current +Gitea versions do not send the webhook secret in the payload body. Always verify +the request by checking the signature headers instead. ::: -The following is an example of event information that will be sent by Gitea to -a Payload URL: +### Branch filters + +The branch filter uses glob syntax compatible with +[`github.com/gobwas/glob`](https://pkg.go.dev/github.com/gobwas/glob#Compile). + +- Empty, `*`, or `**` matches everything. +- A plain branch name such as `main` matches that branch. +- Full refs such as `refs/tags/v*` are also supported. +- Brace expressions such as `{main,release/*}` are supported. +- The filter only applies to events that carry a git ref, such as `create`, + `delete`, and `push`. +- Events without a ref, such as issues or releases, ignore the branch filter. + +Examples: + +- `main` +- `{main,feature/*}` +- `{refs/heads/feature/*,refs/tags/release/*}` + +### Authorization header + +Gitea can be configured to send a custom +[Authorization header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization) +with each webhook delivery. This is independent from the webhook secret: + +- Use the secret to verify integrity with HMAC. +- Use the `Authorization` header when the receiving endpoint requires + application-level authentication. + +## Delivery + +This section describes how Gitea sends webhook deliveries and how receivers can +identify and verify them. + +### Delivery behavior + +- Webhooks are delivered asynchronously over HTTP. +- Generic `Gitea` and `Gogs` webhooks support `POST` and `GET`; `POST` is the + normal choice. +- For `POST` requests, the payload can be sent either as JSON + (`application/json`) or as a form field named `payload` + (`application/x-www-form-urlencoded`). +- Provider-specific integrations may use the HTTP method and body format + required by that provider. + +### Delivery headers + +Every delivery includes a unique delivery ID and event headers. For +GitHub-compatible integrations, Gitea also sends the corresponding GitHub and +Gogs header names. + +| Header | Description | +| --- | --- | +| `X-Gitea-Delivery` | Unique delivery UUID for this attempt. | +| `X-Gitea-Event` | Normalized event name, such as `push`, `issues`, or `pull_request`. | +| `X-Gitea-Event-Type` | More specific event type, such as `issue_assign` or `pull_request_review_comment`. | +| `X-Gitea-Signature` | Hex-encoded HMAC-SHA256 of the raw request body, without a prefix. | +| `X-Gitea-Hook-Installation-Target-Type` | Where the webhook is defined: typically `repository`, `organization`, `user`, or `system`. Default webhooks are copied into repositories before delivery, so they are typically delivered as `repository`. | +| `X-Gogs-Delivery`, `X-Gogs-Event`, `X-Gogs-Event-Type`, `X-Gogs-Signature` | Compatibility headers with the same values as the Gitea variants. | +| `X-GitHub-Delivery`, `X-GitHub-Event`, `X-GitHub-Event-Type` | GitHub-style compatibility headers. | +| `X-GitHub-Hook-Installation-Target-Type` | GitHub-style compatibility header for the webhook scope. | +| `X-Hub-Signature` | GitHub-compatible HMAC-SHA1 header in the form `sha1=`. | +| `X-Hub-Signature-256` | GitHub-compatible HMAC-SHA256 header in the form `sha256=`. | + +If no secret is configured, the signature headers are still present, but their +digest values are empty. + +#### `Event` versus `Event-Type` + +Some Gitea webhook subscriptions are grouped together under one normalized event +name. For example, an issue assignment delivery uses the issue event group: ```http -X-GitHub-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 -X-GitHub-Event: push -X-Gogs-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 -X-Gogs-Event: push -X-Gitea-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 -X-Gitea-Event: push +X-Gitea-Event: issues +X-Gitea-Event-Type: issue_assign +X-GitHub-Event: issues +X-GitHub-Event-Type: issue_assign ``` -```json -{ - "secret": "3gEsCfjlV2ugRwgpU#w1*WaW*wa4NXgGmpCfkbG3", - "ref": "refs/heads/develop", - "before": "28e1879d029cb852e4844d9c718537df08844e03", - "after": "bffeb74224043ba2feb48d137756c8a9331c449a", - "compare_url": "http://localhost:3000/gitea/webhooks/compare/28e1879d029cb852e4844d9c718537df08844e03...bffeb74224043ba2feb48d137756c8a9331c449a", - "commits": [ - { - "id": "bffeb74224043ba2feb48d137756c8a9331c449a", - "message": "Webhooks Yay!", - "url": "http://localhost:3000/gitea/webhooks/commit/bffeb74224043ba2feb48d137756c8a9331c449a", - "author": { - "name": "Gitea", - "email": "someone@gitea.io", - "username": "gitea" - }, - "committer": { - "name": "Gitea", - "email": "someone@gitea.io", - "username": "gitea" - }, - "timestamp": "2017-03-13T13:52:11-04:00" - } - ], - "repository": { - "id": 140, - "owner": { - "id": 1, - "login": "gitea", - "full_name": "Gitea", - "email": "someone@gitea.io", - "avatar_url": "https://localhost:3000/avatars/1", - "username": "gitea" - }, - "name": "webhooks", - "full_name": "gitea/webhooks", - "description": "", - "private": false, - "fork": false, - "html_url": "http://localhost:3000/gitea/webhooks", - "ssh_url": "ssh://gitea@localhost:2222/gitea/webhooks.git", - "clone_url": "http://localhost:3000/gitea/webhooks.git", - "website": "", - "stars_count": 0, - "forks_count": 1, - "watchers_count": 1, - "open_issues_count": 7, - "default_branch": "master", - "created_at": "2017-02-26T04:29:06-05:00", - "updated_at": "2017-03-13T13:51:58-04:00" - }, - "pusher": { - "id": 1, - "login": "gitea", - "full_name": "Gitea", - "email": "someone@gitea.io", - "avatar_url": "https://localhost:3000/avatars/1", - "username": "gitea" - }, - "sender": { - "id": 1, - "login": "gitea", - "full_name": "Gitea", - "email": "someone@gitea.io", - "avatar_url": "https://localhost:3000/avatars/1", - "username": "gitea" - } -} -``` +Use `X-Gitea-Event-Type` when you need the exact trigger that fired the webhook. -### Example +#### Validating deliveries -This is an example of how to use webhooks to run a php script upon push requests to the repository. -In your repository Settings, under Webhooks, Setup a Gitea webhook as follows: +Gitea signs the raw request body with your webhook secret. To validate a +delivery: -- Target URL: http://mydomain.com/webhook.php -- HTTP Method: POST -- POST Content Type: application/json -- Secret: 123 -- Trigger On: Push Events -- Active: Checked +1. Read the request body exactly as it was received. +2. Compute the HMAC-SHA256 digest with your webhook secret. +3. Compare the result with `X-Gitea-Signature` or with the GitHub-compatible + `X-Hub-Signature-256` header. +4. Use a constant-time comparison when possible. -Now on your server create the php file webhook.php +Important details: + +- `X-Gitea-Signature` contains only the lowercase hexadecimal SHA-256 digest. +- `X-Hub-Signature-256` contains the same digest with a `sha256=` prefix. +- `X-Hub-Signature` is also sent for compatibility and uses SHA-1. +- The body must be verified before JSON parsing or any other modification. + +##### PHP example + +The following example verifies a generic `Gitea` webhook sent as +`application/json`. ```php `。 | +| `X-Hub-Signature-256` | GitHub 兼容的 HMAC-SHA256 请求头,格式为 `sha256=`。 | + +如果未配置密钥,签名请求头仍然会存在,但摘要值为空。 + +#### `Event` 与 `Event-Type` + +某些 Gitea Webhook 订阅会被归类到同一个规范化事件名下。例如,issue 指派 +投递会归类到 issue 事件组: ```http -X-GitHub-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 -X-GitHub-Event: push -X-Gogs-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 -X-Gogs-Event: push -X-Gitea-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 -X-Gitea-Event: push +X-Gitea-Event: issues +X-Gitea-Event-Type: issue_assign +X-GitHub-Event: issues +X-GitHub-Event-Type: issue_assign ``` -```json -{ - "secret": "3gEsCfjlV2ugRwgpU#w1*WaW*wa4NXgGmpCfkbG3", - "ref": "refs/heads/develop", - "before": "28e1879d029cb852e4844d9c718537df08844e03", - "after": "bffeb74224043ba2feb48d137756c8a9331c449a", - "compare_url": "http://localhost:3000/gitea/webhooks/compare/28e1879d029cb852e4844d9c718537df08844e03...bffeb74224043ba2feb48d137756c8a9331c449a", - "commits": [ - { - "id": "bffeb74224043ba2feb48d137756c8a9331c449a", - "message": "Webhooks Yay!", - "url": "http://localhost:3000/gitea/webhooks/commit/bffeb74224043ba2feb48d137756c8a9331c449a", - "author": { - "name": "Gitea", - "email": "someone@gitea.io", - "username": "gitea" - }, - "committer": { - "name": "Gitea", - "email": "someone@gitea.io", - "username": "gitea" - }, - "timestamp": "2017-03-13T13:52:11-04:00" - } - ], - "repository": { - "id": 140, - "owner": { - "id": 1, - "login": "gitea", - "full_name": "Gitea", - "email": "someone@gitea.io", - "avatar_url": "https://localhost:3000/avatars/1", - "username": "gitea" - }, - "name": "webhooks", - "full_name": "gitea/webhooks", - "description": "", - "private": false, - "fork": false, - "html_url": "http://localhost:3000/gitea/webhooks", - "ssh_url": "ssh://gitea@localhost:2222/gitea/webhooks.git", - "clone_url": "http://localhost:3000/gitea/webhooks.git", - "website": "", - "stars_count": 0, - "forks_count": 1, - "watchers_count": 1, - "open_issues_count": 7, - "default_branch": "master", - "created_at": "2017-02-26T04:29:06-05:00", - "updated_at": "2017-03-13T13:51:58-04:00" - }, - "pusher": { - "id": 1, - "login": "gitea", - "full_name": "Gitea", - "email": "someone@gitea.io", - "avatar_url": "https://localhost:3000/avatars/1", - "username": "gitea" - }, - "sender": { - "id": 1, - "login": "gitea", - "full_name": "Gitea", - "email": "someone@gitea.io", - "avatar_url": "https://localhost:3000/avatars/1", - "username": "gitea" - } -} -``` +如果你需要知道真正触发投递的具体事件类型,请使用 `X-Gitea-Event-Type`。 -### 示例 +#### 校验投递 -这是一个示例,演示如何使用 Webhooks 在推送请求到达仓库时运行一个 php 脚本。 -在你的仓库设置中,在 Webhooks 下,设置一个如下的 Gitea webhook: +Gitea 会使用你的 Webhook 密钥对原始请求体进行签名。要校验一次投递: -- 目标 URL:http://mydomain.com/webhook.php -- HTTP 方法:POST -- POST Content Type:application/json -- Secret:123 -- 触发条件:推送事件 -- 激活:勾选 +1. 按接收到的原始内容读取请求体。 +2. 使用 Webhook 密钥计算 HMAC-SHA256 摘要。 +3. 将结果与 `X-Gitea-Signature` 或 GitHub 兼容的 + `X-Hub-Signature-256` 进行比较。 +4. 尽量使用常量时间比较函数。 -现在在你的服务器上创建 php 文件 webhook.php。 +注意事项: + +- `X-Gitea-Signature` 仅包含小写十六进制的 SHA-256 摘要。 +- `X-Hub-Signature-256` 使用相同摘要,但带有 `sha256=` 前缀。 +- `X-Hub-Signature` 也会出于兼容性目的发送,其算法是 SHA-1。 +- 在完成签名校验之前,不应先解析 JSON 或修改请求体。 + +##### PHP 示例 + +下面的示例演示如何校验以 `application/json` 发送的通用 `Gitea` Webhook。 ```php `。 | +| `X-Hub-Signature-256` | GitHub 兼容的 HMAC-SHA256 请求头,格式为 `sha256=`。 | + +如果未配置密钥,签名请求头仍然会存在,但摘要值为空。 + +#### `Event` 与 `Event-Type` + +某些 Gitea Webhook 订阅会被归类到同一个规范化事件名下。例如,issue 指派 +投递会归类到 issue 事件组: ```http -X-GitHub-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 -X-GitHub-Event: push -X-Gogs-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 -X-Gogs-Event: push -X-Gitea-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 -X-Gitea-Event: push +X-Gitea-Event: issues +X-Gitea-Event-Type: issue_assign +X-GitHub-Event: issues +X-GitHub-Event-Type: issue_assign ``` -```json -{ - "secret": "3gEsCfjlV2ugRwgpU#w1*WaW*wa4NXgGmpCfkbG3", - "ref": "refs/heads/develop", - "before": "28e1879d029cb852e4844d9c718537df08844e03", - "after": "bffeb74224043ba2feb48d137756c8a9331c449a", - "compare_url": "http://localhost:3000/gitea/webhooks/compare/28e1879d029cb852e4844d9c718537df08844e03...bffeb74224043ba2feb48d137756c8a9331c449a", - "commits": [ - { - "id": "bffeb74224043ba2feb48d137756c8a9331c449a", - "message": "Webhooks Yay!", - "url": "http://localhost:3000/gitea/webhooks/commit/bffeb74224043ba2feb48d137756c8a9331c449a", - "author": { - "name": "Gitea", - "email": "someone@gitea.io", - "username": "gitea" - }, - "committer": { - "name": "Gitea", - "email": "someone@gitea.io", - "username": "gitea" - }, - "timestamp": "2017-03-13T13:52:11-04:00" - } - ], - "repository": { - "id": 140, - "owner": { - "id": 1, - "login": "gitea", - "full_name": "Gitea", - "email": "someone@gitea.io", - "avatar_url": "https://localhost:3000/avatars/1", - "username": "gitea" - }, - "name": "webhooks", - "full_name": "gitea/webhooks", - "description": "", - "private": false, - "fork": false, - "html_url": "http://localhost:3000/gitea/webhooks", - "ssh_url": "ssh://gitea@localhost:2222/gitea/webhooks.git", - "clone_url": "http://localhost:3000/gitea/webhooks.git", - "website": "", - "stars_count": 0, - "forks_count": 1, - "watchers_count": 1, - "open_issues_count": 7, - "default_branch": "master", - "created_at": "2017-02-26T04:29:06-05:00", - "updated_at": "2017-03-13T13:51:58-04:00" - }, - "pusher": { - "id": 1, - "login": "gitea", - "full_name": "Gitea", - "email": "someone@gitea.io", - "avatar_url": "https://localhost:3000/avatars/1", - "username": "gitea" - }, - "sender": { - "id": 1, - "login": "gitea", - "full_name": "Gitea", - "email": "someone@gitea.io", - "avatar_url": "https://localhost:3000/avatars/1", - "username": "gitea" - } -} -``` +如果你需要知道真正触发投递的具体事件类型,请使用 `X-Gitea-Event-Type`。 -### 示例 +#### 校验投递 -这是一个示例,演示如何使用 Webhooks 在推送请求到达仓库时运行一个 php 脚本。 -在你的仓库设置中,在 Webhooks 下,设置一个如下的 Gitea webhook: +Gitea 会使用你的 Webhook 密钥对原始请求体进行签名。要校验一次投递: -- 目标 URL:http://mydomain.com/webhook.php -- HTTP 方法:POST -- POST Content Type:application/json -- Secret:123 -- 触发条件:推送事件 -- 激活:勾选 +1. 按接收到的原始内容读取请求体。 +2. 使用 Webhook 密钥计算 HMAC-SHA256 摘要。 +3. 将结果与 `X-Gitea-Signature` 或 GitHub 兼容的 + `X-Hub-Signature-256` 进行比较。 +4. 尽量使用常量时间比较函数。 -现在在你的服务器上创建 php 文件 webhook.php。 +注意事项: + +- `X-Gitea-Signature` 仅包含小写十六进制的 SHA-256 摘要。 +- `X-Hub-Signature-256` 使用相同摘要,但带有 `sha256=` 前缀。 +- `X-Hub-Signature` 也会出于兼容性目的发送,其算法是 SHA-1。 +- 在完成签名校验之前,不应先解析 JSON 或修改请求体。 + +##### PHP 示例 + +下面的示例演示如何校验以 `application/json` 发送的通用 `Gitea` Webhook。 ```php `。 | +| `X-Hub-Signature-256` | GitHub 兼容的 HMAC-SHA256 请求头,格式为 `sha256=`。 | + +如果未配置密钥,签名请求头仍然会存在,但摘要值为空。 + +#### `Event` 与 `Event-Type` + +某些 Gitea Webhook 订阅会被归类到同一个规范化事件名下。例如,issue 指派 +投递会归类到 issue 事件组: ```http -X-GitHub-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 -X-GitHub-Event: push -X-Gogs-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 -X-Gogs-Event: push -X-Gitea-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 -X-Gitea-Event: push +X-Gitea-Event: issues +X-Gitea-Event-Type: issue_assign +X-GitHub-Event: issues +X-GitHub-Event-Type: issue_assign ``` -```json -{ - "secret": "3gEsCfjlV2ugRwgpU#w1*WaW*wa4NXgGmpCfkbG3", - "ref": "refs/heads/develop", - "before": "28e1879d029cb852e4844d9c718537df08844e03", - "after": "bffeb74224043ba2feb48d137756c8a9331c449a", - "compare_url": "http://localhost:3000/gitea/webhooks/compare/28e1879d029cb852e4844d9c718537df08844e03...bffeb74224043ba2feb48d137756c8a9331c449a", - "commits": [ - { - "id": "bffeb74224043ba2feb48d137756c8a9331c449a", - "message": "Webhooks Yay!", - "url": "http://localhost:3000/gitea/webhooks/commit/bffeb74224043ba2feb48d137756c8a9331c449a", - "author": { - "name": "Gitea", - "email": "someone@gitea.io", - "username": "gitea" - }, - "committer": { - "name": "Gitea", - "email": "someone@gitea.io", - "username": "gitea" - }, - "timestamp": "2017-03-13T13:52:11-04:00" - } - ], - "repository": { - "id": 140, - "owner": { - "id": 1, - "login": "gitea", - "full_name": "Gitea", - "email": "someone@gitea.io", - "avatar_url": "https://localhost:3000/avatars/1", - "username": "gitea" - }, - "name": "webhooks", - "full_name": "gitea/webhooks", - "description": "", - "private": false, - "fork": false, - "html_url": "http://localhost:3000/gitea/webhooks", - "ssh_url": "ssh://gitea@localhost:2222/gitea/webhooks.git", - "clone_url": "http://localhost:3000/gitea/webhooks.git", - "website": "", - "stars_count": 0, - "forks_count": 1, - "watchers_count": 1, - "open_issues_count": 7, - "default_branch": "master", - "created_at": "2017-02-26T04:29:06-05:00", - "updated_at": "2017-03-13T13:51:58-04:00" - }, - "pusher": { - "id": 1, - "login": "gitea", - "full_name": "Gitea", - "email": "someone@gitea.io", - "avatar_url": "https://localhost:3000/avatars/1", - "username": "gitea" - }, - "sender": { - "id": 1, - "login": "gitea", - "full_name": "Gitea", - "email": "someone@gitea.io", - "avatar_url": "https://localhost:3000/avatars/1", - "username": "gitea" - } -} -``` +如果你需要知道真正触发投递的具体事件类型,请使用 `X-Gitea-Event-Type`。 -### 示例 +#### 校验投递 -这是一个示例,演示如何使用 Webhooks 在推送请求到达仓库时运行一个 php 脚本。 -在你的仓库设置中,在 Webhooks 下,设置一个如下的 Gitea webhook: +Gitea 会使用你的 Webhook 密钥对原始请求体进行签名。要校验一次投递: -- 目标 URL:http://mydomain.com/webhook.php -- HTTP 方法:POST -- POST Content Type:application/json -- Secret:123 -- 触发条件:推送事件 -- 激活:勾选 +1. 按接收到的原始内容读取请求体。 +2. 使用 Webhook 密钥计算 HMAC-SHA256 摘要。 +3. 将结果与 `X-Gitea-Signature` 或 GitHub 兼容的 + `X-Hub-Signature-256` 进行比较。 +4. 尽量使用常量时间比较函数。 -现在在你的服务器上创建 php 文件 webhook.php。 +注意事项: + +- `X-Gitea-Signature` 仅包含小写十六进制的 SHA-256 摘要。 +- `X-Hub-Signature-256` 使用相同摘要,但带有 `sha256=` 前缀。 +- `X-Hub-Signature` 也会出于兼容性目的发送,其算法是 SHA-1。 +- 在完成签名校验之前,不应先解析 JSON 或修改请求体。 + +##### PHP 示例 + +下面的示例演示如何校验以 `application/json` 发送的通用 `Gitea` Webhook。 ```php `。 | +| `X-Hub-Signature-256` | GitHub 相容的 HMAC-SHA256 標頭,格式為 `sha256=`。 | + +如果未設定密鑰,簽章標頭仍然會存在,但摘要值為空。 + +#### `Event` 與 `Event-Type` + +某些 Gitea Webhook 訂閱會被歸類到同一個規範化事件名稱下。例如,issue 指派 +投遞會歸類到 issue 事件群組: ```http -X-GitHub-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 -X-GitHub-Event: push -X-Gogs-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 -X-Gogs-Event: push -X-Gitea-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 -X-Gitea-Event: push +X-Gitea-Event: issues +X-Gitea-Event-Type: issue_assign +X-GitHub-Event: issues +X-GitHub-Event-Type: issue_assign ``` -```json -{ - "secret": "3gEsCfjlV2ugRwgpU#w1*WaW*wa4NXgGmpCfkbG3", - "ref": "refs/heads/develop", - "before": "28e1879d029cb852e4844d9c718537df08844e03", - "after": "bffeb74224043ba2feb48d137756c8a9331c449a", - "compare_url": "http://localhost:3000/gitea/webhooks/compare/28e1879d029cb852e4844d9c718537df08844e03...bffeb74224043ba2feb48d137756c8a9331c449a", - "commits": [ - { - "id": "bffeb74224043ba2feb48d137756c8a9331c449a", - "message": "Webhooks Yay!", - "url": "http://localhost:3000/gitea/webhooks/commit/bffeb74224043ba2feb48d137756c8a9331c449a", - "author": { - "name": "Gitea", - "email": "someone@gitea.io", - "username": "gitea" - }, - "committer": { - "name": "Gitea", - "email": "someone@gitea.io", - "username": "gitea" - }, - "timestamp": "2017-03-13T13:52:11-04:00" - } - ], - "repository": { - "id": 140, - "owner": { - "id": 1, - "login": "gitea", - "full_name": "Gitea", - "email": "someone@gitea.io", - "avatar_url": "https://localhost:3000/avatars/1", - "username": "gitea" - }, - "name": "webhooks", - "full_name": "gitea/webhooks", - "description": "", - "private": false, - "fork": false, - "html_url": "http://localhost:3000/gitea/webhooks", - "ssh_url": "ssh://gitea@localhost:2222/gitea/webhooks.git", - "clone_url": "http://localhost:3000/gitea/webhooks.git", - "website": "", - "stars_count": 0, - "forks_count": 1, - "watchers_count": 1, - "open_issues_count": 7, - "default_branch": "master", - "created_at": "2017-02-26T04:29:06-05:00", - "updated_at": "2017-03-13T13:51:58-04:00" - }, - "pusher": { - "id": 1, - "login": "gitea", - "full_name": "Gitea", - "email": "someone@gitea.io", - "avatar_url": "https://localhost:3000/avatars/1", - "username": "gitea" - }, - "sender": { - "id": 1, - "login": "gitea", - "full_name": "Gitea", - "email": "someone@gitea.io", - "avatar_url": "https://localhost:3000/avatars/1", - "username": "gitea" - } -} -``` +如果你需要知道實際觸發投遞的具體事件類型,請使用 `X-Gitea-Event-Type`。 -### 示例 +#### 驗證投遞 -这是一个示例,演示如何使用 Webhooks 在推送请求到达仓库时运行一个 php 脚本。 -在你的仓库设置中,在 Webhooks 下,设置一个如下的 Gitea webhook: +Gitea 會使用你的 Webhook 密鑰對原始請求主體進行簽章。要驗證一次投遞: -- 目标 URL:http://mydomain.com/webhook.php -- HTTP 方法:POST -- POST Content Type:application/json -- Secret:123 -- 触发条件:推送事件 -- 激活:勾选 +1. 以接收到的原始內容讀取請求主體。 +2. 使用 Webhook 密鑰計算 HMAC-SHA256 摘要。 +3. 將結果與 `X-Gitea-Signature` 或 GitHub 相容的 + `X-Hub-Signature-256` 進行比較。 +4. 盡量使用常數時間比較函式。 -现在在你的服务器上创建 php 文件 webhook.php。 +注意事項: + +- `X-Gitea-Signature` 只包含小寫十六進位的 SHA-256 摘要。 +- `X-Hub-Signature-256` 使用相同摘要,但帶有 `sha256=` 前綴。 +- `X-Hub-Signature` 也會為了相容性而送出,其演算法為 SHA-1。 +- 在完成簽章驗證之前,不應先解析 JSON 或修改請求主體。 + +##### PHP 範例 + +下面的範例示範如何驗證以 `application/json` 送出的通用 `Gitea` Webhook。 ```php `。 | +| `X-Hub-Signature-256` | GitHub 相容的 HMAC-SHA256 標頭,格式為 `sha256=`。 | + +如果未設定密鑰,簽章標頭仍然會存在,但摘要值為空。 + +#### `Event` 與 `Event-Type` + +某些 Gitea Webhook 訂閱會被歸類到同一個規範化事件名稱下。例如,issue 指派 +投遞會歸類到 issue 事件群組: ```http -X-GitHub-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 -X-GitHub-Event: push -X-Gogs-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 -X-Gogs-Event: push -X-Gitea-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 -X-Gitea-Event: push +X-Gitea-Event: issues +X-Gitea-Event-Type: issue_assign +X-GitHub-Event: issues +X-GitHub-Event-Type: issue_assign ``` -```json -{ - "secret": "3gEsCfjlV2ugRwgpU#w1*WaW*wa4NXgGmpCfkbG3", - "ref": "refs/heads/develop", - "before": "28e1879d029cb852e4844d9c718537df08844e03", - "after": "bffeb74224043ba2feb48d137756c8a9331c449a", - "compare_url": "http://localhost:3000/gitea/webhooks/compare/28e1879d029cb852e4844d9c718537df08844e03...bffeb74224043ba2feb48d137756c8a9331c449a", - "commits": [ - { - "id": "bffeb74224043ba2feb48d137756c8a9331c449a", - "message": "Webhooks Yay!", - "url": "http://localhost:3000/gitea/webhooks/commit/bffeb74224043ba2feb48d137756c8a9331c449a", - "author": { - "name": "Gitea", - "email": "someone@gitea.io", - "username": "gitea" - }, - "committer": { - "name": "Gitea", - "email": "someone@gitea.io", - "username": "gitea" - }, - "timestamp": "2017-03-13T13:52:11-04:00" - } - ], - "repository": { - "id": 140, - "owner": { - "id": 1, - "login": "gitea", - "full_name": "Gitea", - "email": "someone@gitea.io", - "avatar_url": "https://localhost:3000/avatars/1", - "username": "gitea" - }, - "name": "webhooks", - "full_name": "gitea/webhooks", - "description": "", - "private": false, - "fork": false, - "html_url": "http://localhost:3000/gitea/webhooks", - "ssh_url": "ssh://gitea@localhost:2222/gitea/webhooks.git", - "clone_url": "http://localhost:3000/gitea/webhooks.git", - "website": "", - "stars_count": 0, - "forks_count": 1, - "watchers_count": 1, - "open_issues_count": 7, - "default_branch": "master", - "created_at": "2017-02-26T04:29:06-05:00", - "updated_at": "2017-03-13T13:51:58-04:00" - }, - "pusher": { - "id": 1, - "login": "gitea", - "full_name": "Gitea", - "email": "someone@gitea.io", - "avatar_url": "https://localhost:3000/avatars/1", - "username": "gitea" - }, - "sender": { - "id": 1, - "login": "gitea", - "full_name": "Gitea", - "email": "someone@gitea.io", - "avatar_url": "https://localhost:3000/avatars/1", - "username": "gitea" - } -} -``` +如果你需要知道實際觸發投遞的具體事件類型,請使用 `X-Gitea-Event-Type`。 -### 示例 +#### 驗證投遞 -这是一个示例,演示如何使用 Webhooks 在推送请求到达仓库时运行一个 php 脚本。 -在你的仓库设置中,在 Webhooks 下,设置一个如下的 Gitea webhook: +Gitea 會使用你的 Webhook 密鑰對原始請求主體進行簽章。要驗證一次投遞: -- 目标 URL:http://mydomain.com/webhook.php -- HTTP 方法:POST -- POST Content Type:application/json -- Secret:123 -- 触发条件:推送事件 -- 激活:勾选 +1. 以接收到的原始內容讀取請求主體。 +2. 使用 Webhook 密鑰計算 HMAC-SHA256 摘要。 +3. 將結果與 `X-Gitea-Signature` 或 GitHub 相容的 + `X-Hub-Signature-256` 進行比較。 +4. 盡量使用常數時間比較函式。 -现在在你的服务器上创建 php 文件 webhook.php。 +注意事項: + +- `X-Gitea-Signature` 只包含小寫十六進位的 SHA-256 摘要。 +- `X-Hub-Signature-256` 使用相同摘要,但帶有 `sha256=` 前綴。 +- `X-Hub-Signature` 也會為了相容性而送出,其演算法為 SHA-1。 +- 在完成簽章驗證之前,不應先解析 JSON 或修改請求主體。 + +##### PHP 範例 + +下面的範例示範如何驗證以 `application/json` 送出的通用 `Gitea` Webhook。 ```php `。 | +| `X-Hub-Signature-256` | GitHub 相容的 HMAC-SHA256 標頭,格式為 `sha256=`。 | + +如果未設定密鑰,簽章標頭仍然會存在,但摘要值為空。 + +#### `Event` 與 `Event-Type` + +某些 Gitea Webhook 訂閱會被歸類到同一個規範化事件名稱下。例如,issue 指派 +投遞會歸類到 issue 事件群組: ```http -X-GitHub-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 -X-GitHub-Event: push -X-Gogs-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 -X-Gogs-Event: push -X-Gitea-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 -X-Gitea-Event: push +X-Gitea-Event: issues +X-Gitea-Event-Type: issue_assign +X-GitHub-Event: issues +X-GitHub-Event-Type: issue_assign ``` -```json -{ - "secret": "3gEsCfjlV2ugRwgpU#w1*WaW*wa4NXgGmpCfkbG3", - "ref": "refs/heads/develop", - "before": "28e1879d029cb852e4844d9c718537df08844e03", - "after": "bffeb74224043ba2feb48d137756c8a9331c449a", - "compare_url": "http://localhost:3000/gitea/webhooks/compare/28e1879d029cb852e4844d9c718537df08844e03...bffeb74224043ba2feb48d137756c8a9331c449a", - "commits": [ - { - "id": "bffeb74224043ba2feb48d137756c8a9331c449a", - "message": "Webhooks Yay!", - "url": "http://localhost:3000/gitea/webhooks/commit/bffeb74224043ba2feb48d137756c8a9331c449a", - "author": { - "name": "Gitea", - "email": "someone@gitea.io", - "username": "gitea" - }, - "committer": { - "name": "Gitea", - "email": "someone@gitea.io", - "username": "gitea" - }, - "timestamp": "2017-03-13T13:52:11-04:00" - } - ], - "repository": { - "id": 140, - "owner": { - "id": 1, - "login": "gitea", - "full_name": "Gitea", - "email": "someone@gitea.io", - "avatar_url": "https://localhost:3000/avatars/1", - "username": "gitea" - }, - "name": "webhooks", - "full_name": "gitea/webhooks", - "description": "", - "private": false, - "fork": false, - "html_url": "http://localhost:3000/gitea/webhooks", - "ssh_url": "ssh://gitea@localhost:2222/gitea/webhooks.git", - "clone_url": "http://localhost:3000/gitea/webhooks.git", - "website": "", - "stars_count": 0, - "forks_count": 1, - "watchers_count": 1, - "open_issues_count": 7, - "default_branch": "master", - "created_at": "2017-02-26T04:29:06-05:00", - "updated_at": "2017-03-13T13:51:58-04:00" - }, - "pusher": { - "id": 1, - "login": "gitea", - "full_name": "Gitea", - "email": "someone@gitea.io", - "avatar_url": "https://localhost:3000/avatars/1", - "username": "gitea" - }, - "sender": { - "id": 1, - "login": "gitea", - "full_name": "Gitea", - "email": "someone@gitea.io", - "avatar_url": "https://localhost:3000/avatars/1", - "username": "gitea" - } -} -``` +如果你需要知道實際觸發投遞的具體事件類型,請使用 `X-Gitea-Event-Type`。 -### 示例 +#### 驗證投遞 -这是一个示例,演示如何使用 Webhooks 在推送请求到达仓库时运行一个 php 脚本。 -在你的仓库设置中,在 Webhooks 下,设置一个如下的 Gitea webhook: +Gitea 會使用你的 Webhook 密鑰對原始請求主體進行簽章。要驗證一次投遞: -- 目标 URL:http://mydomain.com/webhook.php -- HTTP 方法:POST -- POST Content Type:application/json -- Secret:123 -- 触发条件:推送事件 -- 激活:勾选 +1. 以接收到的原始內容讀取請求主體。 +2. 使用 Webhook 密鑰計算 HMAC-SHA256 摘要。 +3. 將結果與 `X-Gitea-Signature` 或 GitHub 相容的 + `X-Hub-Signature-256` 進行比較。 +4. 盡量使用常數時間比較函式。 -现在在你的服务器上创建 php 文件 webhook.php。 +注意事項: + +- `X-Gitea-Signature` 只包含小寫十六進位的 SHA-256 摘要。 +- `X-Hub-Signature-256` 使用相同摘要,但帶有 `sha256=` 前綴。 +- `X-Hub-Signature` 也會為了相容性而送出,其演算法為 SHA-1。 +- 在完成簽章驗證之前,不應先解析 JSON 或修改請求主體。 + +##### PHP 範例 + +下面的範例示範如何驗證以 `application/json` 送出的通用 `Gitea` Webhook。 ```php `. | +| `X-Hub-Signature-256` | GitHub-compatible HMAC-SHA256 header in the form `sha256=`. | + +If no secret is configured, the signature headers are still present, but their +digest values are empty. + +#### `Event` versus `Event-Type` + +Some Gitea webhook subscriptions are grouped together under one normalized event +name. For example, an issue assignment delivery uses the issue event group: ```http -X-GitHub-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 -X-GitHub-Event: push -X-Gogs-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 -X-Gogs-Event: push -X-Gitea-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 -X-Gitea-Event: push +X-Gitea-Event: issues +X-Gitea-Event-Type: issue_assign +X-GitHub-Event: issues +X-GitHub-Event-Type: issue_assign ``` -```json -{ - "secret": "3gEsCfjlV2ugRwgpU#w1*WaW*wa4NXgGmpCfkbG3", - "ref": "refs/heads/develop", - "before": "28e1879d029cb852e4844d9c718537df08844e03", - "after": "bffeb74224043ba2feb48d137756c8a9331c449a", - "compare_url": "http://localhost:3000/gitea/webhooks/compare/28e1879d029cb852e4844d9c718537df08844e03...bffeb74224043ba2feb48d137756c8a9331c449a", - "commits": [ - { - "id": "bffeb74224043ba2feb48d137756c8a9331c449a", - "message": "Webhooks Yay!", - "url": "http://localhost:3000/gitea/webhooks/commit/bffeb74224043ba2feb48d137756c8a9331c449a", - "author": { - "name": "Gitea", - "email": "someone@gitea.io", - "username": "gitea" - }, - "committer": { - "name": "Gitea", - "email": "someone@gitea.io", - "username": "gitea" - }, - "timestamp": "2017-03-13T13:52:11-04:00" - } - ], - "repository": { - "id": 140, - "owner": { - "id": 1, - "login": "gitea", - "full_name": "Gitea", - "email": "someone@gitea.io", - "avatar_url": "https://localhost:3000/avatars/1", - "username": "gitea" - }, - "name": "webhooks", - "full_name": "gitea/webhooks", - "description": "", - "private": false, - "fork": false, - "html_url": "http://localhost:3000/gitea/webhooks", - "ssh_url": "ssh://gitea@localhost:2222/gitea/webhooks.git", - "clone_url": "http://localhost:3000/gitea/webhooks.git", - "website": "", - "stars_count": 0, - "forks_count": 1, - "watchers_count": 1, - "open_issues_count": 7, - "default_branch": "master", - "created_at": "2017-02-26T04:29:06-05:00", - "updated_at": "2017-03-13T13:51:58-04:00" - }, - "pusher": { - "id": 1, - "login": "gitea", - "full_name": "Gitea", - "email": "someone@gitea.io", - "avatar_url": "https://localhost:3000/avatars/1", - "username": "gitea" - }, - "sender": { - "id": 1, - "login": "gitea", - "full_name": "Gitea", - "email": "someone@gitea.io", - "avatar_url": "https://localhost:3000/avatars/1", - "username": "gitea" - } -} -``` +Use `X-Gitea-Event-Type` when you need the exact trigger that fired the webhook. -### Example +#### Validating deliveries -This is an example of how to use webhooks to run a php script upon push requests to the repository. -In your repository Settings, under Webhooks, Setup a Gitea webhook as follows: +Gitea signs the raw request body with your webhook secret. To validate a +delivery: -- Target URL: http://mydomain.com/webhook.php -- HTTP Method: POST -- POST Content Type: application/json -- Secret: 123 -- Trigger On: Push Events -- Active: Checked +1. Read the request body exactly as it was received. +2. Compute the HMAC-SHA256 digest with your webhook secret. +3. Compare the result with `X-Gitea-Signature` or with the GitHub-compatible + `X-Hub-Signature-256` header. +4. Use a constant-time comparison when possible. -Now on your server create the php file webhook.php +Important details: + +- `X-Gitea-Signature` contains only the lowercase hexadecimal SHA-256 digest. +- `X-Hub-Signature-256` contains the same digest with a `sha256=` prefix. +- `X-Hub-Signature` is also sent for compatibility and uses SHA-1. +- The body must be verified before JSON parsing or any other modification. + +##### PHP example + +The following example verifies a generic `Gitea` webhook sent as +`application/json`. ```php `. | +| `X-Hub-Signature-256` | GitHub-compatible HMAC-SHA256 header in the form `sha256=`. | + +If no secret is configured, the signature headers are still present, but their +digest values are empty. + +#### `Event` versus `Event-Type` + +Some Gitea webhook subscriptions are grouped together under one normalized event +name. For example, an issue assignment delivery uses the issue event group: ```http -X-GitHub-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 -X-GitHub-Event: push -X-Gogs-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 -X-Gogs-Event: push -X-Gitea-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 -X-Gitea-Event: push +X-Gitea-Event: issues +X-Gitea-Event-Type: issue_assign +X-GitHub-Event: issues +X-GitHub-Event-Type: issue_assign ``` -```json -{ - "secret": "3gEsCfjlV2ugRwgpU#w1*WaW*wa4NXgGmpCfkbG3", - "ref": "refs/heads/develop", - "before": "28e1879d029cb852e4844d9c718537df08844e03", - "after": "bffeb74224043ba2feb48d137756c8a9331c449a", - "compare_url": "http://localhost:3000/gitea/webhooks/compare/28e1879d029cb852e4844d9c718537df08844e03...bffeb74224043ba2feb48d137756c8a9331c449a", - "commits": [ - { - "id": "bffeb74224043ba2feb48d137756c8a9331c449a", - "message": "Webhooks Yay!", - "url": "http://localhost:3000/gitea/webhooks/commit/bffeb74224043ba2feb48d137756c8a9331c449a", - "author": { - "name": "Gitea", - "email": "someone@gitea.io", - "username": "gitea" - }, - "committer": { - "name": "Gitea", - "email": "someone@gitea.io", - "username": "gitea" - }, - "timestamp": "2017-03-13T13:52:11-04:00" - } - ], - "repository": { - "id": 140, - "owner": { - "id": 1, - "login": "gitea", - "full_name": "Gitea", - "email": "someone@gitea.io", - "avatar_url": "https://localhost:3000/avatars/1", - "username": "gitea" - }, - "name": "webhooks", - "full_name": "gitea/webhooks", - "description": "", - "private": false, - "fork": false, - "html_url": "http://localhost:3000/gitea/webhooks", - "ssh_url": "ssh://gitea@localhost:2222/gitea/webhooks.git", - "clone_url": "http://localhost:3000/gitea/webhooks.git", - "website": "", - "stars_count": 0, - "forks_count": 1, - "watchers_count": 1, - "open_issues_count": 7, - "default_branch": "master", - "created_at": "2017-02-26T04:29:06-05:00", - "updated_at": "2017-03-13T13:51:58-04:00" - }, - "pusher": { - "id": 1, - "login": "gitea", - "full_name": "Gitea", - "email": "someone@gitea.io", - "avatar_url": "https://localhost:3000/avatars/1", - "username": "gitea" - }, - "sender": { - "id": 1, - "login": "gitea", - "full_name": "Gitea", - "email": "someone@gitea.io", - "avatar_url": "https://localhost:3000/avatars/1", - "username": "gitea" - } -} -``` +Use `X-Gitea-Event-Type` when you need the exact trigger that fired the webhook. -### Example +#### Validating deliveries -This is an example of how to use webhooks to run a php script upon push requests to the repository. -In your repository Settings, under Webhooks, Setup a Gitea webhook as follows: +Gitea signs the raw request body with your webhook secret. To validate a +delivery: -- Target URL: http://mydomain.com/webhook.php -- HTTP Method: POST -- POST Content Type: application/json -- Secret: 123 -- Trigger On: Push Events -- Active: Checked +1. Read the request body exactly as it was received. +2. Compute the HMAC-SHA256 digest with your webhook secret. +3. Compare the result with `X-Gitea-Signature` or with the GitHub-compatible + `X-Hub-Signature-256` header. +4. Use a constant-time comparison when possible. -Now on your server create the php file webhook.php +Important details: + +- `X-Gitea-Signature` contains only the lowercase hexadecimal SHA-256 digest. +- `X-Hub-Signature-256` contains the same digest with a `sha256=` prefix. +- `X-Hub-Signature` is also sent for compatibility and uses SHA-1. +- The body must be verified before JSON parsing or any other modification. + +##### PHP example + +The following example verifies a generic `Gitea` webhook sent as +`application/json`. ```php