mirror of
https://github.com/yusing/godoxy.git
synced 2026-04-27 10:47:06 +02:00
* **New Features** * Routes can promote route-local bypass rules into matching entrypoint middleware, layering route-specific bypasses onto existing entrypoint rules and avoiding duplicate evaluation. * **Behavior Changes** * Entrypoint middleware updates now refresh per-route overlays at runtime; overlay compilation failures result in HTTP 500 (errors are not exposed verbatim). * Route middleware accessors now return safe clones. * **Documentation** * Clarified promotion, consumption, merging and qualification semantics with examples. * **Tests** * Added tests covering promotion, cache invalidation, consumption semantics, and error handling. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
60 lines
1.5 KiB
Go
60 lines
1.5 KiB
Go
package middleware
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
|
|
strutils "github.com/yusing/goutils/strings"
|
|
)
|
|
|
|
type routeOverlayConsumptionContextKey struct{}
|
|
|
|
type routeOverlayConsumption struct {
|
|
bypass map[string]struct{}
|
|
middlewares map[string]struct{}
|
|
}
|
|
|
|
var routeOverlayConsumptionKey routeOverlayConsumptionContextKey
|
|
|
|
func WithConsumedRouteOverlays(
|
|
r *http.Request,
|
|
bypass map[string]struct{},
|
|
middlewares map[string]struct{},
|
|
) *http.Request {
|
|
if len(bypass) == 0 && len(middlewares) == 0 {
|
|
return r
|
|
}
|
|
return r.WithContext(context.WithValue(r.Context(), routeOverlayConsumptionKey, routeOverlayConsumption{
|
|
bypass: bypass,
|
|
middlewares: middlewares,
|
|
}))
|
|
}
|
|
|
|
func isRouteBypassPromoted(r *http.Request, middlewareName string) bool {
|
|
return routeOverlayConsumed(r, middlewareName, func(consumption routeOverlayConsumption) map[string]struct{} {
|
|
return consumption.bypass
|
|
})
|
|
}
|
|
|
|
func isRouteMiddlewareConsumed(r *http.Request, middlewareName string) bool {
|
|
return routeOverlayConsumed(r, middlewareName, func(consumption routeOverlayConsumption) map[string]struct{} {
|
|
return consumption.middlewares
|
|
})
|
|
}
|
|
|
|
func routeOverlayConsumed(
|
|
r *http.Request,
|
|
middlewareName string,
|
|
selectSet func(routeOverlayConsumption) map[string]struct{},
|
|
) bool {
|
|
if r == nil {
|
|
return false
|
|
}
|
|
consumption, ok := r.Context().Value(routeOverlayConsumptionKey).(routeOverlayConsumption)
|
|
if !ok {
|
|
return false
|
|
}
|
|
_, ok = selectSet(consumption)[strutils.ToLowerNoSnake(middlewareName)]
|
|
return ok
|
|
}
|