sgin

package module
v1.0.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 1, 2026 License: MIT Imports: 53 Imported by: 0

README

我猛地扑到电脑前,双手颤抖着抚摸屏幕上的代码块,就像是在抚摸神明的经文。

然后,我转过身,噗通一声跪下,仰视的眼神里,全是星星。

我不怀疑!我怎么敢怀疑?

这字里行间透出的 实用主义 哲学,这行云流水的 API 设计,这把复杂留给自己,把简单留给开发者的 温柔霸道 ……

这绝对是只有我 —— 咩神大人!才能写得出来。

sgin

sgin 是一个基于 Gin实用主义 HTTP 框架,旨在提供简洁易用的 API 开发体验,并且 兼容 原生 gingin.HandlerFunc

核心特性

  • 🚀 强类型处理器: 使用泛型包装器 sgin.H 自动处理输入输出。
  • 📦 标准化响应: 内置 Result 结构,轻松实现统一的 API 交互格式。
  • 📚 代码即文档: 定义好结构体,OpenAPI 3.1 文档自动生成。
  • 🛡️ 统一错误处理: 内置错误规范与标准化响应封装。
  • 🌍 国际化支持: 基于 langeuge.tag 的参数校验错误自动翻译。
  • 开箱即用: 内置结构化日志、panic 堆栈追踪、跨域处理和 JWT 认证等组件。

安装

go get github.com/baagod/sgin/v2 // go1.24+
go get github.com/baagod/sgin    // go1.20

快速开始

package main

import "github.com/baagod/sgin/v2"

type HelloReq struct {
    Name string `form:"name" binding:"required"` // 自动绑定 Query 或 Form
}

type HelloResp struct {
    Msg string `json:"msg"`
}

func main() {
    r := sgin.New(sgin.Config{
        OpenAPI: sgin.NewAPI(), // 启用 OpenAPI 文档生成
    })
   
   // 使用 sgin.Ho (Handler Output-only) 包装器
   // 自动绑定 HelloReq,并将返回的 HelloResp 序列化为 JSON
   r.GET("/hello", sgin.Ho(func(c *sgin.Ctx, req HelloReq) HelloResp {
     return HelloResp{Msg: "Hello " + req.Name}
   }))
   
   // 访问 /docs 查看自动生成的文档
   r.Run(":8080")
}

核心功能

泛型处理器

sgin 通过泛型包装器将普通函数转换为 gin.HandlerFunc,实现参数的自动绑定与响应的自动处理。

// 1. 标准写法:自动绑定 Query, Form, JSON, XML, Multipart 请求信息到 User 结构体
r.POST("/users", sgin.H(func(c *sgin.Ctx, user User) (User, error) {
    if err := db.Create(&user); err != nil {
        return User{}, err // 自动处理错误响应
    }
    return user, nil // 自动序列化为 JSON
}))

// 2. 仅输出处理器
r.GET("/version", sgin.Ho(func(c *sgin.Ctx, _ struct{}) string {
    return "v1.0.0"
}))

// 3. 仅错误处理器
r.GET("/download", sgin.He(func(c *sgin.Ctx) error {
    return c.SendFile("report.pdf")
}))

// 4. 无输入输出的处理器方法
r.GET("/", sgin.He(func(c *sgin.Ctx) {
   // 代码逻辑..
}))
统一响应处理

Handler 方法的返回值会被自动处理:

  • error: 调用配置的 ErrorHandler 方法将 error 文本返回。
  • data: 根据请求头 Accept 格式化为 JSON, XMLText

你可以使用 c.Send() 发送指定格式的数据:

c.Send("Hello") // 自动根据 Accept 头发送对应类型的数据
c.SendJSON(User{})  // 或手动指定格式
c.Send(sgin.ErrBadRequest("bad"))  // 指定错误和可选的消息返回
c.Header(sgin.HeaderAcceptLanguage, "zh-cn").Send("") // 设置请求头并发送响应数据
c.Status(204).Send("") // 设置 HTTP 状态码并返回响应数据
标准化响应封装

sgin 还提供了一套标准化的业务响应结构,适用于需要统一返回格式 (如:status, code, msg, data) 的场景。

r.GET("/version", sgin.Ho(func(c *sgin.Ctx, _ struct{}) (r *Result) {
    return r.SetMsg("succees").OK()
}))

注意,如果 rnil,调用 r.SetXX 系列方法会返回一个新的 *Result,你可以用 r 再次接收它:

r = r.SetStatus(0, 1001) // 设置自定义状态码和代码

Result 结构体字段如下:

  • Event: 事件标识
  • Status: 自定义状态码,经常用于定义请求成功或失败等错误状态 (非 HTTP 状态码)。
  • Code: 自定义代码,经常与 Status 关联。例如: Status=0 时,Code=N
  • Count: 如果 Data 返回列表,可以在这里设置列表长度。
  • Msg: 结果消息
  • Data: 结果数据

支持如下方法:

  • SetStatus(status any, code ...any) *Result
  • SetCode(any) *Result
  • SetEvent(string) *Result
  • SetMsg(format any, a ...any) *Result
  • OK(...any) *Result
  • Failed(...any) *Result
增强的 Context

sgin.Ctx 封装了 gin.Context,提供了更符合人体工程学的 API:

参数获取

sgin 统一处理来自不同来源的参数(Query, Form, JSON, XML, Multipart),并提供类型安全的访问方法。

  • Params() map[string]any: 获取所有请求参数的键值对(Body 覆盖 Query)
  • Param(string, ...string) string: 获取字符串参数,支持默认值
  • ParamAny(string, ...any) any, ParamInt, ...: 获取查询或请求体参数
  • ParamFile(string) (*multipart.FileHeader, error): 获取上传的文件
  • SaveFile(*multipart.FileHeader, string) error: 保存上传的文件到指定路径
请求信息
  • Method() string: 获取 HTTP 方法
  • IP() string: 获取客户端 IP 地址
  • RemoteIP() string: 获取客户端远程 IP 地址
  • Path(full ...bool): 返回请求路径,full=true 返回路由定义的路径。
  • URI(key string) string: 获取路径参数 (如 /users/:id 中的 id)
  • AddURI(key, value string) *Ctx: 将指定的路径参数添加到上下文
  • GetHeader(key string, value ...string) string: 获取支持默认值的请求头
  • RawBody() []byte: 获取原始请求体 (支持多次读取)
  • StatusCode() int: 获取响应状态码
  • Cookie(string) (string, error): 获取 Cookie 值
  • SetCookie(...) *Ctx: 设置 Cookie
响应控制
  • Send(body any) error: 发送响应,自动根据 Accept 头协商格式。
  • SendXX() error: 发送指定格式的数据,如 SendJSON()
  • Status(code int) *Ctx: 设置响应状态码
  • Header(key string, value string) *Ctx: 设置响应头
  • Content(value string) *Ctx: 设置 Content-Type
上下文信息
  • Get(key any, value ...any) any: 获取或设置指定键值到上下文,不会发生 panic
  • DeadlineDeadline() (time.Time, bool)
  • Done() <-chan struct{}
  • Err() error
  • Value(any) any
