fix: enable double slashes for optional path variables

Closes #754

This implementation is flawed, it's making the pass-challenge route
return 404s. I'm not entirely sure why this is happening, but I'm
pushing this for now in case there's some low hanging fruit.

Signed-off-by: Xe Iaso <me@xeiaso.net>
This commit is contained in:
Xe Iaso
2025-07-11 01:19:57 +00:00
parent c74de19532
commit 9a00809840
9 changed files with 37 additions and 19 deletions

View File

@@ -18,6 +18,7 @@ import (
"github.com/golang-jwt/jwt/v5"
"github.com/google/cel-go/common/types"
"github.com/google/uuid"
"github.com/gorilla/mux"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
@@ -68,7 +69,7 @@ var (
type Server struct {
next http.Handler
mux *http.ServeMux
mux *mux.Router
policy *policy.ParsedConfig
OGTags *ogtags.OGTagCache
ed25519Priv ed25519.PrivateKey

View File

@@ -10,6 +10,7 @@ import (
"github.com/TecharoHQ/anubis/lib/policy/config"
"github.com/TecharoHQ/anubis/lib/store"
"github.com/a-h/templ"
"github.com/gorilla/mux"
)
var (
@@ -58,7 +59,7 @@ type ValidateInput struct {
type Impl interface {
// Setup registers any additional routes with the Impl for assets or API routes.
Setup(mux *http.ServeMux)
Setup(r *mux.Router)
// Issue a new challenge to the user, called by the Anubis.
Issue(r *http.Request, lg *slog.Logger, in *IssueInput) (templ.Component, error)

View File

@@ -11,6 +11,7 @@ import (
"github.com/TecharoHQ/anubis/lib/localization"
"github.com/TecharoHQ/anubis/web"
"github.com/a-h/templ"
"github.com/gorilla/mux"
)
//go:generate go tool github.com/a-h/templ/cmd/templ generate
@@ -21,7 +22,7 @@ func init() {
type Impl struct{}
func (i *Impl) Setup(mux *http.ServeMux) {}
func (i *Impl) Setup(r *mux.Router) {}
func (i *Impl) Issue(r *http.Request, lg *slog.Logger, in *challenge.IssueInput) (templ.Component, error) {
u, err := r.URL.Parse(anubis.BasePrefix + "/.within.website/x/cmd/anubis/api/pass-challenge")

View File

@@ -13,6 +13,7 @@ import (
"github.com/TecharoHQ/anubis/lib/localization"
"github.com/TecharoHQ/anubis/web"
"github.com/a-h/templ"
"github.com/gorilla/mux"
)
func init() {
@@ -24,7 +25,7 @@ type Impl struct {
Algorithm string
}
func (i *Impl) Setup(mux *http.ServeMux) {
func (i *Impl) Setup(r *mux.Router) {
/* no implementation required */
}

View File

@@ -9,6 +9,7 @@ import (
"github.com/TecharoHQ/anubis/lib/challenge"
"github.com/TecharoHQ/anubis/lib/policy"
"github.com/TecharoHQ/anubis/lib/policy/config"
"github.com/gorilla/mux"
)
func mkRequest(t *testing.T, values map[string]string) *http.Request {
@@ -124,7 +125,7 @@ func TestBasic(t *testing.T) {
t.Run(cs.name, func(t *testing.T) {
lg := slog.With()
i.Setup(http.NewServeMux())
i.Setup(mux.NewRouter())
inp := &challenge.IssueInput{
Rule: bot,

View File

@@ -24,6 +24,7 @@ import (
"github.com/TecharoHQ/anubis/web"
"github.com/TecharoHQ/anubis/xess"
"github.com/a-h/templ"
"github.com/gorilla/mux"
)
type Options struct {
@@ -110,25 +111,33 @@ func New(opts Options) (*Server, error) {
store: opts.Policy.Store,
}
mux := http.NewServeMux()
xess.Mount(mux)
r := mux.NewRouter()
xess.Mount(r)
// Helper to add global prefix
registerWithPrefix := func(pattern string, handler http.Handler, method string) {
if method != "" {
method = method + " " // methods must end with a space to register with them
}
// Ensure there's no double slash when concatenating BasePrefix and pattern
basePrefix := strings.TrimSuffix(anubis.BasePrefix, "/")
prefix := method + basePrefix
// If pattern doesn't start with a slash, add one
if !strings.HasPrefix(pattern, "/") {
pattern = "/" + pattern
}
mux.Handle(prefix+pattern, handler)
var route *mux.Route
switch strings.HasSuffix(pattern, "/") {
case true:
route = r.PathPrefix(basePrefix + pattern)
case false:
route = r.Path(basePrefix + pattern)
}
if method != "" {
route = route.Methods(method)
}
route.Handler(handler)
}
// Ensure there's no double slash when concatenating BasePrefix and StaticPath
@@ -164,10 +173,10 @@ func New(opts Options) (*Server, error) {
for _, implKind := range challenge.Methods() {
impl, _ := challenge.Get(implKind)
impl.Setup(mux)
impl.Setup(r)
}
result.mux = mux
result.mux = r
return result, nil
}