summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortjpcc <tjp@ctrl-c.club>2023-02-02 17:11:27 -0700
committertjpcc <tjp@ctrl-c.club>2023-02-02 17:11:27 -0700
commit18d69173b4e23a2edd8c07c35f7a5b927587e6d7 (patch)
tree32b5bd4996607a21c536d9b3ed54f5b57b598022
parentac024567e880f0da59557f0051018f4ac932c6ad (diff)
Mount() adds a subrouter under a prefix pattern.
...though I'm already eyeing a better approach.
-rw-r--r--router.go50
1 files changed, 50 insertions, 0 deletions
diff --git a/router.go b/router.go
index 8408246..50cc41f 100644
--- a/router.go
+++ b/router.go
@@ -2,6 +2,9 @@ package gus
import (
"context"
+ "crypto/tls"
+ "net/url"
+ "strings"
"tildegit.org/tjp/gus/internal"
)
@@ -42,6 +45,16 @@ func (r Router) Handler(ctx context.Context, request *Request) *Response {
return nil
}
+ // as we may be a sub-router, check for existing stashed params
+ // and combine with that map if found.
+ priorParams := RouteParams(ctx)
+ for k, v := range priorParams {
+ if k == subrouterPathKey {
+ continue
+ }
+ params[k] = v
+ }
+
return handler(context.WithValue(ctx, routeParamsKey, params), request)
}
@@ -54,6 +67,26 @@ func (r Router) Match(request *Request) (Handler, map[string]string) {
return *handler, params
}
+// Mount attaches a sub-router to handle path suffixes after an initial prefix pattern.
+//
+// The prefix pattern may include segment :wildcards, but no *remainder segment. The
+// mounted sub-router should have patterns which only include the portion of the path
+// after whatever was matched by the prefix pattern.
+func (r Router) Mount(prefix string, subrouter *Router) {
+ prefix = strings.TrimSuffix(prefix, "/")
+ r.Route(prefix+"/*"+subrouterPathKey, func(ctx context.Context, request *Request) *Response {
+ r := cloneRequest(request)
+ r.Path = "/" + RouteParams(ctx)[subrouterPathKey]
+ return subrouter.Handler(ctx, r)
+ })
+
+ // TODO: better approach. the above works but it's a little hacky
+ // - add a method to PathTree that returns all the registered patterns
+ // and their associated handlers
+ // - have Mount pull those out of the subrouter, prepend the prefix to
+ // all its patterns, and re-add them to the parent router.
+}
+
// RouteParams gathers captured path parameters from the request context.
//
// If the context doesn't contain a parameter map, it returns nil.
@@ -66,6 +99,23 @@ func RouteParams(ctx context.Context) map[string]string {
return nil
}
+const subrouterPathKey = "subrouter_path"
+
type routeParamsKeyType struct{}
var routeParamsKey = routeParamsKeyType{}
+
+func cloneRequest(start *Request) *Request {
+ end := &Request{}
+ *end = *start
+
+ end.URL = &url.URL{}
+ *end.URL = *start.URL
+
+ if start.TLSState != nil {
+ end.TLSState = &tls.ConnectionState{}
+ *end.TLSState = *start.TLSState
+ }
+
+ return end
+}