feat(14.2.1-01): add optional surf LocaleResolver seam

Look up a backpack-published resolver so a compiled translate plugin can
strip an enabled URL prefix and write a validated locale onto context.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jakub Zych
2026-10-06 11:54:00 +02:00
parent bd0a27f59f
commit b2ce986604
7 changed files with 134 additions and 15 deletions

View File

@@ -59,6 +59,7 @@ type Router struct {
defaultBytes int64
uploadBytes int64
built map[string]pact.Middleware
app *backpack.App
}
var (
@@ -375,7 +376,7 @@ func (r *Router) compile() (http.Handler, error) {
if err := registerOverlapFamilies(mux, r.routes, handlers, families); err != nil {
return nil, err
}
return pathScopedCORS(r.corsCfg, mux), nil
return r.stripLocalePrefix(pathScopedCORS(r.corsCfg, mux)), nil
}
// handleRoute registers a route, converting a ServeMux conflict panic into an error.
@@ -436,7 +437,7 @@ func (r *Router) wrap(rt route) (http.Handler, error) {
if limit > 0 {
h = bodyLimit(limit)(h)
}
h = locale(h)
h = r.locale(h)
if rt.raw {
h = recoverBare(h)
} else {
@@ -458,6 +459,7 @@ func Assemble(app *backpack.App, plugins []party.Plugin) (http.Handler, error) {
// so callers (route:list) can inspect Routes() after a successful boot.
func BuildRouter(app *backpack.App, plugins []party.Plugin) (*Router, error) {
r := New(corsOrigins(app))
r.app = app
trusted := TrustedProxies(nil)
if app != nil {
trusted = TrustedProxies(app.Config)
@@ -704,9 +706,27 @@ func (w *bufferedResponse) commit(dst http.ResponseWriter) {
_, _ = dst.Write(w.body.Bytes())
}
func locale(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
next.ServeHTTP(w, r.WithContext(towel.WithLocale(r.Context(), r.Header.Get("Accept-Language"))))
func (r *Router) locale(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
if r != nil && r.app != nil {
if resolver, ok := r.app.Lookup[LocaleResolver](); ok && resolver != nil {
code := resolver.Resolve(w, req)
next.ServeHTTP(w, req.WithContext(towel.WithLocale(req.Context(), code)))
return
}
}
next.ServeHTTP(w, req.WithContext(towel.WithLocale(req.Context(), req.Header.Get("Accept-Language"))))
})
}
func (r *Router) stripLocalePrefix(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
if r != nil && r.app != nil {
if resolver, ok := r.app.Lookup[LocaleResolver](); ok && resolver != nil {
req = resolver.Rewrite(req)
}
}
next.ServeHTTP(w, req)
})
}