touka/midware_x.go
2025-06-17 14:41:39 +08:00

89 lines
3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package touka
// UseChainIf 是一个条件中间件包装器。
// 如果 `condition` 为 true它将执行提供的 `middlewares` 链。
// 如果 `condition` 为 false它会直接跳过这些中间件调用下一个处理器。
func (engine *Engine) UseChainIf(condition bool, middlewares ...HandlerFunc) HandlerFunc {
if !condition {
return func(c *Context) {
c.Next()
}
}
// 如果条件为真,返回一个处理器,该处理器负责执行子链。
// 我们通过修改 Context 的状态来做到这一点。
// 这比递归闭包或替换 c.Next 要清晰。
return func(c *Context) {
// 1. 将当前的处理链和索引位置保存下来。
originalHandlers := c.handlers
originalIndex := c.index
// 2. 创建一个新的处理链,它由传入的中间件和最后的 "恢复并继续" 处理器组成。
subChain := make(HandlersChain, len(middlewares)+1)
copy(subChain, middlewares)
// 3. 在子链的末尾添加一个特殊的 handler。
// 它的作用是恢复原始的处理链状态,并继续执行原始链中 `If` 之后的处理器。
subChain[len(middlewares)] = func(ctx *Context) {
ctx.handlers = originalHandlers
ctx.index = originalIndex
ctx.Next()
}
// 4. 将 Context 的处理器链临时替换为我们的子链,并重置索引。
c.handlers = subChain
c.index = -1
// 5. 调用 c.Next() 来启动子链的执行。
c.Next()
}
}
// UseIf 是一个条件中间件包装器
func (engine *Engine) UseIf(condition bool, middlewares HandlerFunc) HandlerFunc {
if !condition {
return func(c *Context) {
c.Next()
}
}
return middlewares
}
func (engine *Engine) UseNewChainIf(condition bool, middlewares ...HandlerFunc) HandlerFunc {
// 如果条件不满足或没有提供中间件,返回一个“穿透”中间件。
if !condition || len(middlewares) == 0 {
return func(c *Context) {
c.Next()
}
}
// 如果条件满足,返回一个处理器,该处理器负责按顺序执行这个子链。
return func(c *Context) {
// 保存原始的处理链和当前执行索引,以便在子链结束后恢复。
originalHandlers := c.handlers
originalIndex := c.index
// 创建一个新的临时处理链。
// 这个链由传入的 `middlewares` 和一个特殊的“恢复”处理器组成。
subChain := make(HandlersChain, len(middlewares)+1)
copy(subChain, middlewares)
// 在子链的末尾添加“恢复”处理器。
// 当所有 `middlewares` 都执行完毕并调用了 Next() 后,这个函数会被执行。
subChain[len(middlewares)] = func(ctx *Context) {
// 恢复原始的处理链状态。
ctx.handlers = originalHandlers
ctx.index = originalIndex
// 继续执行原始处理链中 `ChainIf` 之后的下一个处理器。
ctx.Next()
}
// 将 Context 的处理器链临时替换为我们的子链,并重置索引以从头开始。
c.handlers = subChain
c.index = -1
// 调用 c.Next() 来启动这个子链的执行。
c.Next()
}
}