1 Commits
Author SHA1 Message Date
clawbot f0353d2d8b Percent-decode URL parameters before parsing them (closes #103)
check / check (push) Canceled after 0s
chi matches routes against the escaped path when a request has one and
hands the handlers their URL parameters still percent-encoded. The home
page's lookup form encodes the address it asks for, so every IPv6 lookup
answered 400, as did a comma-separated address list or a prefix that a
client percent-encoded. The router now matches against the decoded path,
so every handler reads its parameters decoded.

Model: opus-5-5
2026-10-19 20:52:05 +00:00
2 changed files with 16 additions and 13 deletions
+15
View File
@@ -10,6 +10,8 @@ import (
"net/http"
"sync"
"time"
"github.com/go-chi/chi/v5"
)
// responseWriter wraps http.ResponseWriter to capture the response
@@ -281,3 +283,16 @@ func RequestLoggerMiddleware(logger *slog.Logger) func(http.Handler) http.Handle
})
}
}
// DecodedPathMiddleware makes the router match routes against the decoded
// path, so that the handlers read their URL parameters decoded. Without it,
// chi matches against the escaped path whenever the request has one and hands
// the handlers their parameters still escaped: /ip/2001%3Adb8%3A%3A1 would
// look up "2001%3Adb8%3A%3A1".
func DecodedPathMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
chi.RouteContext(r.Context()).RoutePath = r.URL.Path
next.ServeHTTP(w, r)
})
}
+1 -13
View File
@@ -1,7 +1,6 @@
package server
import (
"net/http"
"time"
"github.com/go-chi/chi/v5"
@@ -13,18 +12,7 @@ func (s *Server) setupRoutes() {
r := chi.NewRouter()
// Middleware
// Match routes against the decoded path, so that the handlers read their
// URL parameters decoded. chi otherwise matches against the escaped path
// when the request has one and leaves the parameters escaped:
// /ip/2001%3Adb8%3A%3A1 would look up "2001%3Adb8%3A%3A1".
r.Use(func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
chi.RouteContext(req.Context()).RoutePath = req.URL.Path
next.ServeHTTP(w, req)
})
})
r.Use(DecodedPathMiddleware)
r.Use(middleware.RequestID)
r.Use(middleware.RealIP)
r.Use(RequestLoggerMiddleware(s.logger.Logger)) // Structured request logging