summaryrefslogtreecommitdiff
path: root/router.go
diff options
context:
space:
mode:
Diffstat (limited to 'router.go')
-rw-r--r--router.go71
1 files changed, 71 insertions, 0 deletions
diff --git a/router.go b/router.go
new file mode 100644
index 0000000..8408246
--- /dev/null
+++ b/router.go
@@ -0,0 +1,71 @@
+package gus
+
+import (
+ "context"
+
+ "tildegit.org/tjp/gus/internal"
+)
+
+// Router stores a mapping of request path patterns to handlers.
+//
+// Pattern may begin with "/" and then contain slash-delimited segments.
+// - Segments beginning with colon (:) are wildcards and will match any path
+// segment at that location. It may optionally have a word after the colon,
+// which will be the parameter name the path segment is captured into.
+// - Segments beginning with asterisk (*) are remainder wildcards. This must
+// come last and will capture any remainder of the path. It may have a name
+// after the asterisk which will be the parameter name.
+// - Any other segment in the pattern must match a path segment exactly.
+//
+// These patterns do not match any path which shares a prefix, rather then
+// full path must match a pattern. If you want to only match a prefix of the
+// path you can end the pattern with a *remainder segment.
+//
+// The zero value is a usable Router which will fail to match any requst path.
+type Router struct {
+ tree internal.PathTree[Handler]
+}
+
+// Route adds a handler to the router under a path pattern.
+func (r Router) Route(pattern string, handler Handler) {
+ r.tree.Add(pattern, handler)
+}
+
+// Handler matches against the request path and dipatches to a route handler.
+//
+// If no route matches, it returns a nil response.
+// Captured path parameters will be stored in the context passed into the handler
+// and can be retrieved with RouteParams().
+func (r Router) Handler(ctx context.Context, request *Request) *Response {
+ handler, params := r.Match(request)
+ if handler == nil {
+ return nil
+ }
+
+ return handler(context.WithValue(ctx, routeParamsKey, params), request)
+}
+
+// Match returns the matched handler and captured path parameters, or nils.
+func (r Router) Match(request *Request) (Handler, map[string]string) {
+ handler, params := r.tree.Match(request.Path)
+ if handler == nil {
+ return nil, nil
+ }
+ return *handler, params
+}
+
+// RouteParams gathers captured path parameters from the request context.
+//
+// If the context doesn't contain a parameter map, it returns nil.
+// If Router was used but no parameters were captured in the pattern, it
+// returns a non-nil empty map.
+func RouteParams(ctx context.Context) map[string]string {
+ if m, ok := ctx.Value(routeParamsKey).(map[string]string); ok {
+ return m
+ }
+ return nil
+}
+
+type routeParamsKeyType struct{}
+
+var routeParamsKey = routeParamsKeyType{}