golang高效生成OpenAPI 3规范的Web框架插件Fuego的使用

Golang高效生成OpenAPI 3规范的Web框架插件Fuego的使用

Fuego是一个为忙碌的Go开发者设计的框架,它能自动从代码生成OpenAPI 3规范文档,而无需依赖注释或YAML文件。

Fuego Logo

主要特性

  • 自动生成OpenAPI文档:直接从代码生成,无需额外注释
  • 100%兼容net/http:可以无缝使用任何http.Handler中间件
  • 内置路由:基于Go 1.22 net/http的路由系统
  • 自动序列化/反序列化:支持JSON、XML和HTML表单
  • 内置验证:基于go-playground/validator的验证系统
  • 数据转换:通过InTransform和OutTransform接口实现
  • 中间件支持:兼容标准net/http中间件
  • 错误处理:遵循RFC 9457标准
  • 渲染支持:内置html/template支持

快速入门示例

Hello World示例

package main

import "github.com/go-fuego/fuego"

func main() {
	s := fuego.NewServer()

	fuego.Get(s, "/", func(c fuego.ContextNoBody) (string, error) {
		return "Hello, World!", nil
	})

	s.Run()
}

简单POST请求示例

package main

import "github.com/go-fuego/fuego"

type MyInput struct {
	Name string `json:"name" validate:"required"`
}

type MyOutput struct {
	Message string `json:"message"`
}

func main() {
	s := fuego.NewServer()

	// 自动为这个路由生成OpenAPI文档
	fuego.Post(s, "/user/{user}", myController)

	s.Run()
}

func myController(c fuego.ContextWithBody[MyInput]) (*MyOutput, error) {
	body, err := c.Body()
	if err != nil {
		return nil, err
	}

	return &MyOutput{Message: "Hello, " + body.Name}, nil
}

数据转换和自定义验证

type MyInput struct {
	Name string `json:"name" validate:"required"`
}

// 在返回c.Body()之前调用
func (r *MyInput) InTransform(context.Context) error {
	r.Name = strings.ToLower(r.Name)

	if r.Name == "fuego" {
		return errors.New("fuego is not a valid name for this input")
	}

	return nil
}

完整OpenAPI文档示例

package main

import (
	"github.com/go-fuego/fuego"
	"github.com/go-fuego/fuego/option"
	"github.com/go/fuego/param"
)

func main() {
	s := fuego.NewServer()

	// 自定义OpenAPI选项
	fuego.Post(s, "/", myController,
		option.Description("This route does something..."),
		option.Summary("This is my summary"),
		option.Tags("MyTag"), // 根据返回类型自动设置标签(可禁用)
		option.Deprecated(),  // 在OpenAPI规范中标记为弃用

		option.Query("name", "Declares a query parameter with default value", param.Default("Carmack")),
		option.Header("Authorization", "Bearer token", param.Required()),
		optionPagination,
		optionCustomBehavior,
	)

	s.Run()
}

var optionPagination = option.Group(
	option.QueryInt("page", "Page number", param.Default(1), param.Example("1st page", 1), param.Example("42nd page", 42)),
	option.QueryInt("perPage", "Number of items per page"),
)

var optionCustomBehavior = func(r *fuego.BaseRoute) {
	r.XXX = "YYY"
}

标准库兼容示例

package main

import (
	"net/http"

	"github.com/go-fuego/fuego"
)

func main() {
	s := fuego.NewServer()

	// 标准net/http中间件
	fuego.Use(s, func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			w.Header().Set("X-Hello", "World")
			next.ServeHTTP(w, r)
		})
	})

	// 标准net/http处理器,自动生成OpenAPI路由声明
	fuego.GetStd(s, "/std", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("Hello, World!"))
	})

	s.Run()
}

完整示例

package main

import (
	"context"
	"errors"
	"net/http"
	"strings"

	chiMiddleware "github.com/go-chi/chi/v5/middleware"
	"github.com/go-fuego/fuego"
	"github.com/rs/cors"
)

type Received struct {
	Name string `json:"name" validate:"required"`
}

type MyResponse struct {
	Message       string `json:"message"`
	BestFramework string `json:"best"`
}

func main() {
	s := fuego.NewServer(
		fuego.WithAddr("localhost:8088"),
	)

	fuego.Use(s, cors.Default().Handler)
	fuego.Use(s, chiMiddleware.Compress(5, "text/html", "text/css"))

	// Fuego处理器,自动生成OpenAPI、验证、(反)序列化和错误处理
	fuego.Post(s, "/", func(c fuego.ContextWithBody[Received]) (MyResponse, error) {
		data, err := c.Body()
		if err != nil {
			return MyResponse{}, err
		}

		c.Response().Header().Set("X-Hello", "World")

		return MyResponse{
			Message:       "Hello, " + data.Name,
			BestFramework: "Fuego!",
		}, nil
	})

	// 标准net/http处理器,自动生成OpenAPI路由声明
	fuego.GetStd(s, "/std", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("Hello, World!"))
	})

	s.Run()
}

// 在使用c.Body()时调用InTransform
// 可用于转换实体和引发自定义错误
func (r *Received) InTransform(context.Context) error {
	r.Name = strings.ToLower(r.Name)
	if r.Name == "fuego" {
		return errors.New("fuego is not a name")
	}
	return nil
}

// 在发送数据前调用OutTransform
func (r *MyResponse) OutTransform(context.Context) error {
	r.Message = strings.ToUpper(r.Message)
	return nil
}

