101 lines
2.1 KiB
Go
101 lines
2.1 KiB
Go
package goblocks
|
|
|
|
import (
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"slices"
|
|
"strings"
|
|
)
|
|
|
|
type Middleware func(http.Handler) http.Handler
|
|
|
|
type Router struct {
|
|
globalChain []Middleware
|
|
routeChain []Middleware
|
|
isSub bool
|
|
*http.ServeMux
|
|
}
|
|
|
|
func newRouter() *Router {
|
|
return &Router{ServeMux: http.NewServeMux()}
|
|
}
|
|
|
|
func (r *Router) Use(mw ...Middleware) {
|
|
if r.isSub {
|
|
r.routeChain = append(r.routeChain, mw...)
|
|
} else {
|
|
r.globalChain = append(r.globalChain, mw...)
|
|
}
|
|
}
|
|
|
|
func (r *Router) Group(basePath string, fn func(r *Router)) {
|
|
sub := &Router{
|
|
ServeMux: r.ServeMux,
|
|
routeChain: slices.Clone(r.routeChain),
|
|
isSub: true,
|
|
}
|
|
|
|
// Añadir middleware para manejar el basePath
|
|
sub.Use(func(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
if !strings.HasPrefix(req.URL.Path, basePath) {
|
|
http.NotFound(w, req)
|
|
return
|
|
}
|
|
req.URL.Path = strings.TrimPrefix(req.URL.Path, basePath)
|
|
next.ServeHTTP(w, req)
|
|
})
|
|
})
|
|
|
|
fn(sub)
|
|
}
|
|
|
|
func (r *Router) Static(urlPrefix, dir string) {
|
|
urlPrefix = strings.TrimSuffix(urlPrefix, "/")
|
|
|
|
fileServer := http.FileServer(http.Dir(dir))
|
|
fs := http.StripPrefix(urlPrefix, http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
fullPath := filepath.Join(dir, req.URL.Path)
|
|
|
|
info, err := os.Stat(fullPath)
|
|
if err != nil {
|
|
http.NotFound(w, req)
|
|
return
|
|
}
|
|
if info.IsDir() {
|
|
http.NotFound(w, req)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Cache-Control", "public, max-age=31536000, immutable")
|
|
|
|
fileServer.ServeHTTP(w, req)
|
|
}))
|
|
|
|
r.Handle(urlPrefix+"/", fs)
|
|
}
|
|
|
|
func (r *Router) HandleFunc(pattern string, h http.HandlerFunc) {
|
|
r.Handle(pattern, h)
|
|
}
|
|
|
|
func (r *Router) Handle(pattern string, h http.Handler) {
|
|
chain := slices.Clone(r.routeChain)
|
|
slices.Reverse(chain)
|
|
for _, mw := range chain {
|
|
h = mw(h)
|
|
}
|
|
r.ServeMux.Handle(pattern, h)
|
|
}
|
|
|
|
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|
h := http.Handler(r.ServeMux)
|
|
chain := slices.Clone(r.globalChain)
|
|
slices.Reverse(chain)
|
|
for _, mw := range chain {
|
|
h = mw(h)
|
|
}
|
|
h.ServeHTTP(w, req)
|
|
}
|