mirror of
https://github.com/TecharoHQ/anubis.git
synced 2026-04-09 18:18:49 +00:00
feat(lib): enable multiple consecutive slash support
Replaces #808 Closes #754 Some web applications require the ability to include multiple consecutive slashes in a URL. This could be for optional path variables or for wiki article titles that start with a leading slash. I wasn't aware that the RFC allowed this. Signed-off-by: Xe Iaso <me@xeiaso.net>
This commit is contained in:
@@ -99,6 +99,7 @@ There are a bunch of other assorted features and fixes too:
|
||||
- Allow [Common Crawl](https://commoncrawl.org/) by default so scrapers have less incentive to scrape
|
||||
- The [bbolt storage backend](./admin/policies.mdx#bbolt) now runs its cleanup every hour instead of every five minutes.
|
||||
- Don't block Anubis starting up if [Thoth](./admin/thoth.mdx) health checks fail.
|
||||
- Multiple consecutive slashes are supported in upstream application URLs ([#754](https://github.com/TecharoHQ/anubis/issues/754)).
|
||||
|
||||
### Potentially breaking changes
|
||||
|
||||
|
||||
@@ -204,6 +204,63 @@ func TestCVE2025_24369(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDoubleSlashes(t *testing.T) {
|
||||
pol := loadPolicies(t, "", 0)
|
||||
|
||||
path := ""
|
||||
|
||||
srv := spawnAnubis(t, Options{
|
||||
Next: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
path = r.URL.Path
|
||||
}),
|
||||
Policy: pol,
|
||||
})
|
||||
|
||||
ts := httptest.NewServer(internal.RemoteXRealIP(true, "tcp", srv))
|
||||
defer ts.Close()
|
||||
|
||||
cli := httpClient(t)
|
||||
chall := makeChallenge(t, ts, cli)
|
||||
resp := handleChallengeZeroDifficulty(t, ts, cli, chall)
|
||||
|
||||
if resp.StatusCode != http.StatusFound {
|
||||
t.Fatal("can't solve challenge, see logs")
|
||||
}
|
||||
|
||||
for _, tt := range []struct {
|
||||
name, path string
|
||||
}{
|
||||
{
|
||||
name: "basic",
|
||||
path: "/foo",
|
||||
},
|
||||
{
|
||||
name: "leading slashes",
|
||||
path: "//foo",
|
||||
},
|
||||
{
|
||||
name: "mid slashes",
|
||||
path: "/foo//bar///baz",
|
||||
},
|
||||
{
|
||||
name: "trailing slashes",
|
||||
path: "/foo/bar///",
|
||||
},
|
||||
} {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if _, err := cli.Get(ts.URL + tt.path); err != nil {
|
||||
t.Errorf("can't make request to %s: %v", tt.path, err)
|
||||
}
|
||||
|
||||
if path != tt.path {
|
||||
t.Logf("want: %s", tt.path)
|
||||
t.Logf("got: %s", path)
|
||||
t.Error("invalid path sent to server")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCookieCustomExpiration(t *testing.T) {
|
||||
pol := loadPolicies(t, "", 0)
|
||||
ckieExpiration := 10 * time.Minute
|
||||
|
||||
@@ -154,7 +154,6 @@ func New(opts Options) (*Server, error) {
|
||||
|
||||
registerWithPrefix(anubis.APIPrefix+"pass-challenge", http.HandlerFunc(result.PassChallenge), "GET")
|
||||
registerWithPrefix(anubis.APIPrefix+"check", http.HandlerFunc(result.maybeReverseProxyHttpStatusOnly), "")
|
||||
registerWithPrefix("/", http.HandlerFunc(result.maybeReverseProxyOrPage), "")
|
||||
|
||||
//goland:noinspection GoBoolExpressions
|
||||
if anubis.Version == "devel" {
|
||||
|
||||
@@ -200,7 +200,12 @@ func (s *Server) respondWithStatus(w http.ResponseWriter, r *http.Request, msg s
|
||||
}
|
||||
|
||||
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
s.mux.ServeHTTP(w, r)
|
||||
switch strings.HasPrefix(r.URL.Path, anubis.StaticPath) {
|
||||
case true:
|
||||
s.mux.ServeHTTP(w, r)
|
||||
case false:
|
||||
s.maybeReverseProxyOrPage(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) stripBasePrefixFromRequest(r *http.Request) *http.Request {
|
||||
|
||||
Reference in New Issue
Block a user