package hws import ( "errors" "fmt" "net/http" "slices" ) type Route struct { Path string // Absolute path to the requested resource Method Method // HTTP Method // Methods is an optional slice of Methods to use, if more than one can use the same handler. // Will take precedence over the Method field if provided Methods []Method Handler http.Handler // Handler to use for the request } type Method string const ( MethodGET Method = "GET" MethodPOST Method = "POST" MethodPUT Method = "PUT" MethodHEAD Method = "HEAD" MethodDELETE Method = "DELETE" MethodCONNECT Method = "CONNECT" MethodOPTIONS Method = "OPTIONS" MethodTRACE Method = "TRACE" MethodPATCH Method = "PATCH" ) // AddRoutes registers the page handlers for the server. // At least one route must be provided. // If any route patterns (path + method) are defined multiple times, the first // instance will be added and any additional conflicts will be discarded. func (s *Server) AddRoutes(routes ...Route) error { if len(routes) == 0 { return errors.New("no routes provided") } patterns := []string{} mux := http.NewServeMux() mux.HandleFunc("GET /healthz", func(http.ResponseWriter, *http.Request) {}) for _, route := range routes { if len(route.Methods) == 0 { route.Methods = []Method{route.Method} } for _, method := range route.Methods { if !validMethod(method) { return fmt.Errorf("invalid method %s for path %s", method, route.Path) } if route.Handler == nil { return fmt.Errorf("no handler provided for %s %s", method, route.Path) } pattern := fmt.Sprintf("%s %s", method, route.Path) if slices.Contains(patterns, pattern) { continue } patterns = append(patterns, pattern) mux.Handle(pattern, route.Handler) } } s.server.Handler = mux s.routes = true return nil } func validMethod(m Method) bool { switch m { case MethodGET, MethodPOST, MethodPUT, MethodHEAD, MethodDELETE, MethodCONNECT, MethodOPTIONS, MethodTRACE, MethodPATCH: return true default: return false } }