Skip to content

Commit

Permalink
Refactor, mutualize and document Route object
Browse files Browse the repository at this point in the history
  • Loading branch information
EwenQuim committed Dec 16, 2024
1 parent a256a7c commit c3bcab3
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 107 deletions.
78 changes: 39 additions & 39 deletions examples/petstore/lib/testdata/doc/openapi.golden.json
Original file line number Diff line number Diff line change
Expand Up @@ -155,13 +155,6 @@
"description": "#### Controller: \n\n`github.com/go-fuego/fuego/examples/petstore/controllers.PetsResources.filterPets`\n\n---\n\nFilter pets",
"operationId": "GET_/pets/",
"parameters": [
{
"in": "header",
"name": "Accept",
"schema": {
"type": "string"
}
},
{
"description": "header description",
"in": "header",
Expand Down Expand Up @@ -221,6 +214,13 @@
"default": 3,
"type": "integer"
}
},
{
"in": "header",
"name": "Accept",
"schema": {
"type": "string"
}
}
],
"responses": {
Expand Down Expand Up @@ -306,16 +306,16 @@
"operationId": "POST_/pets/",
"parameters": [
{
"description": "header description",
"in": "header",
"name": "Accept",
"name": "X-Header",
"schema": {
"type": "string"
}
},
{
"description": "header description",
"in": "header",
"name": "X-Header",
"name": "Accept",
"schema": {
"type": "string"
}
Expand Down Expand Up @@ -398,13 +398,6 @@
"description": "#### Controller: \n\n`github.com/go-fuego/fuego/examples/petstore/controllers.PetsResources.getAllPets`\n\n---\n\nGet all pets",
"operationId": "GET_/pets/all",
"parameters": [
{
"in": "header",
"name": "Accept",
"schema": {
"type": "string"
}
},
{
"description": "header description",
"in": "header",
Expand Down Expand Up @@ -441,6 +434,13 @@
"default": 1,
"type": "integer"
}
},
{
"in": "header",
"name": "Accept",
"schema": {
"type": "string"
}
}
],
"responses": {
Expand Down Expand Up @@ -529,16 +529,16 @@
"operationId": "GET_/pets/by-age",
"parameters": [
{
"description": "header description",
"in": "header",
"name": "Accept",
"name": "X-Header",
"schema": {
"type": "string"
}
},
{
"description": "header description",
"in": "header",
"name": "X-Header",
"name": "Accept",
"schema": {
"type": "string"
}
Expand Down Expand Up @@ -608,16 +608,16 @@
"operationId": "GET_/pets/by-name/:name...",
"parameters": [
{
"description": "header description",
"in": "header",
"name": "Accept",
"name": "X-Header",
"schema": {
"type": "string"
}
},
{
"description": "header description",
"in": "header",
"name": "X-Header",
"name": "Accept",
"schema": {
"type": "string"
}
Expand Down Expand Up @@ -743,16 +743,16 @@
"operationId": "DELETE_/pets/:id",
"parameters": [
{
"description": "header description",
"in": "header",
"name": "Accept",
"name": "X-Header",
"schema": {
"type": "string"
}
},
{
"description": "header description",
"in": "header",
"name": "X-Header",
"name": "Accept",
"schema": {
"type": "string"
}
Expand Down Expand Up @@ -815,13 +815,6 @@
"description": "Replace description with this sentence.",
"operationId": "getPet",
"parameters": [
{
"in": "header",
"name": "Accept",
"schema": {
"type": "string"
}
},
{
"description": "header description",
"in": "header",
Expand All @@ -843,6 +836,13 @@
"schema": {
"type": "string"
}
},
{
"in": "header",
"name": "Accept",
"schema": {
"type": "string"
}
}
],
"responses": {
Expand Down Expand Up @@ -895,16 +895,16 @@
"operationId": "PUT_/pets/:id",
"parameters": [
{
"description": "header description",
"in": "header",
"name": "Accept",
"name": "X-Header",
"schema": {
"type": "string"
}
},
{
"description": "header description",
"in": "header",
"name": "X-Header",
"name": "Accept",
"schema": {
"type": "string"
}
Expand Down Expand Up @@ -981,16 +981,16 @@
"operationId": "PUT_/pets/:id/json",
"parameters": [
{
"description": "header description",
"in": "header",
"name": "Accept",
"name": "X-Header",
"schema": {
"type": "string"
}
},
{
"description": "header description",
"in": "header",
"name": "X-Header",
"name": "Accept",
"schema": {
"type": "string"
}
Expand Down
62 changes: 4 additions & 58 deletions mux.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,37 +44,6 @@ func Group(s *Server, path string, routeOptions ...func(*BaseRoute)) *Server {
return newServer
}

type Route[ResponseBody any, RequestBody any] struct {
BaseRoute
}

type BaseRoute struct {
Operation *openapi3.Operation // GENERATED OpenAPI operation, do not set manually in Register function. You can change it after the route is registered.
Method string // HTTP method (GET, POST, PUT, PATCH, DELETE)
Path string // URL path. Will be prefixed by the base path of the server and the group path if any
Handler http.Handler // handler executed for this route
FullName string // namespace and name of the function to execute
Params map[string]OpenAPIParam
Middlewares []func(http.Handler) http.Handler
AcceptedContentTypes []string // Content types accepted for the request body. If nil, all content types (*/*) are accepted.
Hidden bool // If true, the route will not be documented in the OpenAPI spec
DefaultStatusCode int // Default status code for the response
OpenAPI *OpenAPI // Ref to the whole OpenAPI spec

overrideDescription bool // Override the default description
}

func (r *BaseRoute) GenerateDefaultDescription() {
if r.overrideDescription {
return
}
r.Operation.Description = DefaultDescription(r.FullName, r.Middlewares) + r.Operation.Description
}

func (r *BaseRoute) GenerateDefaultOperationID() {
r.Operation.OperationID = r.Method + "_" + strings.ReplaceAll(strings.ReplaceAll(r.Path, "{", ":"), "}", "")
}

// Capture all methods (GET, POST, PUT, PATCH, DELETE) and register a controller.
func All[ReturnType, Body any, Contexted ctx[Body]](s *Server, path string, controller func(Contexted) (ReturnType, error), options ...func(*BaseRoute)) *Route[ReturnType, Body] {
return registerFuegoController(s, "", path, controller, options...)
Expand Down Expand Up @@ -173,42 +142,19 @@ func PatchStd(s *Server, path string, controller func(http.ResponseWriter, *http
}

func registerFuegoController[T, B any, Contexted ctx[B]](s *Server, method, path string, controller func(Contexted) (T, error), options ...func(*BaseRoute)) *Route[T, B] {
route := BaseRoute{
Method: method,
Path: path,
Params: make(map[string]OpenAPIParam),
FullName: FuncName(controller),
Operation: &openapi3.Operation{},
OpenAPI: s.OpenAPI,
}
route := NewRoute[T, B](method, path, controller, s.OpenAPI, append(s.routeOptions, options...)...)

acceptHeaderParameter := openapi3.NewHeaderParameter("Accept")
acceptHeaderParameter.Schema = openapi3.NewStringSchema().NewRef()
route.Operation.AddParameter(acceptHeaderParameter)

for _, o := range append(s.routeOptions, options...) {
o(&route)
}

return Register(s, Route[T, B]{BaseRoute: route}, HTTPHandler(s, controller, &route))
return Register(s, route, 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 := BaseRoute{
Method: method,
Path: path,
Params: make(map[string]OpenAPIParam),
FullName: FuncName(controller),
Operation: &openapi3.Operation{},
Handler: http.HandlerFunc(controller),
OpenAPI: s.OpenAPI,
}

for _, o := range append(s.routeOptions, options...) {
o(&route)
}
route := NewRoute[any, any](method, path, controller, s.OpenAPI, append(s.routeOptions, options...)...)

return Register(s, Route[any, any]{BaseRoute: route}, http.HandlerFunc(controller))
return Register(s, route, http.HandlerFunc(controller))
}

func withMiddlewares(controller http.Handler, middlewares ...func(http.Handler) http.Handler) http.Handler {
Expand Down
67 changes: 67 additions & 0 deletions route.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package fuego

import (
"net/http"
"strings"

"github.com/getkin/kin-openapi/openapi3"
)

func NewRoute[T, B any](method, path string, handler any, openapi *OpenAPI, options ...func(*BaseRoute)) Route[T, B] {
return Route[T, B]{
BaseRoute: NewBaseRoute(method, path, handler, openapi, options...),
}
}

// Route is the main struct for a route in Fuego.
// It contains the OpenAPI operation and other metadata.
// It is a wrapper around BaseRoute, with the addition of the response and request body types.
type Route[ResponseBody any, RequestBody any] struct {
BaseRoute
}

func NewBaseRoute(method, path string, handler any, openapi *OpenAPI, options ...func(*BaseRoute)) BaseRoute {
baseRoute := BaseRoute{
Method: method,
Path: path,
Params: make(map[string]OpenAPIParam),
FullName: FuncName(handler),
Operation: openapi3.NewOperation(),
OpenAPI: openapi,
}

for _, o := range options {
o(&baseRoute)
}

return baseRoute
}

// BaseRoute is the base struct for all routes in Fuego.
// It contains the OpenAPI operation and other metadata.
type BaseRoute struct {
Operation *openapi3.Operation // GENERATED OpenAPI operation, do not set manually in Register function. You can change it after the route is registered.
Method string // HTTP method (GET, POST, PUT, PATCH, DELETE)
Path string // URL path. Will be prefixed by the base path of the server and the group path if any
Handler http.Handler // handler executed for this route
FullName string // namespace and name of the function to execute
Params map[string]OpenAPIParam
Middlewares []func(http.Handler) http.Handler
AcceptedContentTypes []string // Content types accepted for the request body. If nil, all content types (*/*) are accepted.
Hidden bool // If true, the route will not be documented in the OpenAPI spec
DefaultStatusCode int // Default status code for the response
OpenAPI *OpenAPI // Ref to the whole OpenAPI spec

overrideDescription bool // Override the default description
}

func (r *BaseRoute) GenerateDefaultDescription() {
if r.overrideDescription {
return
}
r.Operation.Description = DefaultDescription(r.FullName, r.Middlewares) + r.Operation.Description
}

func (r *BaseRoute) GenerateDefaultOperationID() {
r.Operation.OperationID = r.Method + "_" + strings.ReplaceAll(strings.ReplaceAll(r.Path, "{", ":"), "}", "")
}
Loading

0 comments on commit c3bcab3

Please sign in to comment.