2024-12-14 12:35:19 -05:00

126 lines
3.3 KiB
Go

package routing
import (
"errors"
"net/http"
"sync"
"git.markbailey.dev/cerbervs/ptpp/app/controller"
"git.markbailey.dev/cerbervs/ptpp/app/handler"
"git.markbailey.dev/cerbervs/ptpp/app/session"
"git.markbailey.dev/cerbervs/ptpp/lib/database"
werror "git.markbailey.dev/cerbervs/ptpp/lib/error"
"git.markbailey.dev/cerbervs/ptpp/lib/logger"
"git.markbailey.dev/cerbervs/ptpp/lib/middleware"
"git.markbailey.dev/cerbervs/ptpp/util"
)
var sess session.IManager
type IRouter interface {
RegisterRoutes() http.Handler
}
type Route struct {
Controller controller.IController
Path string
Name string
}
type Router struct {
Mux *http.ServeMux
Middleware *[]middleware.Func
BaseRoute Route
BasePath string
SubRouters []*Router
Routes []Route
}
var (
rtr *Router
rtrOnce sync.Once
mux *http.ServeMux
muxOnce sync.Once
fsOnce sync.Once
)
func (r *Router) HandleAllRequestMethods(route Route, fullPath string, mux *http.ServeMux) {
ctx := controller.ControllerCtx{RouterCtx: rtr}
c := route.Controller.Init(sess, database.ChooseDB(), logger.NewCompositeLogger(), ctx)
mux.Handle("GET "+fullPath, handler.HandlerFunc(c.Get))
mux.Handle("OPTIONS "+fullPath, handler.HandlerFunc(c.Options))
mux.Handle("TRACE "+fullPath, handler.HandlerFunc(c.Trace))
mux.Handle("PUT "+fullPath, handler.HandlerFunc(c.Put))
mux.Handle("DELETE "+fullPath, handler.HandlerFunc(c.Delete))
mux.Handle("POST "+fullPath, handler.HandlerFunc(c.Post))
mux.Handle("PATCH "+fullPath, handler.HandlerFunc(c.Patch))
mux.Handle("CONNECT "+fullPath, handler.HandlerFunc(c.Connect))
}
func (r *Router) RegisterRoutes() http.Handler {
rtrOnce.Do(func() { rtr = r })
muxOnce.Do(func() { mux = http.NewServeMux(); r.Mux = mux })
fsOnce.Do(func() { r.RegisterFs() })
if r.Mux == nil {
r.Mux = http.NewServeMux()
}
for _, subRouter := range r.SubRouters {
r.Mux.Handle(subRouter.BasePath, subRouter.RegisterRoutes())
}
r.Mux.Handle(r.BasePath+r.BaseRoute.Path, handler.HandlerFunc(r.BaseRoute.Controller.Get))
for _, route := range r.Routes {
r.HandleAllRequestMethods(route, r.BasePath+route.Path, r.Mux)
}
if r.Middleware != nil {
mw := middleware.Compose(*r.Middleware)
mctx := middleware.MiddlewareCtx{RouterCtx: rtr}
return mw(mux, mctx)
}
return mux
}
func (r *Router) RegisterFs() {
fs := http.FileServer(http.Dir(util.GetFullyQualifiedPath("/public")))
r.Mux.Handle("GET "+r.BasePath+"public/", http.StripPrefix("/public/", fs))
}
type RouteMapping struct {
Path string
Name string
}
func (r *Router) GetFlatRouteList() []RouteMapping {
routes := []RouteMapping{{Path: r.BasePath, Name: r.BaseRoute.Name}}
for _, route := range r.Routes {
routes = append(routes, RouteMapping{Path: r.BasePath + route.Path, Name: route.Name})
}
for _, subRouter := range r.SubRouters {
routes = append(routes, subRouter.GetFlatRouteList()...)
}
return routes
}
func (r *Router) GetRouteByName(name string) (string, error) {
for _, route := range r.GetFlatRouteList() {
if route.Name == name {
return route.Path, nil
}
}
return "", werror.Wrap(errors.New(name+" does not exist"), "Route not found")
}
func init() {
var err error
sess, err = session.NewManager("memory", "ptpp", 3600)
go sess.GC()
if err != nil {
panic(werror.Wrap(err, "Error creating session manager"))
}
}