add middlewares and grouping routes

This commit is contained in:
2024-11-19 22:30:18 +01:00
parent 8e9f348150
commit c4983ee36d
3 changed files with 373 additions and 70 deletions
+69 -16
View File
@@ -17,6 +17,8 @@ type (
Data map[string]any
Middleware func(http.Handler) http.Handler
Context struct {
C context.Context
W http.ResponseWriter
@@ -25,15 +27,25 @@ type (
}
Engine struct {
mux *http.ServeMux
LogLevel slog.Level
Render *Render
mux *http.ServeMux
middleware []Middleware
groupMux map[string]*groupMux
LogLevel slog.Level
Render *Render
}
groupMux struct {
prefix string
mux *http.ServeMux
middleware []Middleware
engine *Engine
}
)
func defaultEngine() *Engine {
return &Engine{
mux: http.NewServeMux(),
groupMux: make(map[string]*groupMux),
LogLevel: slog.LevelInfo,
}
}
@@ -54,7 +66,16 @@ func (e *Engine) apply(opts ...EngineOptions) *Engine {
}
func (e *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request) {
e.handleRequest(w, r)
var handler http.Handler = e.mux
for prefix, group := range e.groupMux {
if strings.HasPrefix(r.URL.Path, prefix) {
handler = createStack(group.middleware...)(handler)
break
}
}
handler = createStack(e.middleware...)(handler)
handler.ServeHTTP(w, r)
}
func (e *Engine) Run(addr string) error {
@@ -62,30 +83,62 @@ func (e *Engine) Run(addr string) error {
return http.ListenAndServe(addr, e)
}
func (e *Engine) handleRequest(w http.ResponseWriter, r *http.Request) {
e.mux.ServeHTTP(w, r)
func createStack(xs ...Middleware) Middleware {
return func(next http.Handler) http.Handler {
for i := len(xs) - 1; i >= 0; i-- {
x := xs[i]
next = x(next)
}
return next
}
}
func (e *Engine) USE(middleware Middleware) {
e.middleware = append(e.middleware, middleware)
}
func (e *Engine) GET(path string, handler func(*Context)) {
e.mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
return
}
e.mux.HandleFunc(fmt.Sprintf("GET %s", path), func(w http.ResponseWriter, r *http.Request) {
handler(&Context{W: w, R: r, E: e})
})
}
func (e *Engine) POST(path string, handler func(*Context)) {
e.mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
return
}
e.mux.HandleFunc(fmt.Sprintf("POST %s", path), func(w http.ResponseWriter, r *http.Request) {
handler(&Context{W: w, R: r, E: e})
})
}
func (e *Engine) GROUP(prefix string) *groupMux {
if _, ok := e.groupMux[prefix]; !ok {
e.groupMux[prefix] = &groupMux{
prefix: prefix,
mux: http.NewServeMux(),
engine: e,
}
e.mux.Handle(prefix+"/", http.StripPrefix(prefix, e.groupMux[prefix].mux))
}
return e.groupMux[prefix]
}
func (g *groupMux) USE(middleware Middleware) {
g.middleware = append(g.middleware, middleware)
}
func (g *groupMux) GET(path string, handler func(*Context)) {
g.mux.HandleFunc(fmt.Sprintf("GET %s", path), func(w http.ResponseWriter, r *http.Request) {
handler(&Context{W: w, R: r, E: g.engine})
})
}
func (g *groupMux) POST(path string, handler func(*Context)) {
g.mux.HandleFunc(fmt.Sprintf("POST %s", path), func(w http.ResponseWriter, r *http.Request) {
handler(&Context{W: w, R: r, E: g.engine})
})
}
// Static serves static files from a specified directory, accessible through a defined URL path.
//
// The `path` parameter represents the URL prefix to access the static files.