AFAIRE
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

168 lines
3.5 KiB

/*
------------------------------------------------------------------------------------------------------------------------
####### kong ####### Copyright (c) 2021-2022 losyme ################################################ MIT License #######
------------------------------------------------------------------------------------------------------------------------
*/
package router
import (
"net/http"
"strings"
"forge.chapril.org/losyme/errors"
"forge.chapril.org/losyme/kong/context"
)
type SubRouter struct {
rrType context.RendererType
ctxPool *context.Pool
middlewares []Middleware
routes *segment
OnNotFound HandlerFunc
}
func newSubRouter(rrt context.RendererType) *SubRouter {
return &SubRouter{
rrType: rrt,
ctxPool: context.NewPool(),
routes: &segment{},
}
}
func (sr *SubRouter) findSegment(path string) *segment {
seg := sr.routes
for _, ps := range strings.Split(strings.Trim(path, "/"), "/") {
if ps == "" {
continue
}
seg = seg.next(ps)
}
return seg
}
func (sr *SubRouter) Use(mdlw ...Middleware) {
sr.middlewares = append(sr.middlewares, mdlw...)
}
func (sr *SubRouter) Add(method, path string, handler HandlerFunc) {
seg := sr.findSegment(path)
if seg.handlers == nil {
seg.handlers = make(map[string]HandlerFunc)
}
seg.handlers[strings.ToUpper(method)] = handler
}
func (sr *SubRouter) Any(path string, handler HandlerFunc) {
sr.Add("*", path, handler)
}
func (sr *SubRouter) Delete(path string, handler HandlerFunc) {
sr.Add(http.MethodDelete, path, handler)
}
func (sr *SubRouter) Get(path string, handler HandlerFunc) {
sr.Add(http.MethodGet, path, handler)
}
func (sr *SubRouter) Head(path string, handler HandlerFunc) {
sr.Add(http.MethodHead, path, handler)
}
func (sr *SubRouter) Options(path string, handler HandlerFunc) {
sr.Add(http.MethodOptions, path, handler)
}
func (sr *SubRouter) Patch(path string, handler HandlerFunc) {
sr.Add(http.MethodPatch, path, handler)
}
func (sr *SubRouter) Post(path string, handler HandlerFunc) {
sr.Add(http.MethodPost, path, handler)
}
func (sr *SubRouter) Put(path string, handler HandlerFunc) {
sr.Add(http.MethodPut, path, handler)
}
func (sr *SubRouter) Group(path string, fn func(*Group)) {
fn(&Group{
sr: sr,
path: path,
})
}
func (sr *SubRouter) ServeFiles(path string, fs http.FileSystem) error {
const param = "filepath"
const suffix = "/:" + param
if len(path) < 10 || path[len(path)-10:] != suffix {
return errors.New("path must end with "+suffix, "path", path) //////////////////////////////////////////////////
}
fileServer := http.FileServer(fs)
sr.Get(path, func(c *context.Context) error {
c.Request.URL.Path = c.Param(param)
fileServer.ServeHTTP(c.Response, c.Request)
return nil
})
return nil
}
func (sr *SubRouter) match(path string, ctx *context.Context, ms *middlewares) *segment {
var ps string
seg := sr.routes
for path != "" {
i := strings.Index(path, "/")
if i == -1 {
ps = path
path = ""
} else if i == 0 {
path = path[1:]
continue
} else {
ps = path[:i]
path = path[i+1:]
}
if seg.routes == nil {
return nil
}
tmp, ok := seg.routes[ps]
if !ok {
for _, t := range seg.routes {
if t.param != "" {
ok = true
tmp = t
ctx.AddParam(t.param, ps)
break
}
}
if !ok {
return nil
}
}
seg = tmp
ms.list = append(ms.list, seg.middlewares...)
}
return seg
}
/*
######################################################################################################## @(°_°)@ #######
*/