Admin API purge/invalidation still panics with nil pointer on v0.16.0 (same root cause as #140)
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 3/5
- Tiempo estimado
- 1-2 días
- Aptitud para principiantes
- 76/100
Línea de trabajo
Comienza en admin.go, en adminAPI.Provision y handleAPIEndpoints, y luego sigue cómo el SouinCaddyMiddleware de cada ruta rellena app.SurrogateStorage. Reprodúcelo con un inicio en frío de Caddy/FrankenPHP y una solicitud de admin purge o group-invalidation; se considera terminado cuando esas solicitudes se completan sin un nil-pointer panic.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
cache-handler version(s) affected: v0.16.0
Description
Every call to the Souin admin API (purge, group-invalidation, etc.) panics with a nil pointer dereference — confirmed on a real deployment (FrankenPHP + github.com/caddyserver/cache-handler), not just in isolation. This looks like the same root cause as #140, still reproducing on v0.16.0.
Root cause
adminAPI.Provision() (in admin.go) resolves a.app (the *SouinApp instance) and returns. The handler map (InternalEndpointHandlers), which is built from a.app.Storers and a.app.SurrogateStorage, is constructed once, also inside Provision().
The problem: a.app.SurrogateStorage is populated by the per-route SouinCaddyMiddleware's own Provision() — a separate module, provisioned in an order Caddy doesn't guarantee relative to adminAPI.Provision(). When adminAPI.Provision() runs first (or the middleware simply hasn't provisioned yet for whatever route ordering reason), the handler map gets built with a nil SurrogateStorage baked in — permanently, since it's only ever built once, at Provision() time. Every subsequent admin API call then panics trying to use it.
How to reproduce
- Configure
cache-handlerwithCache-Tags/Surrogate-Keyinvalidation enabled (a purger hitting the Souin admin API). - Start Caddy/FrankenPHP fresh (cold start matters — the provisioning-order race is timing-dependent, not always reproducible on every boot).
- Send any purge/invalidation request to the admin API (
/souin-api/souin,PURGEmethod or group-invalidation endpoint). - Nil pointer panic in the admin API handler, request fails.
Possible Solution
Defer building InternalEndpointHandlers until the first actual admin API request instead of at Provision() time, guarded by a sync.Once. By the time any real HTTP request reaches the admin API, both modules are guaranteed fully provisioned, so a.app.SurrogateStorage is populated correctly.
type adminAPI struct {
ctx caddy.Context
logger core.Logger
app *SouinApp
InternalEndpointHandlers *api.MapHandler
handlersOnce sync.Once
}
// ensureHandlers builds InternalEndpointHandlers on first use rather than at
// Provision time. adminAPI.Provision() and the per-route SouinCaddyMiddleware's
// Provision() (which populates app.SurrogateStorage) run in an unspecified
// order — building the handler map here at Provision time can capture a nil
// SurrogateStorage forever, crashing every purge call. Deferring the build
// until the first actual admin API request guarantees the app is fully
// provisioned by then.
func (a *adminAPI) ensureHandlers() {
a.handlersOnce.Do(func() {
config := Configuration{
API: a.app.API,
DefaultCache: DefaultCache{
TTL: configurationtypes.Duration{
Duration: 120 * time.Second,
},
},
}
a.InternalEndpointHandlers = api.GenerateHandlerMap(&config, a.app.Storers, a.app.SurrogateStorage)
})
}
func (a *adminAPI) handleAPIEndpoints(writer http.ResponseWriter, request *http.Request) error {
a.ensureHandlers()
if a.InternalEndpointHandlers != nil {
for k, handler := range *a.InternalEndpointHandlers.Handlers {
if strings.Contains(request.RequestURI, k) {
handler(writer, request)
return nil
}
}
}
return caddy.APIError{
HTTPStatus: http.StatusNotFound,
Err: fmt.Errorf("resource not found: %v", request.URL.Path),
}
}
func (a *adminAPI) Provision(ctx caddy.Context) error {
a.ctx = ctx
a.logger = ctx.Logger(a).Sugar()
app, err := ctx.App(moduleName)
if err != nil {
return err
}
a.app = app.(*SouinApp)
return nil
}
Removed from Provision(): the eager InternalEndpointHandlers = api.GenerateHandlerMap(...) call. Everything else in Provision() stays the same.
Patched and running this in production (built via a local xcaddy override on top of the v0.16.0 tag) without further panics since.
Additional Context
Related to #140 — same symptom (nil pointer panic in the admin API), and the fix here is the same shape (lazy-init instead of eager-init at Provision() time). Flagging as its own issue since it's still present on v0.16.0 and #140 seems to have gone quiet — happy to close this in favor of #140 or open a PR directly if that's more useful.
- Lenguaje dominante
- Go
- Estrellas
- 395
- Forks
- 30
- Merge medio
- 32 min
- PR fusionados (30 d)
- 1
Preparar el entorno
Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de caddyserver/cache-handler
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 72/100
caddyserver/cache-handler#138 · 1 comentario · 3 reacciones ·
-
Dificultad 4/5 3-5 días Aptitud para principiantes 48/100
caddyserver/cache-handler#145 ·
-
Can not flush cacheAbierto
Dificultad 3/5 1-2 días Aptitud para principiantes 55/100
caddyserver/cache-handler#140 · 4 comentarios · 1 reacción ·
-
`Incomming` has a typoAbierto
Dificultad 1/5 Menos de una hora Aptitud para principiantes 45/100
caddyserver/cache-handler#139 · 1 comentario ·
-
Dificultad 4/5 3-5 días Aptitud para principiantes 35/100
caddyserver/cache-handler#137 · 1 comentario ·
Todos los issues de caddyserver/cache-handler
Issues similares
-
bug performance scalability
Dificultad 2/5 1-3 horas Aptitud para principiantes 62/100
Davidjustice28/basildb#35 ·
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
rhysd/actionlint#761 ·
-
bug needs-triage P2 tier:1-mechanical
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
krakenhavoc/cmd_and_ctrl#3652 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 66/100
puppe1990/amarra-cais#345 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
limitlessprojects/Go-Hybrid#50 ·
Los mantenedores suelen responder en 1 día