package routes import ( "context" "fmt" "maps" "net/http" "strings" "github.com/a-h/templ" ) func render(component func(context.Context) templ.Component) func(http.ResponseWriter, *http.Request) { return func(writer http.ResponseWriter, req *http.Request) { err := component(req.Context()).Render(req.Context(), writer) if err != nil { http.Error(writer, fmt.Sprintf("can't render component: %s", err), http.StatusInternalServerError) } } } func normalizePath(pathSegments ...string) string { normalized := make([]string, len(pathSegments)) for i, segment := range pathSegments { normalized[i] = strings.Trim(segment, "/") } return "/" + strings.TrimPrefix(strings.Join(normalized, "/"), "/") } func routesToMap(rootPath string, route *Route) RoutesMap { routesMap := make(RoutesMap, 0) optionsHandler := route.Options if optionsHandler == nil { allowed := []string{} if route.Get != nil { allowed = append(allowed, http.MethodGet) } if route.Post != nil { allowed = append(allowed, http.MethodPost) } if route.Put != nil { allowed = append(allowed, http.MethodPut) } if route.Delete != nil { allowed = append(allowed, http.MethodDelete) } allowed = append(allowed, http.MethodOptions) allowedString := strings.Join(allowed, ", ") optionsHandler = func(writer http.ResponseWriter, req *http.Request) { writer.Header().Set("Allow", allowedString) writer.WriteHeader(http.StatusNoContent) } } currentPath := normalizePath(rootPath, route.Path) routesMap[currentPath] = map[string]func(http.ResponseWriter, *http.Request){ http.MethodGet: route.Get, http.MethodPost: route.Post, http.MethodPut: route.Put, http.MethodDelete: route.Delete, http.MethodOptions: optionsHandler, } for _, sub := range route.SubRoutes { maps.Copy(routesMap, routesToMap(currentPath, sub)) } return routesMap }