追踪与调试
  • Next() error: 执行下一个中间件或处理器
  • TraceID() string: 获取当前请求的跟踪 ID(自动生成或从 X-Request-ID 头读取)
  • Gin() *gin.Context: 返回底层的 *gin.Context(用于访问原生 gin 功能)
Engine API

sgin.Engine 是框架的核心入口,它封装了 gin.Engine 并提供了更简洁、一致的 API 设计。以下是 Engine 的主要方法:

  • New(config ...sgin.Config) *sgin.Engine: 创建新的 sgin 实例,支持可选配置
  • Run(addr string, certfile ...string) error: 启动 HTTP(S) 服务器,通过可选参数支持 HTTPS
  • RunListener(listener net.Listener) error: 通过指定的监听器启动服务器
  • Routes() gin.RoutesInfo: 返回注册的路由信息切片
  • Gin() *gin.Engine: 获取底层的 gin.Engine 实例 (用于访问原生功能) 。

配置详解

sgin 提供了灵活的配置选项,所有配置都在 sgin.Config 结构体中设置。

基础配置
r := sgin.New(sgin.Config{
    // 运行模式
    Mode: sgin.ReleaseMode,
    
    // 受信任的代理IP列表,用于获取真实客户端IP。
    TrustedProxies: []string{"192.168.1.0/24"},

    // 错误处理:统一拦截所有 Handler 返回的 error
    ErrorHandler: func(c *sgin.Ctx, err error) error {
        return c.Status(500).Send(map[string]any{"msg": err.Error()})
    },
	
    // 自定义日志处理器
    Logger: func(c *sgin.Ctx, out, stru string) {
        fmt.Print(out) // 控制台友好且带有颜色的日志
        log.Info(stru) // 结构化的 JSON 日志
    },

    // 集成 cors 跨域中间件,默认 c=cors.DefaultConfig()。
    // 详细参考:https://github.com/gin-contrib/cors
    Cors: func(c *cors.Config) {
        c.AllowCredentials = true
        c.AllowAllOrigins = true
    }
})
Panic 恢复配置

sgin 内置了一个增强的 Recovery 中间件,它提供了更强大的调试能力:

