Skip to content

Commit d1be5c3

Browse files
GiteaBotbircniclaudewxiaoguang
authored
Fix encoding for Matrix Webhooks (#37190) (#37201)
Backport #37190 by @bircni `url.PathEscape` unnecessarily encodes ! to %21, causing Matrix homeservers to reject the request with 401. Replace %21 back to ! after escaping. Fixes #36012 Signed-off-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: Nicolas <bircni@icloud.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
1 parent 8687faa commit d1be5c3

2 files changed

Lines changed: 25 additions & 1 deletion

File tree

routers/web/repo/setting/webhook.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,12 +450,21 @@ func MatrixHooksEditPost(ctx *context.Context) {
450450
editWebhook(ctx, matrixHookParams(ctx))
451451
}
452452

453+
func matrixRoomIDEncode(roomID string) string {
454+
// See https://spec.matrix.org/latest/appendices/#room-ids
455+
// Some (unrelated) demo links: https://spec.matrix.org/latest/appendices/#matrixto-navigation
456+
// API spec: https://spec.matrix.org/v1.18/client-server-api/#sending-events-to-a-room
457+
// Some of their examples show links like: "PUT /rooms/!roomid:domain/state/m.example.event"
458+
return strings.NewReplacer("%21", "!", "%3A", ":").Replace(url.PathEscape(roomID))
459+
}
460+
453461
func matrixHookParams(ctx *context.Context) webhookParams {
454462
form := web.GetForm(ctx).(*forms.NewMatrixHookForm)
455463

464+
// TODO: need to migrate to the latest (v3) API: https://spec.matrix.org/v1.18/client-server-api/
456465
return webhookParams{
457466
Type: webhook_module.MATRIX,
458-
URL: fmt.Sprintf("%s/_matrix/client/r0/rooms/%s/send/m.room.message", form.HomeserverURL, url.PathEscape(form.RoomID)),
467+
URL: fmt.Sprintf("%s/_matrix/client/r0/rooms/%s/send/m.room.message", form.HomeserverURL, matrixRoomIDEncode(form.RoomID)),
459468
ContentType: webhook.ContentTypeJSON,
460469
HTTPMethod: http.MethodPut,
461470
WebhookForm: form.WebhookForm,
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2026 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package setting
5+
6+
import (
7+
"testing"
8+
9+
"github.com/stretchr/testify/assert"
10+
)
11+
12+
func TestWebhookMatrix(t *testing.T) {
13+
assert.Equal(t, "!roomid:domain", matrixRoomIDEncode("!roomid:domain"))
14+
assert.Equal(t, "!room%23id:domain", matrixRoomIDEncode("!room#id:domain")) // maybe it should never really happen in real world
15+
}

0 commit comments

Comments
 (0)