fix: Use catch-all route to avoid /{slug}/dl vs /static/ conflict
Go 1.22+ panics when two patterns overlap without one being strictly
more specific. GET /{slug}/dl and GET /static/ both match /static/dl.
Replaced individual wildcard routes with GET /{path...} catch-all
that manually dispatches to batch handlers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
c5b710498f
commit
5464484d73
65
main.go
65
main.go
|
|
@ -8,6 +8,7 @@ import (
|
|||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
|
|
@ -67,24 +68,54 @@ func main() {
|
|||
mux.HandleFunc("GET /f/{id}/auth", h.AuthPage)
|
||||
mux.HandleFunc("POST /f/{id}/auth", h.AuthSubmit)
|
||||
mux.HandleFunc("DELETE /f/{id}", h.Delete)
|
||||
// Top-level batch routes (batches use their own slug)
|
||||
mux.HandleFunc("GET /{slug}", h.Batch)
|
||||
mux.HandleFunc("GET /{slug}/dl", h.BatchDownload)
|
||||
mux.HandleFunc("GET /{slug}/auth", h.BatchAuthPage)
|
||||
mux.HandleFunc("POST /{slug}/auth", h.BatchAuthSubmit)
|
||||
// Catch-all for batch routes: /{slug}, /{slug}/dl, /{slug}/auth
|
||||
// Uses {path...} to avoid conflicts with /static/ subtree pattern
|
||||
mux.HandleFunc("GET /{path...}", func(w http.ResponseWriter, r *http.Request) {
|
||||
p := r.PathValue("path")
|
||||
parts := strings.SplitN(p, "/", 3)
|
||||
if len(parts) == 0 || parts[0] == "" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
slug := parts[0]
|
||||
// Backward compat: /b/{id} -> /{id}
|
||||
if slug == "b" && len(parts) >= 2 {
|
||||
target := "/" + strings.Join(parts[1:], "/")
|
||||
http.Redirect(w, r, target, http.StatusMovedPermanently)
|
||||
return
|
||||
}
|
||||
r.SetPathValue("slug", slug)
|
||||
if len(parts) == 1 {
|
||||
h.Batch(w, r)
|
||||
} else if len(parts) == 2 {
|
||||
switch parts[1] {
|
||||
case "dl":
|
||||
h.BatchDownload(w, r)
|
||||
case "auth":
|
||||
h.BatchAuthPage(w, r)
|
||||
default:
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
} else {
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
})
|
||||
|
||||
// Backward compat: /b/{id} redirects to /{id}
|
||||
mux.HandleFunc("GET /b/{id}", func(w http.ResponseWriter, r *http.Request) {
|
||||
http.Redirect(w, r, "/"+r.PathValue("id"), http.StatusMovedPermanently)
|
||||
})
|
||||
mux.HandleFunc("GET /b/{id}/dl", func(w http.ResponseWriter, r *http.Request) {
|
||||
http.Redirect(w, r, "/"+r.PathValue("id")+"/dl", http.StatusMovedPermanently)
|
||||
})
|
||||
mux.HandleFunc("GET /b/{id}/auth", func(w http.ResponseWriter, r *http.Request) {
|
||||
http.Redirect(w, r, "/"+r.PathValue("id")+"/auth", http.StatusMovedPermanently)
|
||||
})
|
||||
mux.HandleFunc("POST /b/{id}/auth", func(w http.ResponseWriter, r *http.Request) {
|
||||
http.Redirect(w, r, "/"+r.PathValue("id")+"/auth", http.StatusTemporaryRedirect)
|
||||
mux.HandleFunc("POST /{path...}", func(w http.ResponseWriter, r *http.Request) {
|
||||
p := r.PathValue("path")
|
||||
parts := strings.SplitN(p, "/", 3)
|
||||
// Backward compat: /b/{id}/auth -> /{id}/auth
|
||||
if len(parts) >= 2 && parts[0] == "b" {
|
||||
target := "/" + strings.Join(parts[1:], "/")
|
||||
http.Redirect(w, r, target, http.StatusTemporaryRedirect)
|
||||
return
|
||||
}
|
||||
if len(parts) == 2 && parts[1] == "auth" {
|
||||
r.SetPathValue("slug", parts[0])
|
||||
h.BatchAuthSubmit(w, r)
|
||||
return
|
||||
}
|
||||
http.NotFound(w, r)
|
||||
})
|
||||
|
||||
// Favicon (prevent 404)
|
||||
|
|
|
|||
Loading…
Reference in New Issue