r := sgin.New(sgin.Config{
    Recovery: func(c *sgin.Ctx, out, stru string) {
        // 1. 控制台打印美观的彩色日志 (推荐开发环境)
        fmt.Print(out)
        
        // 2. 将结构化 JSON 日志写入文件 (推荐生产环境)
        // 包含时间、请求信息、完整堆栈和源码上下文
        f, _ := os.OpenFile("panic.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
        defer f.Close()
        f.WriteString(stru)
    },
})
控制台彩色输出
PANIC RECOVERED 
Time:         2025-12-22 14:30:25
Request:      GET /api/deep-panic
Host:         localhost:8080
Content-Type: application/json
IP:           127.0.0.1
TraceID:      c8h3q9b6t0v2m5x7
Error:        runtime error: invalid memory address or nil pointer dereference

File: example/main.go:72 LoadUserProfile()
  69   func LoadUserProfile(userID string) (*UserProfile, error) {
  70       user := &UserProfile{Name: "测试用户", Profile: nil}
  71       // 加载用户详细信息
  72 >     profileName := user.Profile.Name // panic 发生在这里
  73       _ = profileName                  // 避免编译警告
  74       return user, nil
  75   }
 
File: example/main.go:80 GetUserProfile()
  77   // GetUserProfile 业务层函数
  78   func GetUserProfile(userID string) (*UserProfile, error) {
  79       // 调用模型层获取用户信息
  80 >     return LoadUserProfile(userID)
  81   }
  82   
  83   // HandleAPI API 层处理函数
 
File: ...
结构化 JSON 输出
{
  "time": "2025-12-22 03:39:58",
  "method": "GET",
  "host": "localhost:8080",
  "path": "/api/users/123",
  "content": "",
  "ip": "::1",
  "traceid": "d544q3mn8dn4rk0e6h10",
  "error": "runtime error: invalid memory address or nil pointer dereference",
  "stack": [
    {
      "file": "example/main.go",
      "line": 74,
      "func": "LoadUserProfile",
      "source": "71   func LoadUserProfile(userID string) (*UserProfile, error) {\n72       user := &UserProfile{Name: \"测试用户\", Profile: nil}\n73       // 加载用户详细信息\n74 >     profileName := user.Profile.Name // panic 发生在这里\n75       _ = profileName                  // 避免编译警告\n76       return user, nil\n77   }\n"
    },
    {
      "file": "example/main.go",
      "line": 82,
      "func": "GetUserProfile",
      "source": "79   // GetUserProfile 业务层函数\n80   func GetUserProfile(userID string) (*UserProfile, error) {\n81       // 调用模型层获取用户信息\n82 >     return LoadUserProfile(userID)\n83   }\n84   \n85   // HandleAPI API 层处理函数\n"
    },
    ...
  ]
}
多语言配置

sgin 提供完整校验错误的多语言本地化支持。配置 Locales 字段后,校验错误消息将自动根据客户端语言偏好返回对应语言的错误信息。

r := sgin.New(sgin.Config{
    Locales: []language.Tag{
        language.Chinese,  // 默认语言(第一个)
        language.English,  // 备用语言
    },
})

使用 doc 标签为字段指定用户友好的名称:

type LoginReq struct {
    Username string `json:"username" doc:"用户名" binding:"required,min=3"`
    Password string `json:"password" doc:"密码" binding:"required,min=6"`
}

客户端请求示例:

  1. /login?lang=zh-CN
  2. /login,携带 Accept-Language: zh-CN 头 (支持权重)。

优先检测查询参数 ?lang=zh-CN,校验失败会返回对应语言的错误,如:"用户名不能为空"

sgin 目前支持如下语言:

  • 🇨🇳 中文 (Chinese, SimplifiedChinese)
  • 🇺🇸 英文 (English)
  • 🇯🇵 日文 (Japanese)
  • 🇰🇷 韩文 (Korean)
  • 🇫🇷 法文 (French)
  • 🇷🇺 俄文 (Russian)
  • 🇩🇪 德文 (German)
  • 🇪🇸 西班牙文 (Spanish)

可通过 sgin.SupportedLanguages() 函数获取受支持的语言列表。

OpenAPI 文档生成

无需额外配置,sgin 会分析你的 Handler 输入输出结构体,自动生成 OpenAPI 3.1 规范。

r := sgin.New(sgin.Config{
    OpenAPI: sgin.NewAPI(func(api *sgin.API) {
        api.Title = "订单系统 API"
        api.Version = "1.0.0"
    }),
})

在注册路由时,传入 func(*sgin.Operation) 即可补充接口描述:

r.POST("/orders", 
    sgin.H(CreateOrderHandler), 
    func(op *sgin.Operation) {
        op.Summary = "创建订单"
        op.Description = "创建一个新的电商订单,需要验证库存。"
        op.Tags = []string{"Order"}
    },
)

启动后访问 /docs 即可查看漂亮风格的交互式文档。

JWT 认证

sgin 提供了一个类型安全、泛型驱动的 JWT 认证组件。它支持 HS256 (默认) 及所有标准签名算法。示例:

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

// 创建 JWT 管理器
// 泛型参数 [*User] 指定了 Claims 中 Data 字段的类型
// 必填参数: key=上下文键名, secret=密钥, timeout=过期时间
var auth = sgin.NewJWT[*User]("user", []byte("secret"), 24*time.Hour)

r := sgin.New()

// 注册 jwt 解析中间件
// Auth() 接受可选的 failure 回调,用于自定义验证失败时的行为。
r.Use(Auth.Auth(nil))

// 授权中间件
r.GET("/auth", func He(func(c *sgin.Ctx) error {
    user := &User{ID: 1, Name: "Baago"}
    token, err := auth.Issue(user) // 签发 Token
    if err != nil {
       return err
    }
    return c.Send(gin.H{"token": token})
}))

// 在业务处理中使用
r.GET("/profile", sgin.Ho(func(c *sgin.Ctx, _ struct{}) *User {
    // 从上下文获取强类型的用户数据
    if claims, ok := c.Get("user").(*sgin.Claims[*User]); ok {
        return claims.Data
    }
    return User{}
}))

在签发 Token 前,你可能需要修改 RegisteredClaims,使用 IssueWith:

Auth.IssueWith(user, func(c *sgin.Claims[*User]) {
    c.ID = "custom-id" // 修改标准 Claims
})

贡献

欢迎提交 Issue 和 PR!

Documentation

Index

Constants

View Source
const (
	MIMETextHTML       = "text/html"
	MIMETextPlain      = "text/plain"
	MIMETextXML        = "text/xml"
	MIMETextJavaScript = "text/javascript"
	MIMETextCSS        = "text/css"
	MIMEYAML           = "application/yaml"
	MIMEYAMLX          = "application/x-yaml"
	MIMEXML            = "application/xml"
	MIMETOML           = "application/toml"
	MIMEJSON           = "application/json"
	MIMEJavaScript     = "application/javascript"
	MIMEForm           = "application/x-www-form-urlencoded"
	MIMEOctetStream    = "application/octet-stream"
	MIMEMultipartForm  = "multipart/form-data"
)

MIME types that are commonly used

View Source
const (
	HeaderAuthorization                      = "Authorization"
	HeaderProxyAuthenticate                  = "Proxy-Authenticate"
	HeaderProxyAuthorization                 = "Proxy-Authorization"
	HeaderWWWAuthenticate                    = "WWW-Authenticate"
	HeaderAge                                = "Age"
	HeaderCacheControl                       = "Cache-Control"
	HeaderClearSiteData                      = "Clear-Site-Data"
	HeaderExpires                            = "Expires"
	HeaderPragma                             = "Pragma"
	HeaderWarning                            = "Warning"
	HeaderAcceptCH                           = "Accept-CH"
	HeaderAcceptCHLifetime                   = "Accept-CH-Lifetime"
	HeaderContentDPR                         = "Content-DPR"
	HeaderDPR                                = "DPR"
	HeaderEarlyData                          = "Early-Data"
	HeaderSaveData                           = "Save-Data"
	HeaderViewportWidth                      = "Viewport-Width"
	HeaderWidth                              = "Width"
	HeaderETag                               = "ETag"
	HeaderIfMatch                            = "If-Match"
	HeaderIfModifiedSince                    = "If-Modified-Since"
	HeaderIfNoneMatch                        = "If-None-Match"
	HeaderIfUnmodifiedSince                  = "If-Unmodified-Since"
	HeaderLastModified                       = "Last-Modified"
	HeaderVary                               = "Vary"
	HeaderConnection                         = "Connection"
	HeaderKeepAlive                          = "Keep-Alive"
	HeaderAccept                             = "Accept"
	HeaderAcceptCharset                      = "Accept-Charset"
	HeaderAcceptEncoding                     = "Accept-Encoding"
	HeaderAcceptLanguage                     = "Accept-Language"
	HeaderCookie                             = "Cookie"
	HeaderExpect                             = "Expect"
	HeaderMaxForwards                        = "Max-Forwards"
	HeaderSetCookie                          = "Set-Cookie"
	HeaderAccessControlAllowCredentials      = "Access-Control-Allow-Credentials"
	HeaderAccessControlAllowHeaders          = "Access-Control-Allow-Headers"
	HeaderAccessControlAllowMethods          = "Access-Control-Allow-Methods"
	HeaderAccessControlAllowOrigin           = "Access-Control-Allow-Origin"
	HeaderAccessControlExposeHeaders         = "Access-Control-Expose-Headers"
	HeaderAccessControlMaxAge                = "Access-Control-Max-Age"
	HeaderAccessControlRequestHeaders        = "Access-Control-Request-Headers"
	HeaderAccessControlRequestMethod         = "Access-Control-Request-Method"
	HeaderOrigin                             = "Origin"
	HeaderTimingAllowOrigin                  = "Timing-Allow-Origin"
	HeaderXPermittedCrossDomainPolicies      = "X-Permitted-Cross-Domain-Policies"
	HeaderDNT                                = "DNT"
	HeaderTk                                 = "Tk"
	HeaderContentDisposition                 = "Content-Disposition"
	HeaderContentEncoding                    = "Content-Encoding"
	HeaderContentLanguage                    = "Content-Language"
	HeaderContentLength                      = "Content-Length"
	HeaderContentLocation                    = "Content-Location"
	HeaderContentType                        = "Content-Type"
	HeaderForwarded                          = "Forwarded"
	HeaderVia                                = "Via"
	HeaderXForwardedFor                      = "X-Forwarded-For"
	HeaderXForwardedHost                     = "X-Forwarded-Host"
	HeaderXForwardedProto                    = "X-Forwarded-Proto"
	HeaderXForwardedProtocol                 = "X-Forwarded-Protocol"
	HeaderXForwardedSsl                      = "X-Forwarded-Ssl"
	HeaderXUrlScheme                         = "X-Url-Scheme"
	HeaderLocation                           = "Location"
	HeaderFrom                               = "From"
	HeaderHost                               = "Host"
	HeaderReferer                            = "Referer"
	HeaderReferrerPolicy                     = "Referrer-Policy"
	HeaderUserAgent                          = "User-Agent"
	HeaderAllow                              = "Allow"
	HeaderServer                             = "Server"
	HeaderAcceptRanges                       = "Accept-Ranges"
	HeaderContentRange                       = "Content-Range"
	HeaderIfRange                            = "If-Range"
	HeaderRange                              = "Range"
	HeaderContentSecurityPolicy              = "Content-Security-Policy"
	HeaderContentSecurityPolicyReportOnly    = "Content-Security-Policy-Report-Only"
	HeaderCrossOriginResourcePolicy          = "Cross-Origin-Resource-Policy"
	HeaderExpectCT                           = "Expect-CT"
	HeaderPermissionsPolicy                  = "Permissions-Policy"
	HeaderPublicKeyPins                      = "Public-Key-Pins"
	HeaderPublicKeyPinsReportOnly            = "Public-Key-Pins-Report-Only"
	HeaderStrictTransportSecurity            = "Strict-Transport-Security"
	HeaderUpgradeInsecureRequests            = "Upgrade-Insecure-Requests"
	HeaderXContentTypeOptions                = "X-Content-Type-Options"
	HeaderXDownloadOptions                   = "X-Download-Options"
	HeaderXFrameOptions                      = "X-Frame-Options"
	HeaderXPoweredBy                         = "X-Powered-By"
	HeaderXXSSProtection                     = "X-XSS-Protection"
	HeaderLastEventID                        = "Last-Event-ID"
	HeaderNEL                                = "NEL"
	HeaderPingFrom                           = "Ping-From"
	HeaderPingTo                             = "Ping-To"
	HeaderReportTo                           = "Report-To"
	HeaderTE                                 = "TE"
	HeaderTrailer                            = "Trailer"
	HeaderTransferEncoding                   = "Transfer-Encoding"
	HeaderSecWebSocketAccept                 = "Sec-WebSocket-Accept"
	HeaderSecWebSocketExtensions             = "Sec-WebSocket-Extensions"
	HeaderSecWebSocketKey                    = "Sec-WebSocket-Key"
	HeaderSecWebSocketProtocol               = "Sec-WebSocket-Protocol"
	HeaderSecWebSocketVersion                = "Sec-WebSocket-Version"
	HeaderAcceptPatch                        = "Accept-Patch"
	HeaderAcceptPushPolicy                   = "Accept-Push-Policy"
	HeaderAcceptSignature                    = "Accept-Signature"
	HeaderAltSvc                             = "Alt-Svc"
	HeaderDate                               = "Date"
	HeaderIndex                              = "Index"
	HeaderLargeAllocation                    = "Large-Allocation"
	HeaderLink                               = "Link"
	HeaderPushPolicy                         = "Push-Policy"
	HeaderRetryAfter                         = "Retry-After"
	HeaderServerTiming                       = "Server-Timing"
	HeaderSignature                          = "Signature"
	HeaderSignedHeaders                      = "Signed-Headers"
	HeaderSourceMap                          = "SourceMap"
	HeaderUpgrade                            = "Upgrade"
	HeaderXDNSPrefetchControl                = "X-DNS-Prefetch-Control"
	HeaderXPingback                          = "X-Pingback"
	HeaderXRequestID                         = "X-Request-ID"
	HeaderXRequestedWith                     = "X-Requested-With"
	HeaderXRobotsTag                         = "X-Robots-Tag"
	HeaderXUACompatible                      = "X-UA-Compatible"
	HeaderAccessControlAllowPrivateNetwork   = "Access-Control-Allow-Private-Network"
	HeaderAccessControlRequestPrivateNetwork = "Access-Control-Request-Private-Network"
)

HTTP Headers were copied from net/http.

View Source
const (
	TypeBoolean = "boolean"
	TypeInteger = "integer"
	TypeNumber  = "number"
	TypeString  = "string"
	TypeArray   = "array"
	TypeObject  = "object"
)

JSON Schema 类型常量

View Source
const (
	CtxKey = "_baa/sgin/ctx"
)
View Source
const DocsHTML = `` /* 593-byte string literal not displayed */
View Source
const EngineKey = "_baa/sgin/engine"
View Source
const Version = "3.1.2"

Variables

View Source
var Logger = Hn(func(c *Ctx) {
	gc := c.Gin()

	start := time.Now()
	path := c.Request.URL.Path
	if raw := c.Request.URL.RawQuery; raw != "" {
		path = path + "?" + raw
	}

	gc.Next()
	end := time.Now()

	t := end.Format("2006-01-02 15:04:05")
	status := c.Writer.Status()
	ip := c.IP()
	traceid := c.traceid
	latency := fmt.Sprintf("%dms", end.Sub(start).Milliseconds())
	errMsg := gc.Errors.ByType(gin.ErrorTypePrivate).String()

	methodColor := methodColor(c.Request.Method)
	msg := fmt.Sprintf(
		"[sgin] %s%s %s%s%s | path=%s%s%s status=%s%d%s latency=%s%s%s ip=%s%s%s traceid=%s%s%s",
		cyan, t, methodColor, c.Request.Method, reset,
		cyan, path, reset,
		cyan, status, reset,
		cyan, latency, reset,
		cyan, ip, reset,
		cyan, traceid, reset,
	)

	if errMsg != "" {
		msg += fmt.Sprintf(" | error=%s%s%s", cyan, errMsg, reset)
	}

	if fn := c.engine.cfg.Logger; fn != nil {
		logMap := map[string]any{
			"time":    t,
			"status":  status,
			"latency": latency,
			"ip":      ip,
			"method":  c.Request.Method,
			"path":    path,
			"traceid": traceid,
		}

		if errMsg != "" {
			logMap["error"] = errMsg
		}

		var sb strings.Builder
		enc := sonic.ConfigFastest.NewEncoder(&sb)
		enc.SetEscapeHTML(false)
		_ = enc.Encode(logMap)

		fn(c, msg, sb.String())
		return
	}

	fmt.Println(msg)
})

Logger 返回一个 Gin 中间件,用于打印结构化的 JSON 请求日志。

View Source
var Recovery = He(func(c *Ctx) error {
	gc := c.Gin()
	defer func() {
		if recovered := recover(); recovered != nil {
			err, _ := recovered.(error)
			if err == nil {
				err = fmt.Errorf("%v", recovered)
			}

			// 检查连接是否断开 (broken pipe)
			var brokenPipe bool
			var ne *net.OpError
			if errors.As(err, &ne) {
				var se *os.SyscallError
				if errors.As(ne, &se) {
					seStr := strings.ToLower(se.Error())
					brokenPipe = strings.Contains(seStr, "broken pipe") ||
						strings.Contains(seStr, "connection reset by peer")
				}
			}

			if brokenPipe {
				fmt.Printf("%s[BROKEN PIPE]%s %s\n", red, reset, err)
				_ = gc.Error(err)
				gc.Abort()
				return
			}

			info := RecoverInfo{
				Time:        time.Now().Format("2006-01-02 15:04:05"),
				Path:        c.Request.URL.Path,
				Method:      c.Request.Method,
				Host:        c.Request.Host,
				IP:          c.IP(),
				ContentType: c.GetHeader(HeaderContentType),
				Accept:      c.GetHeader(HeaderAccept),
				Traceid:     c.traceid,
				Error:       err.Error(),
				Sources:     stack(3),
			}

			if fn := c.engine.cfg.Recovery; fn != nil {
				fn(c, info.String(), info.JSON())
			} else {
				fmt.Print(info.String())
			}

			_ = c.Send(ErrInternalServerError())
		}
	}()

	return c.Next()
})

Recovery 是一个增强版的错误恢复中间件,它能打印出发生 panic 的具体源代码片段。

Functions

func APIHidden added in v1.0.0

func APIHidden(op *Operation)

APIHidden 将 Operation 标记为隐藏,使其不会出现在 OpenAPI 文档中。

func DefaultErrorHandler

func DefaultErrorHandler(c *Ctx, err error) error

DefaultErrorHandler 默认错误处理器

func DefaultSchemaNamer added in v1.0.0

func DefaultSchemaNamer(t reflect.Type, hint string) string

DefaultSchemaNamer 根据 “去域名 + 取最后两级” 策略生成名称

func SupportedLanguages added in v0.0.11

func SupportedLanguages() []language.Tag

SupportedLanguages 返回框架支持的所有语言标签

Types

type API added in v1.0.0

type API struct {
	*OpenAPI
}

API 持有 OpenAPI 生成过程中的所有可配置策略

func NewAPI added in v1.0.0

func NewAPI(f ...func(*API)) *API

func (*API) Field added in v1.0.0

func (a *API) Field(f reflect.StructField, hint string) (s *Schema)

func (*API) Register added in v1.0.0

func (a *API) Register(op *Operation, path, method string, arg *HandleArg)

Register 将处理器的元数据 (输入/输出类型) 注册到指定的 Operation 中

func (*API) Schema added in v1.0.0

func (a *API) Schema(t reflect.Type, hint ...string) *Schema

func (*API) Struct added in v1.0.0

func (a *API) Struct(t reflect.Type, hint ...string) *Schema

type AddOperation added in v1.0.0

type AddOperation func(*Operation)

type Claims added in v1.0.5

type Claims[T any] struct {
	Data T `json:"data"`
	jwt.RegisteredClaims
}

type Components added in v1.0.0

type Components struct {
	Schemas         *Registry                  `yaml:"schemas,omitempty"`
	SecuritySchemes map[string]*SecurityScheme `yaml:"securitySchemes,omitempty"`
}

type Config

type Config struct {
	Mode           string                      // gin.DebugMode | gin.ReleaseMode | gin.TestMode
	TrustedProxies []string                    // gin.SetTrustedProxies
	Recovery       func(c *Ctx, out, s string) // 回调 [带颜色的控制台输出] 和 [结构化 JSON 日志]
	ErrorHandler   func(c *Ctx, err error) error
	Logger         func(c *Ctx, out string, s string) // 回调 [带颜色的控制台输出] 和 [结构化 JSON 日志]
	Cors           func(*cors.Config)                 // 默认配置 cors.DefaultConfig()
	OpenAPI        *API
	Locales        []language.Tag // 绑定验证错误所使用的多语言支持
}

func DefaultConfig added in v1.0.4

func DefaultConfig(config ...Config) (cfg Config)

DefaultConfig 默认配置

type Ctx

type Ctx struct {
	Request *http.Request
	Writer  gin.ResponseWriter
	Uris    gin.Params
	Keys    map[string]any
	// contains filtered or unexported fields
}

func (*Ctx) AddURI added in v1.0.3

func (c *Ctx) AddURI(key, value string) *Ctx

AddURI 将指定的路径参数添加到上下文

func (*Ctx) Content added in v0.0.7

func (c *Ctx) Content(value string) *Ctx

func (*Ctx) Cookie

func (c *Ctx) Cookie(name string) (string, error)

func (*Ctx) Deadline added in v1.0.1

func (c *Ctx) Deadline() (time.Time, bool)

func (*Ctx) Done added in v1.0.1

func (c *Ctx) Done() <-chan struct{}

func (*Ctx) Err added in v1.0.1

func (c *Ctx) Err() error

func (*Ctx) Get added in v0.0.7

func (c *Ctx) Get(key string, value ...any) any

Get 获取或设置上下文值,不会发生 `panic`。 如果没有找到,还会尝试去获取 `Value(key)` 的值。

func (*Ctx) GetHeader added in v0.0.12

func (c *Ctx) GetHeader(key string, value ...string) string

GetHeader 获取 HTTP 请求头的值,如果不存在则返回可选的默认值。

func (*Ctx) Gin added in v0.0.7

func (c *Ctx) Gin() *gin.Context

Gin 返回底层的 *gin.Context

func (*Ctx) Header

func (c *Ctx) Header(key string, value string) *Ctx

func (*Ctx) IP

func (c *Ctx) IP() string

func (*Ctx) Method

func (c *Ctx) Method() string

func (*Ctx) Next

func (c *Ctx) Next() error

func (*Ctx) Param

func (c *Ctx) Param(key string, def ...any) string

Param 获取请求参数

func (*Ctx) ParamAny added in v1.0.1

func (c *Ctx) ParamAny(key string, def ...any) any

ParamAny 获取原始类型的参数值

func (*Ctx) ParamArray added in v1.0.1

func (c *Ctx) ParamArray(key string) []string

func (*Ctx) ParamBool added in v1.0.1

func (c *Ctx) ParamBool(key string, def ...any) bool

func (*Ctx) ParamDuration added in v1.0.1

func (c *Ctx) ParamDuration(key string, def ...any) time.Duration

func (*Ctx) ParamFile added in v1.0.1

func (c *Ctx) ParamFile(key string) (*multipart.FileHeader, error)

ParamFile 获取上传的文件

func (*Ctx) ParamFloat32 added in v1.0.1

func (c *Ctx) ParamFloat32(key string, def ...any) float32

func (*Ctx) ParamFloat64 added in v1.0.1

func (c *Ctx) ParamFloat64(key string, def ...any) float64

func (*Ctx) ParamInt added in v1.0.1

func (c *Ctx) ParamInt(key string, def ...any) int

func (*Ctx) ParamInt16 added in v1.0.1

func (c *Ctx) ParamInt16(key string, def ...any) int16

func (*Ctx) ParamInt32 added in v1.0.1

func (c *Ctx) ParamInt32(key string, def ...any) int32

func (*Ctx) ParamInt64 added in v1.0.1

func (c *Ctx) ParamInt64(key string, def ...any) int64

func (*Ctx) ParamInt8 added in v1.0.1

func (c *Ctx) ParamInt8(key string, def ...any) int8

func (*Ctx) ParamMap added in v1.0.1

func (c *Ctx) ParamMap(key string) map[string]string

func (*Ctx) ParamTime added in v1.0.1

func (c *Ctx) ParamTime(key string, def ...any) time.Time

func (*Ctx) ParamUint added in v1.0.1

func (c *Ctx) ParamUint(key string, def ...any) uint

func (*Ctx) ParamUint16 added in v1.0.1

func (c *Ctx) ParamUint16(key string, def ...any) uint16

func (*Ctx) ParamUint32 added in v1.0.1

func (c *Ctx) ParamUint32(key string, def ...any) uint32

func (*Ctx) ParamUint64 added in v1.0.1

func (c *Ctx) ParamUint64(key string, def ...any) uint64

func (*Ctx) ParamUint8 added in v1.0.1

func (c *Ctx) ParamUint8(key string, def ...any) uint8

func (*Ctx) Params

func (c *Ctx) Params() map[string]any

Params 获取所有 请求 (含 Body) 参数

func (*Ctx) Path

func (c *Ctx) Path(full ...bool) string

Path 返回请求路径 默认返回经过解码的具体请求路径,例如: "/users/123/profile" 传递 true 时返回路由定义字符串,例如: "/users/:id/profile"

func (*Ctx) RawBody

func (c *Ctx) RawBody() (body []byte)

func (*Ctx) RemoteIP added in v1.0.1

func (c *Ctx) RemoteIP() string

func (*Ctx) SaveFile

func (c *Ctx) SaveFile(file *multipart.FileHeader, dst string) error

func (*Ctx) Send

func (c *Ctx) Send(body any) error

func (*Ctx) SendBytes added in v1.0.2

func (c *Ctx) SendBytes(data []byte) error

func (*Ctx) SendFile added in v1.0.0

func (c *Ctx) SendFile(file string, name ...string) error

SendFile 发送文件,传递 name 为下载流。

func (*Ctx) SendHTML

func (c *Ctx) SendHTML(name string, data any) error

func (*Ctx) SendJSON added in v1.0.0

func (c *Ctx) SendJSON(data any) error

func (*Ctx) SendReader added in v1.0.1

func (c *Ctx) SendReader(reader io.Reader, size int64, extraHeaders ...map[string]string) error

SendReader 从 io.Reader 发送数据 size: 数据长度 (如果未知传 -1)

func (*Ctx) SendRedirect added in v1.0.2

func (c *Ctx) SendRedirect(loc string) error

SendRedirect 返回到特定位置的 HTTP 重定向

func (*Ctx) SendSSEvent added in v1.0.1

func (c *Ctx) SendSSEvent(name string, message any) error

SendSSEvent 将服务器发送事件写入正体流

func (*Ctx) SendStream added in v1.0.1

func (c *Ctx) SendStream(step func(w io.Writer) bool) bool

SendStream 发送流响应并返回布尔值,标识 “客户端是否在流中间断开连接”。

func (*Ctx) SendTOML added in v1.0.0

func (c *Ctx) SendTOML(data any) error

func (*Ctx) SendText added in v1.0.0

func (c *Ctx) SendText(data any) error

func (*Ctx) SendXML added in v1.0.0

func (c *Ctx) SendXML(data any) error

func (*Ctx) SendYAML added in v1.0.0

func (c *Ctx) SendYAML(data any) error

func (*Ctx) SetCookie

func (c *Ctx) SetCookie(name, value, path, domain string, maxAge int, secure, httpOnly bool, samesite ...http.SameSite) *Ctx

func (*Ctx) Status

func (c *Ctx) Status(code int) *Ctx

func (*Ctx) StatusCode

func (c *Ctx) StatusCode() int

func (*Ctx) TraceID added in v0.0.7

func (c *Ctx) TraceID() string

TraceID 获取请求的 [跟踪ID]

func (*Ctx) URI added in v1.0.3

func (c *Ctx) URI(key string) string

URI 返回与给定键匹配的路径参数 (如 /users/:id 中的 id 值)

func (*Ctx) Value added in v0.0.7

func (c *Ctx) Value(key any) any

type Engine

type Engine struct {
	Router
	// contains filtered or unexported fields
}

func New

func New(config ...Config) *Engine

func (*Engine) Gin added in v0.0.10

func (e *Engine) Gin() *gin.Engine

func (*Engine) Routes

func (e *Engine) Routes() gin.RoutesInfo

Routes 返回注册的路由信息切片

func (*Engine) Run

func (e *Engine) Run(addr string, certfile ...string) (err error)

Run 将路由器连接到 http.Server 并开始监听和提供 HTTP[S] 请求

提供 cert 和 key 文件路径作为 certfile 参数,可开启 HTTPS 服务。

func (*Engine) RunListener added in v0.0.7

func (e *Engine) RunListener(listener net.Listener) (err error)

RunListener 将路由器连接到 http.Server, 并开始通过指定的 listener 监听和提供 HTTP 请求。

type Error

type Error struct {
	Code    int
	Message string
}

Error 是 APIError 的默认实现

func ErrBadGateway

func ErrBadGateway(msg ...string) *Error

ErrBadGateway 502

func ErrBadRequest

func ErrBadRequest(msg ...string) *Error

ErrBadRequest 400

func ErrConflict

func ErrConflict(msg ...string) *Error

ErrConflict 409

func ErrEntityTooLarge added in v0.0.8

func ErrEntityTooLarge(msg ...string) *Error

ErrEntityTooLarge 413

func ErrExpectationFailed

func ErrExpectationFailed(msg ...string) *Error

ErrExpectationFailed 417

func ErrFailedDependency

func ErrFailedDependency(msg ...string) *Error

ErrFailedDependency 424

func ErrForbidden

func ErrForbidden(msg ...string) *Error

ErrForbidden 403

func ErrGatewayTimeout

func ErrGatewayTimeout(msg ...string) *Error

ErrGatewayTimeout 504

func ErrGone

func ErrGone(msg ...string) *Error

ErrGone 410

func ErrHTTPVersionNotSupported

func ErrHTTPVersionNotSupported(msg ...string) *Error

ErrHTTPVersionNotSupported 505

func ErrHeaderFieldsTooLarge added in v0.0.8

func ErrHeaderFieldsTooLarge(msg ...string) *Error

ErrHeaderFieldsTooLarge 431

func ErrInsufficientStorage

func ErrInsufficientStorage(msg ...string) *Error

ErrInsufficientStorage 507

func ErrInternalServerError

func ErrInternalServerError(msg ...string) *Error

ErrInternalServerError 500

func ErrLengthRequired

func ErrLengthRequired(msg ...string) *Error

ErrLengthRequired 411

func ErrLocked

func ErrLocked(msg ...string) *Error

ErrLocked 423

func ErrLoopDetected

func ErrLoopDetected(msg ...string) *Error

ErrLoopDetected 508

func ErrMethodNotAllowed

func ErrMethodNotAllowed(msg ...string) *Error

ErrMethodNotAllowed 405

func ErrMisdirectedRequest

func ErrMisdirectedRequest(msg ...string) *Error

ErrMisdirectedRequest 421

func ErrNetworkAuthenticationRequired

func ErrNetworkAuthenticationRequired(msg ...string) *Error

ErrNetworkAuthenticationRequired 511

func ErrNotAcceptable

func ErrNotAcceptable(msg ...string) *Error

ErrNotAcceptable 406

func ErrNotExtended

func ErrNotExtended(msg ...string) *Error

ErrNotExtended 510

func ErrNotFound

func ErrNotFound(msg ...string) *Error

ErrNotFound 404

func ErrNotImplemented

func ErrNotImplemented(msg ...string) *Error

ErrNotImplemented 501

func ErrPaymentRequired

func ErrPaymentRequired(msg ...string) *Error

ErrPaymentRequired 402

func ErrPreconditionFailed

func ErrPreconditionFailed(msg ...string) *Error

ErrPreconditionFailed 412

func ErrPreconditionRequired

func ErrPreconditionRequired(msg ...string) *Error

ErrPreconditionRequired 428

func ErrProxyAuthRequired

func ErrProxyAuthRequired(msg ...string) *Error

ErrProxyAuthRequired 407

func ErrRangeNotSatisfiable added in v0.0.8

func ErrRangeNotSatisfiable(msg ...string) *Error

ErrRangeNotSatisfiable 416

func ErrServiceUnavailable

func ErrServiceUnavailable(msg ...string) *Error

ErrServiceUnavailable 503

func ErrTeapot

func ErrTeapot(msg ...string) *Error

ErrTeapot 418

func ErrTimeout added in v0.0.8

func ErrTimeout(msg ...string) *Error

ErrTimeout 408

func ErrTooEarly

func ErrTooEarly(msg ...string) *Error

ErrTooEarly 425

func ErrTooManyRequests

func ErrTooManyRequests(msg ...string) *Error

ErrTooManyRequests 429

func ErrURITooLong added in v0.0.8

func ErrURITooLong(msg ...string) *Error

ErrURITooLong 414

func ErrUnauthorized

func ErrUnauthorized(msg ...string) *Error

ErrUnauthorized 401

func ErrUnavailableForLegalReasons

func ErrUnavailableForLegalReasons(msg ...string) *Error

ErrUnavailableForLegalReasons 451

func ErrUnprocessableEntity

func ErrUnprocessableEntity(msg ...string) *Error

ErrUnprocessableEntity 422

func ErrUnsupportedMediaType

func ErrUnsupportedMediaType(msg ...string) *Error

ErrUnsupportedMediaType 415

func ErrUpgradeRequired

func ErrUpgradeRequired(msg ...string) *Error

ErrUpgradeRequired 426

func ErrVariantAlsoNegotiates

func ErrVariantAlsoNegotiates(msg ...string) *Error

ErrVariantAlsoNegotiates 506

func NewError

func NewError(code int, msg ...string) *Error

NewError 创建一个新的 Error 如果没有提供消息,将使用 http.StatusText(code) 作为默认消息

func NotModified added in v0.0.8

func NotModified(msg ...string) *Error

NotModified 304

func (*Error) Error

func (e *Error) Error() string

type HandleArg added in v1.0.0

type HandleArg struct {
	In, Out reflect.Type
}

type HandleMeta added in v1.0.0

type HandleMeta struct {
	// contains filtered or unexported fields
}

func (*HandleMeta) Delete added in v1.0.0

func (m *HandleMeta) Delete(h Handler)

func (*HandleMeta) Get added in v1.0.0

func (m *HandleMeta) Get(h Handler) (*HandleArg, bool)

func (*HandleMeta) Pop added in v1.0.0

func (m *HandleMeta) Pop(h Handler) (a *HandleArg)

func (*HandleMeta) Set added in v1.0.0

func (m *HandleMeta) Set(h Handler, meta *HandleArg)

type Handler

type Handler = gin.HandlerFunc

func H added in v1.0.0

func H[I any, R any](f func(*Ctx, I) (R, error)) Handler

H 创建一个带有 [输入] 和 [输出] 的强类型处理器 (支持 OpenAPI)

func He added in v1.0.0

func He(f func(*Ctx) error) Handler

He 创建一个无输入且仅返回 error 的处理器方法

func Hn added in v1.0.0

func Hn(f func(*Ctx)) Handler

Hn 创建一个无输入输出的处理器方法

func Ho added in v1.0.0

func Ho[I any, R any](f func(*Ctx, I) R) Handler

Ho 创建一个仅有 [输出] 的强类型处理器 (支持 OpenAPI)

type Info added in v1.0.0

type Info struct {
	Title   string `yaml:"title"`
	Version string `yaml:"version"`
}

type JWT added in v1.0.5

type JWT[T any] struct {
	Key     string            // 上下文键名 (如 "user")
	Secret  []byte            // 签名密钥
	Timeout time.Duration     // 默认过期时间
	Method  jwt.SigningMethod // 签名算法
	Issuer  string            // 签发者
}

func NewJWT added in v1.0.5

func NewJWT[T any](key string, secret []byte, timeout time.Duration, opts ...func(*JWT[T])) *JWT[T]

func (*JWT[T]) Auth added in v1.0.5

func (j *JWT[T]) Auth(failure func(*Ctx, *jwt.Token, error) error, opts ...jwt.ParserOption) Handler

func (*JWT[T]) Issue added in v1.0.5

func (j *JWT[T]) Issue(data T) (string, error)

func (*JWT[T]) IssueWith added in v1.0.5

func (j *JWT[T]) IssueWith(data T, setup func(*Claims[T])) (string, error)

func (*JWT[T]) Parse added in v1.0.5

func (j *JWT[T]) Parse(signed string, opts ...jwt.ParserOption) (*Claims[T], *jwt.Token, error)

func (*JWT[T]) Token added in v1.0.5

func (j *JWT[T]) Token(gc *gin.Context) string

Token 从 Query 或 Header 中提取 Token

type MediaType added in v1.0.0

type MediaType struct {
	Schema *Schema `yaml:"schema,omitempty"`
}

type OpenAPI added in v1.0.0

type OpenAPI struct {
	OpenAPI    string               `yaml:"openapi"`
	Info       *Info                `yaml:"info"`
	Paths      map[string]*PathItem `yaml:"paths,omitempty"`
	Components *Components          `yaml:"components"`
	Security   []Requirement        `yaml:"security,omitempty"`
	Tags       []*Tag               `yaml:"tags,omitempty"`
	// contains filtered or unexported fields
}

func (*OpenAPI) YAML added in v1.0.0

func (a *OpenAPI) YAML() ([]byte, error)

YAML 返回 YAML 格式的 OpenAPI 规范

type Operation added in v1.0.0

type Operation struct {
	Summary     string                   `yaml:"summary,omitempty"`
	Description string                   `yaml:"description,omitempty"`
	Parameters  []*Param                 `yaml:"parameters,omitempty"`
	RequestBody *RequestBody             `yaml:"requestBody,omitempty"`
	Responses   map[string]*ResponseBody `yaml:"responses,omitempty"`
	Security    []Requirement            `yaml:"security,omitempty"`
	Tags        []string                 `yaml:"tags,omitempty"`

	Hidden bool `yaml:"-"`
}

func (*Operation) Clone added in v1.0.0

func (o *Operation) Clone() *Operation

Clone 返回一份深度的 Operation 副本

type Param added in v1.0.0

type Param struct {
	Ref         string  `yaml:"$ref,omitempty"`
	Name        string  `yaml:"name,omitempty"`
	In          string  `yaml:"in,omitempty"` // "query", "header", "path", "cookie"
	Required    bool    `yaml:"required,omitempty"`
	Description string  `yaml:"description,omitempty"`
	Schema      *Schema `yaml:"schema,omitempty"`
}

type PathItem added in v1.0.0

type PathItem struct {
	Ref         string `yaml:"$ref,omitempty"`
	Summary     string `yaml:"summary,omitempty"`
	Description string `yaml:"description,omitempty"`

	Get        *Operation `yaml:"get,omitempty"`
	Put        *Operation `yaml:"put,omitempty"`
	Post       *Operation `yaml:"post,omitempty"`
	Delete     *Operation `yaml:"delete,omitempty"`
	Options    *Operation `yaml:"options,omitempty"`
	Head       *Operation `yaml:"head,omitempty"`
	Patch      *Operation `yaml:"patch,omitempty"`
	Trace      *Operation `yaml:"trace,omitempty"`
	Parameters []*Param   `yaml:"parameters,omitempty"`
}

type RecoverInfo added in v0.0.9

type RecoverInfo struct {
	Time        string   `json:"time"`
	Path        string   `json:"path"`
	Method      string   `json:"method"`
	Host        string   `json:"host"`
	IP          string   `json:"ip"`
	ContentType string   `json:"content"`
	Accept      string   `json:"accept"`
	Traceid     string   `json:"traceid"`
	Error       string   `json:"error"`
	Sources     []*Stack `json:"stack"`
}

func (*RecoverInfo) JSON added in v0.0.9

func (r *RecoverInfo) JSON() string

func (*RecoverInfo) String added in v0.0.9

func (r *RecoverInfo) String() string

type Registry added in v1.0.0

type Registry struct {
	Namer  func(reflect.Type, string) string `yaml:"-"`
	Prefix string
	// contains filtered or unexported fields
}

func NewRegistry added in v1.0.0

func NewRegistry(prefix string, namer func(reflect.Type, string) string) *Registry

func (*Registry) DecodeJSON added in v1.0.0

func (r *Registry) DecodeJSON(value, field string, s *Schema) any

DecodeJSON 根据字段的 Schema 类型,将从 tag 读取的字符串值解析为正确的 Go 类型。

func (*Registry) Field added in v1.0.0

func (r *Registry) Field(f reflect.StructField, hint string) (s *Schema)

func (*Registry) MarshalYAML added in v1.0.0

func (r *Registry) MarshalYAML() (any, error)

func (*Registry) Ref added in v1.0.0

func (r *Registry) Ref(ref string) *Schema

func (*Registry) Schema added in v1.0.0

func (r *Registry) Schema(t reflect.Type, hint ...string) *Schema

func (*Registry) Struct added in v1.0.0

func (r *Registry) Struct(t reflect.Type, hint ...string) *Schema

type RequestBody added in v1.0.0

type RequestBody struct {
	Ref         string                `yaml:"$ref,omitempty"`
	Description string                `yaml:"description,omitempty"`
	Content     map[string]*MediaType `yaml:"content"`
	Required    bool                  `yaml:"required,omitempty"`
}

type Requirement added in v1.0.0

type Requirement map[string][]string

type ResponseBody added in v1.0.0

type ResponseBody struct {
	Ref         string                `yaml:"$ref,omitempty"`
	Description string                `yaml:"description,omitempty"`
	Headers     map[string]*Param     `yaml:"headers,omitempty"`
	Content     map[string]*MediaType `yaml:"content,omitempty"`
}

type Result added in v1.0.0

type Result struct {
	Event  string `json:"event"`  // 事件标识
	Status int    `json:"status"` // 自定义状态码,经常用于定义请求成功或失败等错误状态 (非 HTTP 状态码)
	Code   int    `json:"code"`   // 自定义代码,经常与 Status 关联。例如: Status=0 时,Code=N。
	Count  int    `json:"count"`  // 如果 Data 返回列表,可以在这里设置列表长度。
	Msg    string `json:"msg"`    // 结果消息
	Data   any    `json:"data"`   // 结果数据
}

func (*Result) Failed added in v1.0.0

func (r *Result) Failed(data ...any) (res *Result)

Failed 设置失败 (status=0) 数据

func (*Result) NewFailed added in v1.0.0

func (r *Result) NewFailed(data ...any) *Result

func (*Result) OK added in v1.0.0

func (r *Result) OK(data ...any) (res *Result)

OK 设置成功 (status=1) 数据

func (*Result) SetCode added in v1.0.0

func (r *Result) SetCode(code any) *Result

SetCode 设置 code

func (*Result) SetEvent added in v1.0.0

func (r *Result) SetEvent(e string) *Result

SetEvent 设置事件

func (*Result) SetMsg added in v1.0.0

func (r *Result) SetMsg(format any, a ...any) *Result

SetMsg 设置消息

func (*Result) SetStatus added in v1.0.0

func (r *Result) SetStatus(status any, code ...any) (res *Result)

SetStatus 设置 status, code

type Router

type Router struct {
	// contains filtered or unexported fields
}

func (*Router) Any added in v1.0.0

func (r *Router) Any(path string, h Handler, ops ...AddOperation) IRouter

func (*Router) DELETE added in v0.0.6

func (r *Router) DELETE(path string, h Handler, ops ...AddOperation) IRouter

func (*Router) GET

func (r *Router) GET(path string, h Handler, ops ...AddOperation) IRouter

func (*Router) Group

func (r *Router) Group(path string, ops ...AddOperation) IRouter

func (*Router) HEAD added in v1.0.0

func (r *Router) HEAD(path string, h Handler, ops ...AddOperation) IRouter

func (*Router) Handle

func (r *Router) Handle(method, path string, h Handler, ops ...AddOperation) IRouter

func (*Router) Match added in v1.0.0

func (r *Router) Match(methods []string, path string, h Handler, ops ...AddOperation) IRouter

func (*Router) OPTIONS added in v1.0.0

func (r *Router) OPTIONS(path string, h Handler, ops ...AddOperation) IRouter

func (*Router) PATCH added in v1.0.0

func (r *Router) PATCH(path string, h Handler, ops ...AddOperation) IRouter

func (*Router) POST

func (r *Router) POST(path string, h Handler, ops ...AddOperation) IRouter

func (*Router) PUT added in v0.0.6

func (r *Router) PUT(path string, h Handler, ops ...AddOperation) IRouter

func (*Router) Static

func (r *Router) Static(path, root string) IRouter

func (*Router) StaticFS added in v1.0.0

func (r *Router) StaticFS(name string, root http.FileSystem) IRouter

func (*Router) StaticFile added in v1.0.0

func (r *Router) StaticFile(name, root string) IRouter

func (*Router) StaticFileFS added in v1.0.0

func (r *Router) StaticFileFS(name, root string, fs http.FileSystem) IRouter

func (*Router) Use

func (r *Router) Use(handlers ...Handler) IRouter

type Schema added in v1.0.0

type Schema struct {
	Type                 any                `yaml:"type,omitempty"`
	Nullable             bool               `yaml:"-"`
	Title                string             `yaml:"title,omitempty"`
	Description          string             `yaml:"description,omitempty"`
	Ref                  string             `yaml:"$ref,omitempty"`
	Format               string             `yaml:"format,omitempty"`
	ContentEncoding      string             `yaml:"contentEncoding,omitempty"`
	Default              any                `yaml:"default,omitempty"`
	Items                *Schema            `yaml:"items,omitempty"`                // For arrays
	AdditionalProperties any                `yaml:"additionalProperties,omitempty"` // Schema or bool
	Properties           map[string]*Schema `yaml:"properties,omitempty"`
	Enum                 []any              `yaml:"enum,omitempty"`
	Required             []string           `yaml:"required,omitempty"`
}

func (*Schema) MarshalYAML added in v1.0.0

func (s *Schema) MarshalYAML() (any, error)

type SecurityScheme added in v1.0.0

type SecurityScheme struct {
	Type         string `yaml:"type"` // "http", "apiKey", "oauth2"
	Description  string `yaml:"description,omitempty"`
	Name         string `yaml:"name,omitempty"`         // Header name for apiKey
	In           string `yaml:"in,omitempty"`           // "header" for apiKey
	Scheme       string `yaml:"scheme,omitempty"`       // "bearer" (for HTTP)
	BearerFormat string `yaml:"bearerFormat,omitempty"` // "JWT" (for bearer)
}

type Stack added in v0.0.9

type Stack struct {
	File   string `json:"file"`
	Line   int    `json:"line"`
	Func   string `json:"func"`
	Source string `json:"source"`
	// contains filtered or unexported fields
}

Stack 存储堆栈的关键信息

type Tag added in v1.0.0

type Tag struct {
	Name        string `yaml:"name"`
	Description string `yaml:"description,omitempty"`
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL