79 lines
2.0 KiB
Go
79 lines
2.0 KiB
Go
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
|
|
}
|
|
}
|