使用Fuego的优势

  1. 从代码自动生成OpenAPI文档,无需维护额外文件
  2. 内置数据验证和转换功能
  3. 完全兼容标准net/http
  4. 简化API开发流程
  5. 提供丰富的OpenAPI定制选项

Fuego特别适合需要快速开发API并自动生成文档的项目,它减少了开发者的重复工作,同时保持了Go标准库的兼容性。


更多关于golang高效生成OpenAPI 3规范的Web框架插件Fuego的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang高效生成OpenAPI 3规范的Web框架插件Fuego的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用Fuego高效生成OpenAPI 3规范的Golang Web框架插件

Fuego是一个专为Golang Web框架设计的插件,能够高效生成OpenAPI 3.0规范文档。它支持多种流行框架如Gin、Echo等,通过代码注释自动生成API文档,大幅提升开发效率。

Fuego核心特性

  1. 自动生成OpenAPI 3.0规范
  2. 支持多种Web框架
  3. 基于代码注释的文档生成
  4. 内置Swagger UI集成
  5. 类型安全的参数定义

安装Fuego

go get github.com/swaggest/fuego

基本使用示例

1. Gin框架集成

package main

import (
	"github.com/gin-gonic/gin"
	"github.com/swaggest/fuego"
	"github.com/swaggest/openapi-go/openapi3"
)

// @title 用户API
// @version 1.0
// @description 用户管理接口
func main() {
	r := gin.Default()

	// 初始化Fuego
	reflector := &openapi3.Reflector{}
	fuegoServer := fuego.NewServer(reflector)

	// 添加路由
	r.GET("/users", GetUsers)
	
	// 注册OpenAPI路由
	fuego.RegisterOpenAPI3Route(r, "/openapi.json", fuegoServer)
	fuego.RegisterSwaggerUIRoute(r, "/docs", "/openapi.json")

	r.Run(":8080")
}

// GetUsers 获取用户列表
// @summary 获取用户列表
// @description 返回所有用户数据
// @tags 用户
// @produce json
// @success 200 {array} User
// @router /users [get]
func GetUsers(c *gin.Context) {
	users := []User{
		{ID: 1, Name: "张三"},
		{ID: 2, Name: "李四"},
	}
	c.JSON(200, users)
}

type User struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
}

2. Echo框架集成

package main

import (
	"github.com/labstack/echo/v4"
	"github.com/swaggest/fuego"
	"github.com/swaggest/openapi-go/openapi3"
)

func main() {
	e := echo.New()

	reflector := &openapi3.Reflector{}
	fuegoServer := fuego.NewServer(reflector)

	e.GET("/products", GetProducts)
	
	fuego.RegisterOpenAPI3RouteEcho(e, "/openapi.json", fuegoServer)
	fuego.RegisterSwaggerUIRouteEcho(e, "/docs", "/openapi.json")

	e.Start(":8080")
}

// GetProducts 获取产品列表
// @summary 获取产品
// @description 返回所有产品数据
// @tags 产品
// @param category query string false "产品分类"
// @produce json
// @success 200 {array} Product
// @router /products [get]
func GetProducts(c echo.Context) error {
	category := c.QueryParam("category")
	products := []Product{
		{ID: 1, Name: "产品A", Category: "电子"},
		{ID: 2, Name: "产品B", Category: "家居"},
	}
	
	if category != "" {
		var filtered []Product
		for _, p := range products {
			if p.Category == category {
				filtered = append(filtered, p)
			}
		}
		return c.JSON(200, filtered)
	}
	
	return c.JSON(200, products)
}

type Product struct {
	ID       int    `json:"id"`
	Name     string `json:"name"`
	Category string `json:"category"`
}

高级功能

1. 请求体和响应体定义

// CreateUser 创建用户
// @summary 创建新用户
// @tags 用户
// @accept json
// @param request body CreateUserRequest true "用户信息"
// @produce json
// @success 201 {object} User
// @router /users [post]
func CreateUser(c *gin.Context) {
	var req CreateUserRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(400, gin.H{"error": err.Error()})
		return
	}
	
	// 处理创建逻辑
	user := User{
		ID:   3,
		Name: req.Name,
	}
	
	c.JSON(201, user)
}

type CreateUserRequest struct {
	Name  string `json:"name" required:"true" minLength:"2" maxLength:"50"`
	Email string `json:"email" format:"email"`
}

2. 认证配置

// 在main函数中配置认证
reflector.SpecEns().SecuritySchemes = map[string]openapi3.SecuritySchemeOrRef{
	"BearerAuth": {
		SecurityScheme: &openapi3.SecurityScheme{
			Type:         "http",
			Scheme:       "bearer",
			BearerFormat: "JWT",
		},
	},
}

// 在路由注释中使用
// GetProfile 获取用户资料
// @summary 获取当前用户资料
// @tags 用户
// @security BearerAuth
// @produce json
// @success 200 {object} User
// @router /profile [get]
func GetProfile(c *gin.Context) {
	// 实现代码
}

最佳实践

  1. 保持注释完整:为每个路由添加完整的注释信息
  2. 使用结构体验证:利用结构体标签定义参数验证规则
  3. 分模块组织:为大型项目创建多个OpenAPI文档
  4. 版本控制:在API路径中包含版本号
  5. 定期审查:定期检查生成的文档与实际API的一致性

Fuego通过简洁的注释语法和强大的自动生成能力,显著减少了维护API文档的工作量,是Golang Web开发中提升效率的利器。

回到顶部