package router import ( "fmt" "net/http" "strings" ) type Router struct { *http.ServeMux routes map[string]http.Handler requiredRoutes []string } func NewRouter(mux *http.ServeMux, requiredRoutes ...string) (ro *Router) { if mux == nil { mux = http.NewServeMux() } ro = &Router{ ServeMux: mux, routes: make(map[string]http.Handler), requiredRoutes: make([]string, 0), } ro.AddRequiredRoutes(requiredRoutes...) return } func (ro *Router) AddRequiredRoutes(requiredRoutes ...string) { if requiredRoutes == nil { return } ro.requiredRoutes = append(ro.requiredRoutes, requiredRoutes...) } func (ro *Router) Register(pattern string, server http.Handler) (err error) { if !strings.HasPrefix(pattern, "/") { return fmt.Errorf("missing preceding slash in pattern (%s)", pattern) } if server == nil { return fmt.Errorf("server must be provided") } srv, exists := ro.routes[pattern] if exists && srv != nil { return fmt.Errorf("too many routes for same pattern (%s)", pattern) } ro.routes[pattern] = server ro.ServeMux.Handle(string(pattern), ro.routes[pattern]) return } func (ro *Router) Validate() (err error) { for _, requiredRoute := range ro.requiredRoutes { _, ok := ro.routes[requiredRoute] if !ok { err = fmt.Errorf("missing required route (%s)", requiredRoute) return } } return } func (ro *Router) ServeHTTP(w http.ResponseWriter, r *http.Request) { if err := ro.Validate(); err != nil { panic(err) } ro.ServeMux.ServeHTTP(w, r) }