Fix encoding for Matrix Webhooks (#37190)

`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: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
Nicolas
2026-04-13 20:10:43 +02:00
committed by GitHub
parent fa8f7f15ef
commit 6eae04241d
2 changed files with 25 additions and 1 deletions

View File

@@ -450,12 +450,21 @@ func MatrixHooksEditPost(ctx *context.Context) {
editWebhook(ctx, matrixHookParams(ctx))
}
func matrixRoomIDEncode(roomID string) string {
// See https://spec.matrix.org/latest/appendices/#room-ids
// Some (unrelated) demo links: https://spec.matrix.org/latest/appendices/#matrixto-navigation
// API spec: https://spec.matrix.org/v1.18/client-server-api/#sending-events-to-a-room
// Some of their examples show links like: "PUT /rooms/!roomid:domain/state/m.example.event"
return strings.NewReplacer("%21", "!", "%3A", ":").Replace(url.PathEscape(roomID))
}
func matrixHookParams(ctx *context.Context) webhookParams {
form := web.GetForm(ctx).(*forms.NewMatrixHookForm)
// TODO: need to migrate to the latest (v3) API: https://spec.matrix.org/v1.18/client-server-api/
return webhookParams{
Type: webhook_module.MATRIX,
URL: fmt.Sprintf("%s/_matrix/client/r0/rooms/%s/send/m.room.message", form.HomeserverURL, url.PathEscape(form.RoomID)),
URL: fmt.Sprintf("%s/_matrix/client/r0/rooms/%s/send/m.room.message", form.HomeserverURL, matrixRoomIDEncode(form.RoomID)),
ContentType: webhook.ContentTypeJSON,
HTTPMethod: http.MethodPut,
WebhookForm: form.WebhookForm,

View File

@@ -0,0 +1,15 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package setting
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestWebhookMatrix(t *testing.T) {
assert.Equal(t, "!roomid:domain", matrixRoomIDEncode("!roomid:domain"))
assert.Equal(t, "!room%23id:domain", matrixRoomIDEncode("!room#id:domain")) // maybe it should never really happen in real world
}