showliuzp 2025-11-14 11:00 采纳率: 84.3%
浏览 5
已结题

golang发起302重定向


import (
    "net/http"
    "github.com/zeromicro/go-zero/rest"
)

func add_router(method_type string, path string, handler http.HandlerFunc) rest.Route {
    return rest.Route{
        Method:  method_type,
        Path:    "api/admin/" + path,
        Handler: handler,
    }
}

//路由定义
r = []rest.Route{

        /*++++++++++++++++++++++++++++++会员部分++++++++++++++++++++++++*/
        add_router(types.POST, "/members/list", response.WrapResponse(MembersList,login_chk.RouterCheckToken)), 
  }
return r
}

//response.WrapResponse定义
func WrapResponse(fn func(r *http.Request) (interface{}, error),checkTokenFunc func(r *http.Request) error) http.HandlerFunc {
        return func(w http.ResponseWriter, r *http.Request) {
                resp, err := fn(r)

        if r.URL.Path != "/check/login" {
            if checkTokenFunc != nil{
                err := checkTokenFunc(r)
                if err != nil {
                    handleErrorResponse(w,err)
                    return
                }
            }
                }

                if err == nil {
                        r := &Response{
                                Code:    0,
                                Msg:    "success",
                                Data:    resp,
                        }

                        httpx.WriteJson(w, http.StatusOK, r)
                } else {
            handleErrorResponse(w,err)
                }
        }
}

RouterCheckToken函数定义:
func (l *Login) RouterCheckToken(r *http.Request)(err error){
    authorization := (*r).Header.Get(types.HEADER_AUTH)
    exists,err := l.CheckToken(&authorization);
    if err != nil{
        return
    }

    if !exists{
                //302跳转
                return response.NewErrCodeMsg(200, "已过期,请通过refresh_token获取token或重新登录")
    }

    return

}

RouterCheckToken是校验是否登录的函数,如果过期返回错误消息,我想把他改造成过期了302跳转到登录页,应该怎么做
  • 写回答

3条回答 默认 最新

  • 宝码香车 优质创作者: JavaScript技术领域 2025-11-14 11:17
    关注

    让【宝码香车】来帮您解答,本回答参考DeepSeek编写,并整理提供。

    如果答案能帮助您,请采纳,非常感谢!
    .
    每日一句正能量,让它带给您好心情:把日子过得有滋有味,就是对生活最好的回馈。
    .

    在 Go 语言中实现 302 重定向,你需要在 RouterCheckToken 函数中直接操作 HTTP 响应,而不是返回错误。以下是修改方案:

    方案一:修改 RouterCheckToken 函数

    func (l *Login) RouterCheckToken(w http.ResponseWriter, r *http.Request) error {
        authorization := r.Header.Get(types.HEADER_AUTH)
        exists, err := l.CheckToken(&authorization)
        if err != nil {
            return err
        }
    
    
        if !exists {
            // 302 重定向到登录页
            http.Redirect(w, r, "/login", http.StatusFound)
            return nil // 这里返回 nil 表示已经处理了响应
        }
    
    
        return nil
    }
    

    方案二:修改 WrapResponse 函数签名和调用

    由于 RouterCheckToken 现在需要 http.ResponseWriter 参数,你需要修改 WrapResponse 函数:

    func WrapResponse(fn func(r *http.Request) (interface{}, error), checkTokenFunc func(w http.ResponseWriter, r *http.Request) error) http.HandlerFunc {
        return func(w http.ResponseWriter, r *http.Request) {
            // 先执行 token 检查
            if r.URL.Path != "/check/login" {
                if checkTokenFunc != nil {
                    err := checkTokenFunc(w, r)
                    if err != nil {
                        handleErrorResponse(w, err)
                        return
                    }
                    // 如果 checkTokenFunc 执行了重定向,直接返回
                    if w.(interface{ Written() bool }).Written() {
                        return
                    }
                }
            }
    
    
            resp, err := fn(r)
            if err != nil {
                handleErrorResponse(w, err)
                return
            }
    
    
            r := &Response{
                Code: 0,
                Msg:  "success",
                Data: resp,
            }
            httpx.WriteJson(w, http.StatusOK, r)
        }
    }
    

    方案三:使用中间件模式(推荐)

    更优雅的方式是使用中间件模式:

    // 创建认证中间件
    func AuthMiddleware(l *Login) func(http.Handler) http.Handler {
        return func(next http.Handler) http.Handler {
            return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
                authorization := r.Header.Get(types.HEADER_AUTH)
                exists, err := l.CheckToken(&authorization)
                if err != nil {
                    handleErrorResponse(w, err)
                    return
                }
    
    
                if !exists {
                    // 302 重定向到登录页
                    http.Redirect(w, r, "/login", http.StatusFound)
                    return
                }
    
    
                next.ServeHTTP(w, r)
            })
        }
    }
    
    
    // 修改路由定义,使用中间件
    func add_router(method_type string, path string, handler http.HandlerFunc, authRequired bool) rest.Route {
        var finalHandler http.HandlerFunc = handler
        
        if authRequired {
            finalHandler = func(w http.ResponseWriter, r *http.Request) {
                // 这里可以添加认证中间件
                handler(w, r)
            }
        }
        
        return rest.Route{
            Method:  method_type,
            Path:    "api/admin/" + path,
            Handler: finalHandler,
        }
    }
    

    方案四:修改现有代码的最简方式

    如果你希望最小化修改现有代码,可以这样调整:

    func (l *Login) RouterCheckToken(r *http.Request) error {
        authorization := r.Header.Get(types.HEADER_AUTH)
        exists, err := l.CheckToken(&authorization)
        if err != nil {
            return err
        }
    
    
        if !exists {
            // 返回特殊错误类型,在 WrapResponse 中处理重定向
            return &RedirectError{URL: "/login"}
        }
    
    
        return nil
    }
    
    
    // 自定义重定向错误类型
    type RedirectError struct {
        URL string
    }
    
    
    func (e *RedirectError) Error() string {
        return "need redirect to: " + e.URL
    }
    
    
    // 修改 WrapResponse 中的错误处理
    func WrapResponse(fn func(r *http.Request) (interface{}, error), checkTokenFunc func(r *http.Request) error) http.HandlerFunc {
        return func(w http.ResponseWriter, r *http.Request) {
            if r.URL.Path != "/check/login" {
                if checkTokenFunc != nil {
                    err := checkTokenFunc(r)
                    if err != nil {
                        // 检查是否是重定向错误
                        if redirectErr, ok := err.(*RedirectError); ok {
                            http.Redirect(w, r, redirectErr.URL, http.StatusFound)
                            return
                        }
                        handleErrorResponse(w, err)
                        return
                    }
                }
            }
    
    
            resp, err := fn(r)
            if err != nil {
                handleErrorResponse(w, err)
                return
            }
    
    
            r := &Response{
                Code: 0,
                Msg:  "success",
                Data: resp,
            }
            httpx.WriteJson(w, http.StatusOK, r)
        }
    }
    

    推荐使用方案三的中间件模式,因为它更符合 Go 语言的惯用法,代码结构更清晰,也更容易维护和测试。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 11月22日
  • 已采纳回答 11月14日
  • 创建了问题 11月14日