fix(go.sum): update ResolveSpec dependency to v1.0.87
This commit is contained in:
+179
@@ -0,0 +1,179 @@
|
||||
package bunrouter
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Router is the main router structure that implements HTTP request routing.
|
||||
// It maintains a routing tree and handles incoming HTTP requests.
|
||||
type Router struct {
|
||||
config // embedded router configuration
|
||||
Group // embedded route group
|
||||
mu sync.Mutex // protects the routing tree
|
||||
tree node // root node of the routing tree
|
||||
}
|
||||
|
||||
// New creates and returns a new Router instance with the given options.
|
||||
// Options can include middleware, custom handlers for 404 and 405 responses,
|
||||
// and other router configurations.
|
||||
func New(opts ...Option) *Router {
|
||||
r := &Router{
|
||||
tree: node{
|
||||
part: "/",
|
||||
},
|
||||
}
|
||||
|
||||
r.Group.router = r
|
||||
r.config.group = &r.Group
|
||||
r.methodNotAllowedHandler = methodNotAllowedHandler
|
||||
|
||||
for _, opt := range opts {
|
||||
opt.apply(&r.config)
|
||||
}
|
||||
|
||||
// Do it after processing middlewares from the options.
|
||||
if r.notFoundHandler == nil {
|
||||
r.notFoundHandler = r.group.wrap(notFoundHandler)
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
var _ http.Handler = (*Router)(nil)
|
||||
|
||||
// ServeHTTP implements the http.Handler interface.
|
||||
// It processes the incoming HTTP request and routes it to the appropriate handler.
|
||||
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
_ = r.ServeHTTPError(w, req)
|
||||
}
|
||||
|
||||
// ServeHTTPError is similar to ServeHTTP but also returns any error
|
||||
// that occurred during request handling.
|
||||
func (r *Router) ServeHTTPError(w http.ResponseWriter, req *http.Request) error {
|
||||
handler, params := r.lookup(w, req)
|
||||
return handler(w, newRequestParams(req, params))
|
||||
}
|
||||
|
||||
// lookup finds the appropriate handler and parameters for the given HTTP request.
|
||||
// It returns the handler function and parsed route parameters.
|
||||
func (r *Router) lookup(w http.ResponseWriter, req *http.Request) (HandlerFunc, Params) {
|
||||
path := req.URL.RawPath
|
||||
if path == "" {
|
||||
path = req.URL.Path
|
||||
}
|
||||
|
||||
node, handler, wildcardLen := r.tree.findRoute(req.Method, path)
|
||||
if node == nil {
|
||||
if redir := r.redir(req.Method, path); redir != nil {
|
||||
return redir, Params{}
|
||||
}
|
||||
return r.notFoundHandler, Params{}
|
||||
}
|
||||
|
||||
if handler == nil {
|
||||
if redir := r.redir(req.Method, path); redir != nil {
|
||||
return redir, Params{}
|
||||
}
|
||||
handler = node.handlerMap.notAllowed
|
||||
}
|
||||
|
||||
return handler.fn, Params{
|
||||
node: node,
|
||||
handler: handler,
|
||||
path: path,
|
||||
wildcardLen: uint16(wildcardLen),
|
||||
}
|
||||
}
|
||||
|
||||
// redir handles URL redirects for cleaned paths and trailing slash variations.
|
||||
// It returns a redirect handler if a redirect is needed, nil otherwise.
|
||||
func (r *Router) redir(method, path string) HandlerFunc {
|
||||
if path == "/" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Path was not found. Try cleaning it up and search again.
|
||||
if cleanPath := CleanPath(path); cleanPath != path {
|
||||
if _, handler, _ := r.tree.findRoute(method, cleanPath); handler != nil {
|
||||
return redirectHandler(cleanPath)
|
||||
}
|
||||
}
|
||||
|
||||
if strings.HasSuffix(path, "/") {
|
||||
// Try path without a slash.
|
||||
cleanPath := path[:len(path)-1]
|
||||
if _, handler, _ := r.tree.findRoute(method, cleanPath); handler != nil {
|
||||
return redirectHandler(cleanPath)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Try path with a slash.
|
||||
cleanPath := path + "/"
|
||||
if _, handler, _ := r.tree.findRoute(method, cleanPath); handler != nil {
|
||||
return redirectHandler(cleanPath)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// CompatRouter provides compatibility layer for the router.
|
||||
type CompatRouter struct {
|
||||
*Router
|
||||
*CompatGroup
|
||||
}
|
||||
|
||||
// Compat returns a new CompatRouter instance that wraps the current router.
|
||||
func (r *Router) Compat() *CompatRouter {
|
||||
return &CompatRouter{
|
||||
Router: r,
|
||||
CompatGroup: r.Group.Compat(),
|
||||
}
|
||||
}
|
||||
|
||||
// VerboseRouter provides a verbose interface to the router.
|
||||
type VerboseRouter struct {
|
||||
*Router
|
||||
*VerboseGroup
|
||||
}
|
||||
|
||||
// Verbose returns a new VerboseRouter instance that wraps the current router.
|
||||
func (r *Router) Verbose() *VerboseRouter {
|
||||
return &VerboseRouter{
|
||||
Router: r,
|
||||
VerboseGroup: r.Group.Verbose(),
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// redirectHandler creates a handler function that performs HTTP redirects
|
||||
// to the specified new path while preserving query parameters and fragments.
|
||||
func redirectHandler(newPath string) HandlerFunc {
|
||||
return func(w http.ResponseWriter, req Request) error {
|
||||
newURL := url.URL{
|
||||
Path: newPath,
|
||||
RawQuery: req.URL.RawQuery,
|
||||
Fragment: req.URL.Fragment,
|
||||
}
|
||||
http.Redirect(w, req.Request, newURL.String(), http.StatusMovedPermanently)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// methodNotAllowedHandler is the default handler for requests with methods
|
||||
// that are not allowed for the matched route.
|
||||
func methodNotAllowedHandler(w http.ResponseWriter, r Request) error {
|
||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||
return nil
|
||||
}
|
||||
|
||||
// notFoundHandler is the default handler for requests that don't match any route.
|
||||
func notFoundHandler(w http.ResponseWriter, req Request) error {
|
||||
http.NotFound(w, req.Request)
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user