diff --git a/extra/fuegogin/adaptor.go b/extra/fuegogin/adaptor.go index c1693e64..4d3a4c11 100644 --- a/extra/fuegogin/adaptor.go +++ b/extra/fuegogin/adaptor.go @@ -1,7 +1,6 @@ package fuegogin import ( - "log/slog" "net/http" "github.com/gin-gonic/gin" @@ -28,27 +27,36 @@ func Post[T, B any](engine *fuego.Engine, ginRouter gin.IRouter, path string, ha func handleFuego[T, B any](engine *fuego.Engine, ginRouter gin.IRouter, method, path string, fuegoHandler func(c fuego.ContextWithBody[B]) (T, error), options ...func(*fuego.BaseRoute)) *fuego.Route[T, B] { baseRoute := fuego.NewBaseRoute(method, path, fuegoHandler, engine.OpenAPI, options...) - return handle(engine, ginRouter, &fuego.Route[T, B]{BaseRoute: baseRoute}, GinHandler(engine, fuegoHandler, baseRoute)) + return fuego.Registers(engine, ginRouteRegisterer[T, B]{ + ginRouter: ginRouter, + route: fuego.Route[T, B]{BaseRoute: baseRoute}, + ginHandler: GinHandler(engine, fuegoHandler, baseRoute), + }) } func handleGin(engine *fuego.Engine, ginRouter gin.IRouter, method, path string, ginHandler gin.HandlerFunc, options ...func(*fuego.BaseRoute)) *fuego.Route[any, any] { baseRoute := fuego.NewBaseRoute(method, path, ginHandler, engine.OpenAPI, options...) - return handle(engine, ginRouter, &fuego.Route[any, any]{BaseRoute: baseRoute}, ginHandler) + return fuego.Registers(engine, ginRouteRegisterer[any, any]{ + ginRouter: ginRouter, + route: fuego.Route[any, any]{BaseRoute: baseRoute}, + ginHandler: ginHandler, + }) } -func handle[T, B any](engine *fuego.Engine, ginRouter gin.IRouter, route *fuego.Route[T, B], ginHandler gin.HandlerFunc) *fuego.Route[T, B] { - if _, ok := ginRouter.(*gin.RouterGroup); ok { - route.Path = ginRouter.(*gin.RouterGroup).BasePath() + route.Path - } - - ginRouter.Handle(route.Method, route.Path, ginHandler) +type ginRouteRegisterer[T, B any] struct { + ginRouter gin.IRouter + ginHandler gin.HandlerFunc + route fuego.Route[T, B] +} - err := route.RegisterOpenAPIOperation(engine.OpenAPI) - if err != nil { - slog.Warn("error documenting openapi operation", "error", err) +func (a ginRouteRegisterer[T, B]) Register() fuego.Route[T, B] { + if _, ok := a.ginRouter.(*gin.RouterGroup); ok { + a.route.Path = a.ginRouter.(*gin.RouterGroup).BasePath() + a.route.Path } - return route + a.ginRouter.Handle(a.route.Method, a.route.Path, a.ginHandler) + + return a.route } // Convert a Fuego handler to a Gin handler. diff --git a/generic_mux.go b/generic_mux.go new file mode 100644 index 00000000..354ac752 --- /dev/null +++ b/generic_mux.go @@ -0,0 +1,19 @@ +package fuego + +import "log/slog" + +// Registerer is an interface that allows registering routes. +// It can be implementable by any router. +type Registerer[T, B any] interface { + Register() Route[T, B] +} + +func Registers[B, T any](engine *Engine, a Registerer[B, T]) *Route[B, T] { + route := a.Register() + + err := route.RegisterOpenAPIOperation(engine.OpenAPI) + if err != nil { + slog.Warn("error documenting openapi operation", "error", err) + } + return &route +} diff --git a/mux.go b/net_http_mux.go similarity index 90% rename from mux.go rename to net_http_mux.go index 854d57ad..7450dd97 100644 --- a/mux.go +++ b/net_http_mux.go @@ -69,7 +69,9 @@ func Patch[T, B any](s *Server, path string, controller func(ContextWithBody[B]) return registerFuegoController(s, http.MethodPatch, path, controller, options...) } -// Register registers a controller into the default mux and documents it in the OpenAPI spec. +// Register registers a controller into the default net/http mux. +// +// Deprecated: Used internally. Please satisfy the [Registerer] interface instead and pass to [Registers]. func Register[T, B any](s *Server, route Route[T, B], controller http.Handler, options ...func(*BaseRoute)) *Route[T, B] { for _, o := range options { o(&route.BaseRoute) @@ -86,11 +88,6 @@ func Register[T, B any](s *Server, route Route[T, B], controller http.Handler, o route.Middlewares = append(s.middlewares, route.Middlewares...) s.Mux.Handle(fullPath, withMiddlewares(controller, route.Middlewares...)) - err := route.RegisterOpenAPIOperation(s.OpenAPI) - if err != nil { - slog.Warn("error documenting openapi operation", "error", err) - } - return &route } @@ -144,13 +141,21 @@ func registerFuegoController[T, B any](s *Server, method, path string, controlle acceptHeaderParameter.Schema = openapi3.NewStringSchema().NewRef() route.Operation.AddParameter(acceptHeaderParameter) - return Register(s, route, HTTPHandler(s, controller, route.BaseRoute)) + return Registers(s.Engine, netHttpRouteRegisterer[T, B]{ + s: s, + route: route, + controller: HTTPHandler(s, controller, route.BaseRoute), + }) } func registerStdController(s *Server, method, path string, controller func(http.ResponseWriter, *http.Request), options ...func(*BaseRoute)) *Route[any, any] { route := NewRoute[any, any](method, path, controller, s.OpenAPI, append(s.routeOptions, options...)...) - return Register(s, route, http.HandlerFunc(controller)) + return Registers(s.Engine, netHttpRouteRegisterer[any, any]{ + s: s, + route: route, + controller: http.HandlerFunc(controller), + }) } func withMiddlewares(controller http.Handler, middlewares ...func(http.Handler) http.Handler) http.Handler { @@ -216,3 +221,15 @@ func DefaultDescription[T any](handler string, middlewares []T) string { return description + "\n\n---\n\n" } + +type netHttpRouteRegisterer[T, B any] struct { + s *Server + controller http.Handler + route Route[T, B] +} + +var _ Registerer[string, any] = netHttpRouteRegisterer[string, any]{} + +func (a netHttpRouteRegisterer[T, B]) Register() Route[T, B] { + return *Register(a.s, a.route, a.controller) +} diff --git a/mux_test.go b/net_http_mux_test.go similarity index 100% rename from mux_test.go rename to net_http_mux_test.go