Files
old-ibcetvorke/vendor/github.com/a-h/gemini/mux/mux.go
2023-07-30 19:21:16 +02:00

77 lines
1.8 KiB
Go

package mux
import (
"context"
"strings"
"github.com/a-h/gemini"
)
// Mux routes Gemini requests to the appropriate handler.
type Mux struct {
RouteHandlers []*RouteHandler
NotFoundHandler gemini.Handler
}
// NewMux creates a new Mux for routing requests.
func NewMux() *Mux {
return &Mux{
RouteHandlers: make([]*RouteHandler, 0),
NotFoundHandler: gemini.NotFoundHandler(),
}
}
// AddRoute to the mux.
func (m *Mux) AddRoute(pattern string, handler gemini.Handler) {
rh := &RouteHandler{
Route: NewRoute(pattern),
Handler: handler,
}
m.RouteHandlers = append(m.RouteHandlers, rh)
}
// RouteHandler is the Handler to use for a given Route.
type RouteHandler struct {
Route *Route
Handler gemini.Handler
}
// contextKey used to store the route handler in the request context.
type contextKey string
// matchedRouteContextKey is the key stored in the context.
const matchedRouteContextKey = contextKey("matchedRoute")
// MatchedRoute is provided in the context to Gemini handlers that use the router.
type MatchedRoute struct {
Pattern string
PathVars map[string]string
}
func (m *Mux) ServeGemini(w gemini.ResponseWriter, r *gemini.Request) {
s := r.URL.Path
s = strings.TrimSuffix(s, "/")
s = strings.TrimPrefix(s, "/")
segments := strings.Split(s, "/")
for _, rh := range m.RouteHandlers {
v, ok := rh.Route.Match(segments)
if ok {
mr := MatchedRoute{
Pattern: rh.Route.Pattern,
PathVars: v,
}
r.Context = context.WithValue(r.Context, matchedRouteContextKey, mr)
rh.Handler.ServeGemini(w, r)
return
}
}
m.NotFoundHandler.ServeGemini(w, r)
}
// GetMatchedRoute returns the route that was matched by the router, along with any path variables extracted from the URL.
func GetMatchedRoute(ctx context.Context) (mr MatchedRoute, ok bool) {
mr, ok = ctx.Value(matchedRouteContextKey).(MatchedRoute)
return mr, ok
}