Fuego Documentation

website·Indexed 32 days ago

http://go-fuego.dev/

A Go web framework featuring automatic OpenAPI generation, support for net/http middlewares, and flexible rendering options including html/template, Templ, and Gomponents. It provides tools for input/output transformation, struct tag validation, and incremental migration from other routers like Gin and Echo via dedicated adaptors.

Tokens
21.1K
Snippets
116
Records
132
Agent score
59%

What's inside Fuego

  1. Understand Fuego's core architectural components

    Fuego's architecture is built around four primary components that manage the lifecycle of a request and the integration with web frameworks:

    • Engine: The core of Fuego. It handles requests and responses, manages the OpenAPI struct (containing the API description and utilities), and provides a centralized Error Handler.
    • Server: A standard net/http server implementation used to listen for incoming requests and manage routes, groups, and middlewares.
    • Adaptors: Integration layers that allow Fuego to be used with third-party web frameworks such as Gin or Echo.
    • Context: A generic typed interface representing the state that developers can access and modify within a controller.
  2. Understand Fuego's core architectural components

    Fuego's architecture is built around four primary components:

    1. Engine: The core of Fuego. It handles requests and responses, manages the OpenAPI struct (including descriptions and utilities), and provides a centralized Error Handler.
    2. Server: A default net/http server used to listen for incoming requests. It manages routes, groups, and middlewares.
    3. Adaptors: Integration layers that allow Fuego to be used with other web frameworks such as Gin or Echo.
    4. Context: A generic typed interface representing the state that users can access and modify within a controller.
  3. Automatically generate OpenAPI specifications with Fuego

    Fuego automatically generates an OpenAPI specification for your API based on your route definitions. By default, it provides a Swagger UI and a JSON endpoint to view the specification.
    package main
    
    import (
    	"github.com/go-fuego/fuego"
    )
    
    func main() {
    	s := fuego.NewServer()
    
    	fuego.Get(s, "/", helloWorld)
    
    	s.Run()
    }
    
    func helloWorld(c fuego.ContextNoBody) (string, error) {
    	return "Hello, World!", nil
    }
  4. Apply middlewares to a specific route

    Fuego allows adding net/http compatible middlewares to individual routes by passing option.Middleware as an argument to the route handler method (e.g., fuego.Get). Middlewares are executed in the order they are declared.
    package main
    
    import (
    	"github.com/go-fuego/fuego"
    )
    
    func main() {
    	s := fuego.NewServer()
    
    	// Declare the middlewares after the route handler
    	fuego.Get(s, "/", myController,
    		option.QueryInt("page", "The page number"),
    		option.Middleware(middleware1),
    		option.Middleware(middleware2, middleware3),
    	)
    
    	s.Run()
    }
  5. Define route-level options and OpenAPI metadata

    Route options are passed during route registration to define query parameters, summaries, descriptions, and tags for OpenAPI documentation. You can use built-in options from the option package or create custom functions that modify the fuego.BaseRoute struct. For reusability, use option.Group to bundle multiple options together.
    package main
    
    import (
    	"github.com/go-fuego/fuego"
    	"github.com/go-fuego/fuego/option"
    	"github.com/go-fuego/fuego/param"
    )
    
    // Reusable group of options
    var myReusableOption = option.Group(
    	option.QueryInt("per_page", "Number of items per page", param.Default(100), param.Example("100 per page", 100)),
    	option.QueryInt("page", "Page number", param.Default(1), param.Example("page 9", 9)),
    )
    
    func main() {
    	s := fuego.NewServer()
    
    	fuego.Get(s, "/", myController,
    		option.Query("name", "Name of the user", param.Required(), param.Example("example 1", "Napoleon")),
    		option.Summary("Name getting route"),
    		option.Description("This is the longdescription of the route"),
    		option.Tags("Name", "Getting"),
    		myReusableOption,
    	)
    
    	s.Run()
    }
  6. Render Templ components in Fuego handlers

    Fuego supports templating with Templ. To render a Templ component, set the handler's return type to fuego.Templ.

    Because fuego.Templ is an alias for fuego.CtxRenderer, any type that implements the Render(context.Context, io.Writer) error method can be used as a return type for a handler.

    import (
    	"github.com/go-fuego/fuego"
    )
    
    // Handler returning a Templ component
    func (rs Resource) adminIngredients(c fuego.ContextNoBody) (fuego.Templ, error) {
    	// ... logic to fetch data ...
    
    	// Return the Templ component and nil error
    	return admin.IngredientList(ingredients, searchParams), nil
    }
  7. Incrementally migrate a Gin application to Fuego

    You can migrate an existing Gin application to Fuego without rewriting all controllers at once by following these steps:

    1. Initialize the Fuego engine using fuego.NewEngine().
    2. Wrap existing Gin routes using fuegogin.GetGin instead of gin.GET. This adds OpenAPI declarations to the routes without requiring changes to the existing controllers.
    3. Gradually replace existing Gin controllers with Fuego controllers one by one to enable full OpenAPI documentation, validation, and Content-Negotiation for those specific endpoints.
  8. Transform outgoing response data with OutTransform

    To transform data before it is sent to the client, implement the fuego.OutTransformer interface by adding an OutTransform(ctx context.Context) error method to your response struct. This method is called automatically after the controller returns the response struct but before it is serialized to JSON/XML. This is ideal for masking sensitive data, calculating derived fields, or adding request-specific metadata from the context.
    package main
    
    import (
    	"context"
    	"github.com/go-fuego/fuego"
    )
    
    type UserResponse struct {
    	FirstName string `json:"first_name"`
    	LastName  string `json:"last_name"`
    	FullName  string `json:"full_name"`
    }
    
    // OutTransform implements fuego.OutTransformer
    func (u *UserResponse) OutTransform(ctx context.Context) error {
    	// Mask the last name for privacy
    	if len(u.LastName) > 0 {
    		u.LastName = u.LastName[:1] + "***"
    	}
    
    	// Generate the full name
    	u.FullName = u.FirstName + " " + u.LastName
    	return nil
    }
    
    var _ fuego.OutTransformer = (*UserResponse)(nil)
    
    func getUser(c fuego.ContextNoBody) (UserResponse, error) {
    	user := UserResponse{
    		FirstName: "John",
    		LastName:  "Doe",
    	}
    	// OutTransform is called automatically before serialization
    	return user, nil
    }
  9. Set up hot reloading for Go applications using Air

    Hot reload allows developers to see code changes in real-time without manually restarting the server. This is achieved using the air command-line tool, which monitors files for changes and triggers a rebuild and restart of the application.
    # Install the air CLI tool
    go install github.com/air-verse/air@latest
    
    # (Optional) Initialize a .air.toml configuration file to customize behavior
    air init
    
    # Start the server with hot reload enabled
    air
  10. Handle binary request bodies

    To read a request body as a raw byte slice, use []byte as the receiver type in fuego.ContextWithBody. The request must have the Content-Type header set to application/octet-stream.
    fuego.Put(s, "/blob", func(c fuego.ContextWithBody[[]byte]) (any, error) {
    	body, err := c.Body()
    	if err != nil {
    		return nil, err
    	}
    
    	return body, nil
    })
  11. Incrementally migrate Echo routes to Fuego

    Follow these steps to transition an Echo application to Fuego without a full rewrite:

    1. Initialize the Engine: Use fuego.NewEngine() to instantiate the Fuego engine.
    2. Wrap Existing Routes: Replace echo.GET (and other Echo methods) with fuegoecho.GetEcho. This wraps your existing controllers with OpenAPI declarations without requiring changes to the controller logic itself.
    3. Replace Controllers: Gradually replace the wrapped controllers with native Fuego controllers using fuegoecho.Get, fuegoecho.Post, etc. This enables full automatic OpenAPI documentation, request validation, and content-negotiation.
    // Instead of:
    // echo.GET("/path", handler)
    
    // Step 2: Wrap existing Echo handler
    fuegoecho.GetEcho("/path", handler)
    
    // Step 3: Fully migrate to Fuego controller
    fuegoecho.Get("/path", fuegoHandler)
  12. Handle path and wildcard parameters

    Fuego supports two types of path parameters:

    1. Named Parameters: Defined using {paramName}. Access them in the controller using c.PathParam("paramName").
    2. Wildcard Parameters: Defined using {param...} to match all remaining segments of a path (catch-all). Access the full matched path using c.PathParam("param").
    // Named parameter example
    func getBook(c fuego.ContextNoBody) (string, error) {
    	id := c.PathParam("id")
    	return "Book ID: " + id, nil
    }
    
    // Wildcard parameter example
    // Route: fuego.Get(s, "/files/{path...}", getFile)
    func getFile(c fuego.ContextNoBody) (string, error) {
    	path := c.PathParam("path")
    	return "File path: " + path, nil
    }