Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb396408

Browse files
authored
fix: handle urls with multiple slashes (#16527)
Fixes:#9877This PR introduces another middleware to rewrite URLs when multipleslashes are used.
1 parent5ec385b commitb396408

File tree

3 files changed

+104
-0
lines changed

3 files changed

+104
-0
lines changed

‎coderd/coderd.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -788,6 +788,7 @@ func New(options *Options) *API {
788788
httpmw.AttachRequestID,
789789
httpmw.ExtractRealIP(api.RealIPConfig),
790790
httpmw.Logger(api.Logger),
791+
singleSlashMW,
791792
rolestore.CustomRoleMW,
792793
prometheusMW,
793794
// Build-Version is helpful for debugging.
@@ -1731,3 +1732,31 @@ func ReadExperiments(log slog.Logger, raw []string) codersdk.Experiments {
17311732
}
17321733
returnexps
17331734
}
1735+
1736+
varmultipleSlashesRe=regexp.MustCompile(`/+`)
1737+
1738+
funcsingleSlashMW(next http.Handler) http.Handler {
1739+
fn:=func(w http.ResponseWriter,r*http.Request) {
1740+
varpathstring
1741+
rctx:=chi.RouteContext(r.Context())
1742+
ifrctx!=nil&&rctx.RoutePath!="" {
1743+
path=rctx.RoutePath
1744+
}else {
1745+
path=r.URL.Path
1746+
}
1747+
1748+
// Normalize multiple slashes to a single slash
1749+
newPath:=multipleSlashesRe.ReplaceAllString(path,"/")
1750+
1751+
// Apply the cleaned path
1752+
// The approach is consistent with: https://github.com/go-chi/chi/blob/e846b8304c769c4f1a51c9de06bebfaa4576bd88/middleware/strip.go#L24-L28
1753+
ifrctx!=nil {
1754+
rctx.RoutePath=newPath
1755+
}else {
1756+
r.URL.Path=newPath
1757+
}
1758+
1759+
next.ServeHTTP(w,r)
1760+
}
1761+
returnhttp.HandlerFunc(fn)
1762+
}

‎coderd/coderd_internal_test.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package coderd
2+
3+
import (
4+
"context"
5+
"net/http"
6+
"net/http/httptest"
7+
"testing"
8+
9+
"github.com/go-chi/chi/v5"
10+
"github.com/stretchr/testify/assert"
11+
)
12+
13+
funcTestStripSlashesMW(t*testing.T) {
14+
t.Parallel()
15+
16+
tests:= []struct {
17+
namestring
18+
inputPathstring
19+
wantPathstring
20+
}{
21+
{"No changes","/api/v1/buildinfo","/api/v1/buildinfo"},
22+
{"Double slashes","/api//v2//buildinfo","/api/v2/buildinfo"},
23+
{"Triple slashes","/api///v2///buildinfo","/api/v2/buildinfo"},
24+
{"Leading slashes","///api/v2/buildinfo","/api/v2/buildinfo"},
25+
{"Root path","/","/"},
26+
{"Double slashes root","//","/"},
27+
{"Only slashes","/////","/"},
28+
}
29+
30+
handler:=http.HandlerFunc(func(w http.ResponseWriter,_*http.Request) {
31+
w.WriteHeader(http.StatusOK)
32+
})
33+
34+
for_,tt:=rangetests {
35+
tt:=tt
36+
37+
t.Run("chi/"+tt.name,func(t*testing.T) {
38+
t.Parallel()
39+
req:=httptest.NewRequest("GET",tt.inputPath,nil)
40+
rec:=httptest.NewRecorder()
41+
42+
// given
43+
rctx:=chi.NewRouteContext()
44+
rctx.RoutePath=tt.inputPath
45+
req=req.WithContext(context.WithValue(req.Context(),chi.RouteCtxKey,rctx))
46+
47+
// when
48+
singleSlashMW(handler).ServeHTTP(rec,req)
49+
updatedCtx:=chi.RouteContext(req.Context())
50+
51+
// then
52+
assert.Equal(t,tt.inputPath,req.URL.Path)
53+
assert.Equal(t,tt.wantPath,updatedCtx.RoutePath)
54+
})
55+
56+
t.Run("stdlib/"+tt.name,func(t*testing.T) {
57+
t.Parallel()
58+
req:=httptest.NewRequest("GET",tt.inputPath,nil)
59+
rec:=httptest.NewRecorder()
60+
61+
// when
62+
singleSlashMW(handler).ServeHTTP(rec,req)
63+
64+
// then
65+
assert.Equal(t,tt.wantPath,req.URL.Path)
66+
assert.Nil(t,chi.RouteContext(req.Context()))
67+
})
68+
}
69+
}

‎site/vite.config.mts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ export default defineConfig({
5252
"csrf_token=JXm9hOUdZctWt0ZZGAy9xiS/gxMKYOThdxjjMnMUyn4=; Path=/; HttpOnly; SameSite=Lax",
5353
},
5454
proxy:{
55+
"//":{
56+
changeOrigin:true,
57+
target:process.env.CODER_HOST||"http://localhost:3000",
58+
secure:process.env.NODE_ENV==="production",
59+
rewrite:(path)=>path.replace(/\/+/g,"/"),
60+
},
5561
"/api":{
5662
ws:true,
5763
changeOrigin:true,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp