Mount() adds a subrouter under a prefix pattern.
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
...though I'm already eyeing a better approach.
This commit is contained in:
parent
ac024567e8
commit
18d69173b4
50
router.go
50
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
|
||||
}
|
||||
|
|
Reference in New Issue