You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置Gorilla Mux的r.Use实现中间件链错误向下传递?

解决gorilla/mux中MiddlewareFunc类型不匹配的问题

问题根源

你遇到的错误是因为gorilla/mux的Router.Use()方法要求传入的中间件必须是mux.MiddlewareFunc类型,也就是**func(http.Handler) http.Handler**,但你的AuthFunc和LoggingFunc的签名和这个不兼容:

  • LoggingFunc接收的是自定义的HandlerFunc(带error返回)而非标准的http.Handler
  • AuthFunc返回的是自定义HandlerFunc,也不符合mux中间件的返回要求

解决方案1:调整中间件为mux兼容的标准类型

如果不需要保留带error返回的自定义Handler,直接把中间件改成符合mux要求的签名即可:

1. 修正日志中间件

import "time"

func LoggingFunc(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // 记录请求开始信息
        start := time.Now()
        log.Printf("Received request: %s %s", r.Method, r.URL.Path)

        defer func() {
            // 捕获panic并处理
            if err, ok := recover().(error); ok {
                w.WriteHeader(http.StatusInternalServerError)
                log.Printf("Panic occurred: %v", err)
            }
            // 记录请求结束耗时
            log.Printf("Request completed in %v", time.Since(start))
        }()

        // 调用下一个中间件/Handler
        next.ServeHTTP(w, r)
    })
}

2. 修正认证中间件

注意:原代码中r.GET("JWT")是错误写法,标准*http.Request没有这个方法,这里改成从Header获取JWT:

import "strings"

func AuthFunc(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        jwtToken := r.Header.Get("Authorization")
        // 简单校验:假设JWT在Authorization头中,格式为Bearer <token>
        if jwtToken == "" || !strings.HasPrefix(jwtToken, "Bearer ") {
            w.WriteHeader(http.StatusUnauthorized)
            fmt.Fprintf(w, "No valid JWT provided")
            return
        }

        // 认证通过,继续执行下一个中间件/Handler
        next.ServeHTTP(w, r)
    })
}

3. 正常使用中间件

现在两个中间件都符合mux.MiddlewareFunc类型,直接传给r.Use()即可:

r := mux.NewRouter()
r.Use(LoggingFunc)
r.Use(AuthFunc)

// 注册你的标准Handler
r.HandleFunc("/api/resource", func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Authenticated access granted")
})

解决方案2:保留自定义带error的Handler,用适配器整合

如果想保留自定义HandlerFunc func(w http.ResponseWriter, r *http.Request) error的设计(统一处理错误),可以写一个适配器将自定义Handler转为标准http.Handler,再整合到mux的中间件链中:

1. 定义适配器函数

这个适配器负责处理自定义Handler返回的错误和panic:

// adaptErrorHandler 将带error返回的自定义Handler转为标准http.Handler
func adaptErrorHandler(h HandlerFunc) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        defer func() {
            if err, ok := recover().(error); ok {
                w.WriteHeader(http.StatusInternalServerError)
                log.Printf("Panic in handler: %v", err)
            }
        }()

        if err := h(w, r); err != nil {
            // 根据错误类型返回对应状态码,这里简单处理为401
            w.WriteHeader(http.StatusUnauthorized)
            fmt.Fprintf(w, "Error: %v", err)
            log.Printf("Handler error: %v", err)
        }
    })
}

2. 调整自定义中间件链

让认证中间件包裹你的业务Handler:

// 自定义业务Handler
func MyAPIHandler(w http.ResponseWriter, r *http.Request) error {
    fmt.Fprintf(w, "Successfully accessed protected resource")
    return nil
}

// 用AuthFunc包裹业务Handler
authProtectedHandler := AuthFunc(MyAPIHandler)

3. 注册适配后的Handler并应用mux中间件

r := mux.NewRouter()
// 应用日志中间件(已改为标准mux兼容类型)
r.Use(LoggingFunc)

// 将适配后的自定义Handler注册到路由
r.Handle("/api/resource", adaptErrorHandler(authProtectedHandler))

这样既保留了自定义Handler的错误返回设计,又能和mux的中间件体系兼容,不会再出现类型不匹配的错误。

内容的提问来源于stack exchange,提问作者mbudge

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:18:20