Skip to content

分组#

操作可以按公共路由前缀分组,并共享中间件、操作修饰器函数和响应转换器。这可以通过在 huma.API 实例周围使用 huma.Group 包装器来实现,然后将该包装器传递给 huma.Register 及其便利包装器,如 huma.Gethuma.Post 等。

grp := huma.NewGroup(api, "/v1")
grp.UseMiddleware(authMiddleware)

huma.Get(grp, "/users", func(ctx context.Context, input *struct{}) (*UsersResponse, error) {
	// ...
})

上述示例将注册一个 GET /v1/users 操作,并在操作处理程序之前运行 authMiddleware

分组与文档

分组假设使用 huma.Register 或其便利包装器来注册操作。如果不是这样,则可能需要调用 group.DocumentOperation(*huma.Operation) 来确保操作正确记录。

分组功能#

分组支持以下功能:

  • 组内所有操作的一个或多个路径前缀。
  • 在组内每个操作之前运行的中间件。
  • 在操作注册时运行的操作修饰器。
  • 在组内每个操作之后运行的响应转换器。

前缀#

分组可以有一个或多个路径前缀,这些前缀会被添加到组内所有操作的前面。这对于将相关操作分组到公共前缀下很有用,通常使用单个前缀。

grp := huma.NewGroup(api, "/prefix1", "/prefix2", "...")

这只是以下等效代码的便利形式:

grp := huma.NewGroup(api)
grp.UseModifier(huma.PrefixModifier("/prefix1", "/prefix2", "..."))

内置的 huma.PrefixModifier 在使用多个前缀时会调整操作的 ID 和标签。如果希望自定义此行为,可以编写自己的操作修饰器。

中间件#

中间件函数在组内每个操作处理程序之前运行。它们可用于常见任务,如认证、日志记录和错误处理。使用组上的 UseMiddleware 方法注册中间件函数。

grp.UseMiddleware(func(ctx huma.Context, next func(huma.Context)) {
	// 在操作运行之前执行某些操作
	next(ctx)
})

操作修饰器#

操作修饰器是函数,在操作注册时运行。它们可用于在注册操作之前修改操作。使用组上的 UseModifier 方法注册操作修饰器。

grp.UseModifier(func(op *huma.Operation, next func(*huma.Operation)) {
	op.Summary = "A summary for all operations in this group"
	op.Tags = []string{"my-tag"}
    next(op)
})

还有一种简化的形式可以使用:

grp.UseSimpleModifier(func(op *huma.Operation) {
	op.Summary = "A summary for all operations in this group"
	op.Tags = []string{"my-tag"}
})

响应转换器#

响应转换器是函数,在组内每个操作处理程序之后运行。它们可用于在返回给客户端之前修改响应。使用组上的 UseResponseTransformer 方法注册响应转换器。

grp.UseTransformer(func(ctx huma.Context, status string, v any) (any, error) {
	// 对输出执行某些操作
	return output, nil
})

自定义文档#

分组实现了 huma.OperationDocumenter,它绕过了正常的文档生成流程,而是调用一个函数。这允许您自定义组内所有操作的文档。如果需要,可以重写 DocumentOperation 方法来自定义文档:

type MyGroup huma.Group

func (g *MyGroup) DocumentOperation(op *huma.Operation) {
	g.ModifyOperation(op, func(op *huma.Operation) {
		if documenter, ok := g.API.(huma.OperationDocumenter); ok {
			// 支持嵌套操作文档器(即分组中的分组)。
			documenter.DocumentOperation(op)
		} else {
			// 默认行为是添加操作。
			if op.Hidden {
				return
			}
			g.OpenAPI().AddOperation(op)
		}
	})
}

深入了解#