package joist import ( "context" "log" "net/http" "regexp" "strings" "time" jerr "git.markbailey.dev/cerbervs/joist/internal/errors" "github.com/go-chi/chi/v5" ) type RouteInfo struct { Method string Name string Path string Description string Title string } func NewRouteInfo(method, path, description, title string) (RouteInfo, error) { name, err := convertRouteToRouteName(path) if err != nil { return RouteInfo{}, err } return RouteInfo{ Method: method, Name: name, Path: path, Description: description, Title: title, }, nil } type routeInfoKey struct{} type Router struct { chi.Mux cache RouteCacher cacheTTL time.Duration } func NewRouter() Router { ttl := 8 * time.Hour cache, err := NewRouteCacheService(WithTTL(ttl)) if err != nil { log.Fatal(jerr.Wrap(err, jerr.ErrRouterNotCreated)) } return Router{cache: cache, cacheTTL: ttl} } func (ro *Router) WithRouteInfo(ri RouteInfo, h HandlerFn) http.HandlerFunc { ro.cache.AddRouteInfo(ri) return func(w http.ResponseWriter, r *http.Request) { ctx := context.WithValue(r.Context(), routeInfoKey{}, ri) h.ServeHTTP(w, r.WithContext(ctx)) } } // TODO: move to base handler when it's implemented func GetRouteInfo(r *http.Request) (RouteInfo, bool) { info, ok := r.Context().Value(routeInfoKey{}).(RouteInfo) return info, ok } func convertRouteToRouteName(route string) (string, error) { name := "app" if route == "/" { return name + ".home", nil } route = strings.ReplaceAll(route, "/", ".") route = strings.ReplaceAll(route, "-", "_") paramRegex := regexp.MustCompile(`\.{[^}]*}`) params := paramRegex.FindAllString(route, -1) route = paramRegex.ReplaceAllString(route, "") if len(params) > 0 { route += ".params" } name += strings.TrimRight(route, ".") return name, nil }