Documentation ¶
Overview ¶
Package treemux is forked from github.com/dimfeld/httptreemux.
`httptreemux` is inspired by Julien Schmidt's httprouter, in that it uses a patricia tree, but the implementation is rather different. Specifically, the routing rules are relaxed so that a single path segment may be a wildcard in one route and a static token in another. This gives a nice combination of high performance with a lot of convenience in designing the routing patterns.
Index ¶
- func AddContextData(r *http.Request, data ContextData) *http.Request
- func AddParamsToContext(ctx context.Context, params Params) context.Context
- func AddRouteToContext(ctx context.Context, route string) context.Context
- func Clean(p string) string
- func ShowErrorsJSONPanicHandler(w http.ResponseWriter, r *http.Request, err interface{})
- func ShowErrorsPanicHandler(w http.ResponseWriter, r *http.Request, err interface{})
- func SimplePanicHandler(w http.ResponseWriter, r *http.Request, err interface{})
- type Bridge
- type ContextData
- type Group
- func (g *Group[T]) DELETE(path string, handler T)
- func (g *Group[T]) GET(path string, handler T)
- func (g *Group[T]) HEAD(path string, handler T)
- func (g *Group[T]) Handle(method string, path string, handler T)
- func (g *Group[T]) NewGroup(path string) *Group[T]
- func (g *Group[T]) OPTIONS(path string, handler T)
- func (g *Group[T]) PATCH(path string, handler T)
- func (g *Group[T]) POST(path string, handler T)
- func (g *Group[T]) PUT(path string, handler T)
- func (g *Group[T]) Use(middlewares ...MiddlewareFunc[T])
- func (g *Group[T]) UseHandler(middlewares ...func(http.Handler) http.Handler)
- type HTTPHandlerFunc
- type HTTPHandlerMiddleware
- type HandlerConstraint
- type HandlerFunc
- type LookupResult
- type MethodNotAllowedHandler
- type MiddlewareFunc
- type PanicHandler
- type Params
- type PathSource
- type RedirectBehavior
- type RewriteFunc
- type RouteType
- type TreeMux
- func (t *TreeMux[_]) Dump() string
- func (t *TreeMux[T]) Lookup(w http.ResponseWriter, r *http.Request) (LookupResult[T], bool)
- func (t *TreeMux[T]) LookupByPath(method, requestURI, urlPath string) (LookupResult[T], bool)
- func (t *TreeMux[T]) ServeHTTP(w http.ResponseWriter, r *http.Request)
- func (t *TreeMux[T]) ServeLookupResult(w http.ResponseWriter, r *http.Request, lr LookupResult[T])
- type UnimplementedBridge
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AddContextData ¶
func AddContextData(r *http.Request, data ContextData) *http.Request
AddContextData helps to do testing. It inserts given ContestData into the request's `Context` using the package's internal context key.
func AddParamsToContext ¶
AddParamsToContext helps to do testing. It inserts given params into a context using the package's internal context key.
func AddRouteToContext ¶
AddRouteToContext helps to do testing. It inserts given route into a context using the package's internal context key.
func Clean ¶
Clean is the URL version of path.Clean, it returns a canonical URL path for p, eliminating . and .. elements.
The following rules are applied iteratively until no further processing can be done:
- Replace multiple slashes with a single slash.
- Eliminate each . path name element (the current directory).
- Eliminate each inner .. path name element (the parent directory) along with the non-.. element that precedes it.
- Eliminate .. elements that begin a rooted path: that is, replace "/.." by "/" at the beginning of a path.
If the result of this process is an empty string, "/" is returned
func ShowErrorsJSONPanicHandler ¶
func ShowErrorsJSONPanicHandler(w http.ResponseWriter, r *http.Request, err interface{})
func ShowErrorsPanicHandler ¶
func ShowErrorsPanicHandler(w http.ResponseWriter, r *http.Request, err interface{})
ShowErrorsPanicHandler prints a nice representation of an error to the browser. This was taken from github.com/gocraft/web, which adapted it from the Traffic project.
func SimplePanicHandler ¶
func SimplePanicHandler(w http.ResponseWriter, r *http.Request, err interface{})
SimplePanicHandler just returns error 500.
Types ¶
type Bridge ¶
type Bridge[T HandlerConstraint] interface { // IsHandlerValid tells whether the Handler is valid, a valid Handler // which matches the request stops the router searching the routing rules. IsHandlerValid(handler T) bool // ToHTTPHandlerFunc convert a handler T and params to [http.HandlerFunc]. // // This method is not required when you don't use http.Handler features. ToHTTPHandlerFunc(handler T, urlParams Params) http.HandlerFunc // ConvertMiddleware converts a HTTPHandlerMiddleware to MiddlewareFunc[T]. // // This method is not required when you don't use http.Handler based middlewares. ConvertMiddleware(middleware HTTPHandlerMiddleware) MiddlewareFunc[T] }
Bridge is a bridge which helps TreeMux with user defined handlers to work together with http.Handler and http.HandlerFunc in stdlib.
type ContextData ¶
type ContextData interface { // Route returns the matched route, without expanded params. Route() string // Param returns the param value by name. Param(name string) string // Params returns the matched params. Params() Params }
ContextData is the information associated with the matched path.
func GetContextData ¶
func GetContextData(r *http.Request) ContextData
GetContextData returns the ContextData associated with the request. In case that no data is available, it returns an empty ContextData.
func NewContextData ¶ added in v0.2.2
func NewContextData(route string, params Params) ContextData
NewContextData creates a new ContextData.
type Group ¶
type Group[T HandlerConstraint] struct { // contains filtered or unexported fields }
func (*Group[T]) Handle ¶
Handle adds routing rules to Group.
Path elements starting with : indicate a wildcard in the path. A wildcard will only match on a single path segment. That is, the pattern `/post/:postid` will match on `/post/1` or `/post/1/`, but not `/post/1/2`.
A path element starting with * is a catch-all, whose value will be a string containing all text in the URL matched by the wildcards. For example, with a pattern of `/images/*path` and a requested URL `images/abc/def`, path would contain `abc/def`.
Routing Rule Priority ¶
The priority rules in the router are simple.
1. Static path segments take the highest priority. If a segment and its subtree are able to match the URL, that match is returned.
2. Wildcards take second priority. For a particular wildcard to match, that wildcard and its subtree must match the URL.
3. Regexp routes are checked after static and wildcards routes. Multiple regexp routes under a same prefix are checked in the registering order, if a regexp route matches the URL, the match is returned. Regular expression must be at the end of a pattern.
4. Finally, a catch-all rule will match when the earlier path segments have matched, and none of above rules have matched. Catch-all rules must be at the end of a pattern.
So with the following patterns, we'll see certain matches:
router = treemux.New[MyHandler]() router.GET("/:page", pageHandler) router.GET("/:year/:month/:post", postHandler) router.GET("/:year/:month", archiveHandler) router.GET(`/images/~^(?P<category>\w+)-(?P<name>.+)$`) router.GET("/images/*path", staticHandler) router.GET("/favicon.ico", staticHandler) /abc will match /:page /2014/05 will match /:year/:month /2014/05/really-great-blog-post will match /:year/:month/:post /images/cate1-Img1.jpg will match /images/~^(?P<category>\w+)-(?P<name>.+)$, the params will be `category=cate1` and `name=Img1.jpg` /images/CoolImage.gif will match /images/*path /images/2014/05/MayImage.jpg will also match /images/*path, with all the text after /images stored in the variable path. /favicon.ico will match /favicon.ico
Trailing Slashes ¶
The router has special handling for paths with trailing slashes. If a pattern is added to the router with a trailing slash, any matches on that pattern without a trailing slash will be redirected to the version with the slash. If a pattern does not have a trailing slash, matches on that pattern with a trailing slash will be redirected to the version without.
The trailing slash flag is only stored once for a pattern. That is, if a pattern is added for a method with a trailing slash, all other methods for that pattern will also be considered to have a trailing slash, regardless of whether it is specified for those methods too.
This behavior can be turned off by setting TreeMux.RedirectTrailingSlash to false. By default it is set to true. The specifics of the redirect depend on RedirectBehavior.
One exception to this rule is catch-all patterns. By default, trailing slash redirection is disabled on catch-all patterns, since the structure of the entire URL and the desired patterns can not be predicted. If trailing slash removal is desired on catch-all patterns, set TreeMux.RemoveCatchAllTrailingSlash to true.
router = treemux.New[MyHandler]() router.GET("/about", pageHandler) router.GET("/posts/", postIndexHandler) router.POST("/posts", postFormHandler) GET /about will match normally. GET /about/ will redirect to /about. GET /posts will redirect to /posts/. GET /posts/ will match normally. POST /posts will redirect to /posts/, because the GET method used a trailing slash.
func (*Group[T]) Use ¶
func (g *Group[T]) Use(middlewares ...MiddlewareFunc[T])
Use appends a middleware handler to the Group middleware stack.
func (*Group[T]) UseHandler ¶
UseHandler is like Use but accepts http.Handler middleware. It calls the middleware wrapper to convert the given middleware to a MiddlewareFunc.
type HTTPHandlerFunc ¶
type HTTPHandlerFunc = http.HandlerFunc
HTTPHandlerFunc is an alias type of http.HandlerFunc.
type HTTPHandlerMiddleware ¶
HTTPHandlerMiddleware is an alias name for http.Handler middleware `func(http.Handler) http.Handler`.
type HandlerConstraint ¶
type HandlerConstraint = any
HandlerConstraint is the type constraint for a handler, any type can be used as a handler target.
type HandlerFunc ¶
type HandlerFunc func(w http.ResponseWriter, r *http.Request, urlParams Params)
HandlerFunc is a default handler type. The parameter urlParams contains the params parsed from the request's URL.
type LookupResult ¶
type LookupResult[T HandlerConstraint] struct { // StatusCode informs the caller about the result of the lookup. // This will generally be `http.StatusNotFound` or `http.StatusMethodNotAllowed` // for an error case. // On a normal success, the StatusCode will be `http.StatusOK`. // A redirect code will also be used in case that RedirectPath is not empty. StatusCode int // Non-empty RedirectPath indicates that the request should be redirected. RedirectPath string // When StatusCode is `http.StatusMethodNotAllowed`, AllowedMethods contains the // methods registered for the request path, else it is nil. AllowedMethods []string // Params represents the key value pairs of the path parameters. Params Params // Handler is the result handler if it's found. Handler T // RoutePath is the route path registered with the result handler. RoutePath string // When StatusCode is not `http.StatusNotFound`, RouteType is the type // of the matched route. RouteType RouteType }
LookupResult contains information about a route lookup, which is returned from Lookup and can be passed to TreeMux.ServeLookupResult if the request should be served.
type MethodNotAllowedHandler ¶
type MethodNotAllowedHandler func(w http.ResponseWriter, r *http.Request, allowedMethods []string)
type MiddlewareFunc ¶
type MiddlewareFunc[T HandlerConstraint] func(next T) T
type PanicHandler ¶
type PanicHandler func(http.ResponseWriter, *http.Request, interface{})
type Params ¶ added in v0.2.0
Params contains the parameters matched from request path, as returned by the router. The slice is ordered, the first URL parameter is also the first slice value. It is therefore safe to read values by the index.
type PathSource ¶
type PathSource int
const ( RequestURI PathSource = iota // Use r.RequestURI URLPath // Use r.URL.Path )
type RedirectBehavior ¶
type RedirectBehavior int
RedirectBehavior sets the behavior when the router redirects the request to the canonical version of the requested URL using RedirectTrailingSlash or RedirectClean. The default behavior is to return a 301 status, redirecting the browser to the version of the URL that matches the given pattern.
On a POST request, most browsers that receive a 301 will submit a GET request to the redirected URL, meaning that any data will likely be lost. If you want to handle and avoid this behavior, you may use Redirect307, which causes most browsers to resubmit the request using the original method and request body.
Since 307 is supposed to be a temporary redirect, the new 308 status code has been proposed, which is treated the same, except it indicates correctly that the redirection is permanent. The big caveat here is that the RFC is relatively recent, and older browsers will not know what to do with it. Therefore its use is not recommended unless you really know what you're doing.
Finally, the UseHandler value will simply call the handler function for the pattern.
const ( Redirect301 RedirectBehavior = iota // Return 301 Moved Permanently Redirect307 // Return 307 HTTP/1.1 Temporary Redirect Redirect308 // Return a 308 RFC7538 Permanent Redirect UseHandler // Just call the handler function )
type RewriteFunc ¶ added in v0.3.0
RewriteFunc is a function which rewrites an url to another one.
func NewRewriteFunc ¶ added in v0.3.0
func NewRewriteFunc(path, rewrite string) (RewriteFunc, error)
NewRewriteFunc creates a new RewriteFunc to rewrite path. The returned function checks its input to match path, if the input does not match path, the input is returned unmodified, else it rewrites the input using the pattern specified by rewrite.
type TreeMux ¶
type TreeMux[T HandlerConstraint] struct { Group[T] // Bridge connects TreeMux to user defined handler type T. Bridge Bridge[T] // The default PanicHandler just returns a 500 code. PanicHandler PanicHandler // The default NotFoundHandler is http.NotFound. NotFoundHandler http.HandlerFunc // Any OPTIONS request that matches a path without its own OPTIONS handler will use this handler, // if set, instead of calling MethodNotAllowedHandler. OptionsHandler T // MethodNotAllowedHandler is called when a pattern matches, but that // pattern does not have a handler for the requested method. // The default handler just writes the status code // http.StatusMethodNotAllowed and adds the required "Allow" header. MethodNotAllowedHandler MethodNotAllowedHandler // HeadCanUseGet allows the router to use the GET handler to respond to // HEAD requests if no explicit HEAD handler has been added for the // matching pattern. This is true by default. HeadCanUseGet bool // RedirectCleanPath allows the router to try clean the current request path, // if no handler is registered for it. This is true by default. RedirectCleanPath bool // RedirectTrailingSlash enables automatic redirection in case router doesn't find a matching route // for the current request path but a handler for the path with or without the trailing // slash exists. This is true by default. RedirectTrailingSlash bool // RemoveCatchAllTrailingSlash removes the trailing slash when a catch-all pattern // is matched, if set to true. By default, catch-all paths are never redirected. RemoveCatchAllTrailingSlash bool // RedirectBehavior sets the default redirect behavior when RedirectTrailingSlash or // RedirectCleanPath are true. The default value is Redirect301. RedirectBehavior RedirectBehavior // RedirectMethodBehavior overrides the default behavior for a particular HTTP method. // The key is the method name, and the value is the behavior to use for that method. RedirectMethodBehavior map[string]RedirectBehavior // PathSource determines from where the router gets its path to search. // By default, it pulls the data from the RequestURI member, but this can // be overridden to use URL.Path instead. // // There is a small tradeoff here. Using RequestURI allows the router to handle // encoded slashes (i.e. %2f) in the URL properly, while URL.Path provides // better compatibility with some utility functions in the http // library that modify the Request before passing it to the router. PathSource PathSource // EscapeAddedRoutes controls URI escaping behavior when adding a route to the tree. // If set to true, the router will add both the route as originally passed, and // a version passed through URL.EscapedPath. This behavior is disabled by default. EscapeAddedRoutes bool // If present, override the default context with this one. DefaultContext context.Context // UseContextData tells the router to populate router-related data to the context // associated with a request. UseContextData bool // SafeAddRoutesWhileRunning tells the router to protect all accesses to the tree with an RWMutex. // This is only needed if you are going to add routes after the router has already begun serving requests. // There is a potential performance penalty at high load. SafeAddRoutesWhileRunning bool // CaseInsensitive determines if routes should be treated as case-insensitive. CaseInsensitive bool // contains filtered or unexported fields }
TreeMux is a generic HTTP request router. It matches the URL of each incoming request against a list of registered patterns.
func (*TreeMux[T]) Lookup ¶
func (t *TreeMux[T]) Lookup(w http.ResponseWriter, r *http.Request) (LookupResult[T], bool)
Lookup performs a lookup without actually serving the request or mutating the request or response. The return values are a LookupResult and a boolean. The boolean will be true when a handler was found or the lookup resulted in a redirect which will point to a real handler. It is false for requests which would result in a `StatusNotFound` or `StatusMethodNotAllowed`.
Regardless of the returned boolean's value, the LookupResult may be passed to ServeLookupResult to be served appropriately.
func (*TreeMux[T]) LookupByPath ¶
func (t *TreeMux[T]) LookupByPath(method, requestURI, urlPath string) (LookupResult[T], bool)
LookupByPath is similar to Lookup, except that it accepts the routing parameters directly.
func (*TreeMux[T]) ServeHTTP ¶
func (t *TreeMux[T]) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP implements the interface http.Handler.
func (*TreeMux[T]) ServeLookupResult ¶
func (t *TreeMux[T]) ServeLookupResult( w http.ResponseWriter, r *http.Request, lr LookupResult[T], )
ServeLookupResult serves a request, given a lookup result from the Lookup function. TreeMux.Bridge must be configured, else it panics.
type UnimplementedBridge ¶ added in v0.2.0
type UnimplementedBridge[T HandlerConstraint] struct{}
func (UnimplementedBridge[T]) ConvertMiddleware ¶ added in v0.2.0
func (UnimplementedBridge[T]) ConvertMiddleware(middleware HTTPHandlerMiddleware) MiddlewareFunc[T]
func (UnimplementedBridge[T]) IsHandlerValid ¶ added in v0.2.0
func (UnimplementedBridge[T]) IsHandlerValid(handler T) bool
func (UnimplementedBridge[T]) ToHTTPHandlerFunc ¶ added in v0.2.0
func (UnimplementedBridge[T]) ToHTTPHandlerFunc(handler T, urlParams Params) http.HandlerFunc