Skip to content

状态处理器

介绍

状态处理器 是类似于控制器的 组件,实现了一个常规处理器,如果 响应体为空 但已设置状态码,则在请求生命周期的 最终化 步骤中执行。状态处理器主要用于为用户或服务器错误实现自定义行为(分别对应 400500 状态码)。简而言之,状态处理器是一种集中处理一个或多个响应状态码的方式。

Goyave 自带三个内置状态处理器,默认定义如下:

  • goyave.PanicStatusHandler:用于错误和 panic(500
  • goyave.ErrorStatusHandler:用于非成功码(400 码、501+ 码)
  • goyave.ValidationStatusHandler:用于 422 Unprocessable Entity(验证错误)

panic 和错误处理器返回对应状态码的简单错误消息。

json
{
	"error": "Not Found"
}

INFO

500 状态处理器是一个例外:即使在写入后发生错误或 panic,它仍将被执行。

实现状态处理器

状态处理器实现在 http/controller/status 包中。如果您的状态处理器相当大,可以将它们拆分成多个文件,否则您可以将它们全部实现在一个 status.go 文件中。

状态处理器是必须实现 goyave.StatusHandler 接口的结构体。该接口要求您的结构体是一个 goyave.Component,并实现一个 Handle(*Response, *Request) 方法。

示例:

go
package status

import (
	"goyave.dev/goyave/v5"
)

type CustomHandler struct {
	goyave.Component
}

func (*CustomHandler) Handle(response *goyave.Response, request *goyave.Request) {
	message := map[string]string{
		"message": request.Lang.Get("customStatusHandlerResponse"),
	}
	response.JSON(response.GetStatus(), message)
}

WARNING

状态处理器在处理程序栈 外部 执行,因为它们是 最终化 步骤的一部分。因此,它们 不受 恢复中间件保护。请特别注意构建您的状态处理器,以确保它们绝不会 panic

注意

如果您的状态处理器未向响应体写入任何内容,状态码 不会 更改为 204 No Content

扩展默认状态处理器

您可以通过 组合 默认状态处理器来扩展它们。这在您希望保留默认行为并仅添加一些自定义操作时非常有用。例如,如果您想使用错误跟踪服务:

go
type ErrorHandler struct {
	goyave.PanicStatusHandler
}

func (h *ErrorHandler) Handle(response *goyave.Response, request *goyave.Request) {
	errortracker.Notify(response.GetError())

	h.PanicStatusHandler.Handle(response, request)
}

注册状态处理器

状态处理器在 路由器 中注册。

go
func Register(_ *goyave.Server, router *goyave.Router) {
	router.StatusHandler(&status.ErrorHandler{}, http.StatusInternalServerError)
	router.StatusHandler(&status.CustomHandler{}, 401, 402, 403)
	//...
}

TIP

状态处理器在子路由器中作为克隆继承。修改子路由器的状态处理器不会修改其父级。这意味着您可以为某些路由组定义不同的状态处理器,并且您应该在子路由器之前注册您的状态处理器。