Skip to content

Commit dcf5983

Browse files
committed
move redirect handler to repo, escape params, and add unit tests
1 parent aa242fc commit dcf5983

File tree

3 files changed

+81
-10
lines changed

3 files changed

+81
-10
lines changed

routers/web/repo/view_home.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"fmt"
99
"html/template"
1010
"net/http"
11+
"net/url"
1112
"path"
1213
"strings"
1314
"time"
@@ -412,3 +413,32 @@ func Home(ctx *context.Context) {
412413

413414
ctx.HTML(http.StatusOK, tplRepoHome)
414415
}
416+
417+
// HomeRedirect redirects from /tree/* to /src/* in order to maintain a similar URL structure.
418+
func HomeRedirect(ctx *context.Context) {
419+
prefix := "/"
420+
if setting.AppSubURL != "" {
421+
prefix = setting.AppSubURL
422+
}
423+
424+
url := treeRedirectURL(
425+
prefix,
426+
ctx.PathParam("username"),
427+
ctx.PathParam("reponame"),
428+
ctx.PathParam("*"),
429+
)
430+
ctx.Redirect(url)
431+
}
432+
433+
// treeRedirectURL constructs a "src" URL from the given "tree"
434+
// prefixed path params. This is a private function for testing
435+
// purposes.
436+
func treeRedirectURL(prefix, username, reponame, remainder string) string {
437+
return path.Join(
438+
prefix,
439+
url.PathEscape(username),
440+
url.PathEscape(reponame),
441+
"src",
442+
util.PathEscapeSegments(remainder),
443+
)
444+
}

routers/web/repo/view_home_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright 2025 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package repo
5+
6+
import (
7+
"testing"
8+
9+
"github.com/stretchr/testify/assert"
10+
)
11+
12+
func TestTreeRedirectURL(t *testing.T) {
13+
type testcase struct {
14+
name string
15+
prefix, username, reponame, remainder string
16+
expected string
17+
}
18+
19+
cases := []testcase{
20+
{
21+
name: "ref",
22+
prefix: "/", username: "user2", reponame: "readme-test", remainder: "main",
23+
expected: "/user2/readme-test/src/main",
24+
},
25+
{
26+
name: "sha",
27+
prefix: "/", username: "user2", reponame: "readme-test", remainder: "fe495ea336f079ef2bed68648d0ba9a37cdbd4aa",
28+
expected: "/user2/readme-test/src/fe495ea336f079ef2bed68648d0ba9a37cdbd4aa",
29+
},
30+
{
31+
name: "escape",
32+
prefix: "/", username: "user/2%", reponame: "readme/test?", remainder: "$/&",
33+
expected: "/user%2F2%25/readme%2Ftest%3F/src/$/&",
34+
},
35+
{
36+
name: "appPath",
37+
prefix: "/app-path", username: "user2", reponame: "readme-test", remainder: "main",
38+
expected: "/app-path/user2/readme-test/src/main",
39+
},
40+
}
41+
42+
for _, c := range cases {
43+
c := c
44+
t.Run(c.name, func(t *testing.T) {
45+
actual := treeRedirectURL(c.prefix, c.username, c.reponame, c.remainder)
46+
assert.Equal(t, c.expected, actual)
47+
})
48+
}
49+
50+
}

routers/web/web.go

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ package web
55

66
import (
77
"net/http"
8-
"path"
98
"strings"
109

1110
auth_model "code.gitea.io/gitea/models/auth"
@@ -1587,15 +1586,7 @@ func registerRoutes(m *web.Router) {
15871586

15881587
// Add a /tree/* path to redirect to the deprecated /src/*
15891588
// path. This emulates both Github & Gitlab's URL structure.
1590-
m.Get("/tree/*", func(ctx *context.Context) {
1591-
prefix := "/"
1592-
if setting.AppSubURL != "" {
1593-
prefix = setting.AppSubURL
1594-
}
1595-
1596-
url := path.Join(prefix, ctx.PathParam("username"), ctx.PathParam("reponame"), "src", ctx.PathParam("*"))
1597-
ctx.Redirect(url)
1598-
})
1589+
m.Get("/tree/*", repo.HomeRedirect)
15991590

16001591
m.Get("/forks", context.RepoRef(), repo.Forks)
16011592
m.Get("/commit/{sha:([a-f0-9]{7,64})}.{ext:patch|diff}", repo.MustBeNotEmpty, repo.RawDiff)

0 commit comments

Comments
 (0)