initial import

This commit is contained in:
2026-01-23 14:41:49 +02:00
commit 772657d9be
37 changed files with 11382 additions and 0 deletions
+127
View File
@@ -0,0 +1,127 @@
package router
import (
"fmt"
"net/http"
"regexp"
)
type Handler interface {
ServeHTTP(rctx *Context)
}
type HandlerFunc func(rctx *Context)
func (handlerFunc HandlerFunc) ServeHTTP(rctx *Context) {
handlerFunc(rctx)
}
type Router struct {
routeHandler *Selector
}
func NewRouter() *Router {
return &Router{
routeHandler: NewSelector(),
}
}
func (rout *Router) AddRoute(method, path string, handlerFunc HandlerFunc) {
rout.routeHandler.AddRoute(method, path, handlerFunc)
}
func (rout *Router) Get(path string, handlerFunc HandlerFunc) {
rout.routeHandler.AddRoute("GET", path, handlerFunc)
}
func (rout *Router) Post(path string, handlerFunc HandlerFunc) {
rout.routeHandler.AddRoute("POST", path, handlerFunc)
}
func (rout *Router) ServeHTTP(writer http.ResponseWriter, req *http.Request) {
rctx := NewContext(writer, req)
rout.routeHandler.ServeHTTP(rctx)
}
func (rout *Router) NotFound(handlerFunc HandlerFunc) {
rout.routeHandler.notFound = handlerFunc
}
type Selector struct {
Routes []*Route
notFound Handler
}
func NewSelector() *Selector {
notFound := HandlerFunc(func(ctx *Context) {
http.NotFound(ctx.Writer, ctx.Request)
})
return &Selector{
Routes: make([]*Route, 0),
notFound: notFound,
}
}
const globalRoutePattern = `^%s$`
func (hand *Selector) AddRoute(method, path string, handlerFunc HandlerFunc) error {
var err error
path, err = pathCompiler(path)
if err != nil {
return err
}
path = fmt.Sprintf(globalRoutePattern, path)
re, err := regexp.Compile(path)
if err != nil {
return err
}
route := &Route{
Method: method,
Path: path,
Handler: handlerFunc,
Regexp: re,
}
hand.Routes = append(hand.Routes, route)
return err
}
func (hand *Selector) ServeHTTP(rctx *Context) {
realHandler := hand.notFound
for _, route := range hand.Routes {
match := route.Match(rctx.Request)
if !match {
continue
}
subvals := route.Regexp.FindStringSubmatch(rctx.Request.URL.Path)
subkeys := route.Regexp.SubexpNames()
for i, val := range subvals {
key := subkeys[i]
if key != "" {
rctx.PathMap[key] = val
}
}
realHandler = route.Handler
break
}
realHandler.ServeHTTP(rctx)
}
type Route struct {
Method string
Regexp *regexp.Regexp
Path string
Handler HandlerFunc
}
func (route Route) Match(req *http.Request) bool {
if req.Method != route.Method {
return false
}
match := route.Regexp.MatchString(req.URL.Path)
if match {
return true
}
return false
}