Skip to content

Commit

Permalink
Generic route registration
Browse files Browse the repository at this point in the history
  • Loading branch information
EwenQuim committed Dec 24, 2024
1 parent c93b8d1 commit 213c766
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 21 deletions.
34 changes: 21 additions & 13 deletions extra/fuegogin/adaptor.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package fuegogin

import (
"log/slog"
"net/http"

"github.com/gin-gonic/gin"
Expand All @@ -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.
Expand Down
19 changes: 19 additions & 0 deletions generic_mux.go
Original file line number Diff line number Diff line change
@@ -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
}
33 changes: 25 additions & 8 deletions mux.go → net_http_mux.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
}

Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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)
}
File renamed without changes.

0 comments on commit 213c766

Please sign in to comment.