操作#
操作#
操作是 Huma 的核心。它们将 HTTP 方法动词和资源路径映射到具有明确定义的输入和输出的处理函数。在查看由资源组成的 API 时,操作对应于这些资源上的 GET、POST、PUT 等方法,如以下示例所示:
graph TD
subgraph Operations
GET
GET2[GET]
POST
PUT
DELETE
end
API --> Resource1[Resource /items]
API --> Resource2["Resource /users/{user-id}"]
Resource1 --> POST
Resource1 --> GET
Resource1 --> DELETE
Resource2 --> GET2
Resource2 --> PUT
操作使用 huma.Register 函数创建:
huma.Register(api, huma.Operation{
OperationID: "your-operation-name",
Method: http.MethodGet,
Path: "/path/to/resource/{id}",
Summary: "操作的简短描述",
}, func(ctx context.Context, input *YourInput) (*YourOutput, error) {
// ... Implementation goes here ...
})
REST
如果遵循 REST-ish 约定,操作路径应为名词,如果返回多个项目则使用复数形式。好的示例:/notes、/likes、/users/{user-id}、/videos/{video-id}/stats 等。Huma 不强制执行此约定,也不关心,因此也可以使用 RPC 风格的路径。使用最适合您和您的团队的方式。
OperationID
您知道吗?OperationID 用于在 Restish 中生成友好的 CLI 命令,并在生成 SDK 时使用!它应唯一、描述性强且易于输入。
便捷方法#
如果您不想直接使用 huma.Operation 结构体,则提供了一系列便捷方法。以下是可用的方法:
huma.Gethuma.Posthuma.Puthuma.Patchhuma.Delete
这些方法等同于使用 huma.Register 并将 Method 字段设置为相应的 HTTP 方法,并且它们会根据路径为您生成操作 ID。例如:
huma.Get(api, "/things/{thing-id}", func(ctx context.Context, input *YourInput) (*YourOutput, error) {
// ... Implementation goes here ...
})
在上面的示例中,生成的操作 ID 是 get-things-by-thing-id,摘要是 Get things by id。要自定义这些,请覆盖 huma.GenerateOperationID(method, path string, response any) 用于操作 ID,以及 huma.GenerateSummary(method, path string, response any) 用于摘要。
这使得入门变得容易,特别是如果您来自其他框架,并且当您需要设置操作的其他字段时,只需切换到使用 huma.Register。
处理函数#
操作处理函数 始终 具有以下通用格式,其中 Input 和 Output 是开发者定义的自定义结构体,分别表示请求的全部内容(路径/查询/标头/ Cookie 参数和主体)和响应(标头和主体):
操作有许多选项可用于配置 OpenAPI 设置,并且支持自定义扩展。有关更多详细信息,请参阅 huma.Operation 结构体。
输入和输出模型#
输入和输出 始终 是表示传入请求或传出响应的全部内容的结构体。这是为了使您的应用程序中的数据流更容易推理的 deliberate 设计决策。这也使共享代码以及生成文档和 SDK 变得更容易。
如果您的操作没有输入或输出,可以在注册时使用指向空结构体的指针 *struct{}。
func(ctx context.Context, input *struct{}) (*struct{}, error) {
// Successful response example, defaults to HTTP 204 No Content
return nil, nil
}
请求流程#
传入 API 的请求在到达您的操作处理函数之前会经过多个步骤。以下图示显示了请求通过系统的流程,从请求输入(如路径/查询/标头参数和请求主体)开始,经过验证、操作处理函数,以及输出如何在响应中发送。
graph LR
subgraph Inputs
Path
Query
Header
Body
RawBody
end
subgraph Outputs
Status
Headers
OutBody[Body]
end
Path --> Validate
Query --> Validate
Header --> Validate
Body --> Unmarshal --> Validate
Validate --> Resolve --> Operation
RawBody -->|raw body input| Operation
Operation --> Transform
Transform --> Status
Transform --> Headers
Transform --> Marshal --> OutBody
Operation -->|raw body output| OutBody
style Operation stroke:#f9f,stroke-width:2px,stroke-dasharray: 5 5
Unmarshal-
将请求主体的原始字节(例如 JSON)读取到 Go 结构中。
Validate-
检查输入上的约束(例如
minimum、maxLength等)并报告失败。 Resolve-
运行自定义验证代码并报告失败。
Operation-
您操作的处理函数。业务逻辑在此处实现。它返回您的响应结构或错误。
Transform-
在将结构化响应数据序列化为字节之前即时修改它。
Marshal-
将结构化响应数据转换为字节(例如 JSON)。
继续阅读以了解每个步骤的工作原理。
深入探索#
- 教程
- 您的第一个 API 包括注册操作
- 参考
huma.Register注册新操作huma.Operation操作
- 外部链接