gqlgen 从解析器设置 cookie

问题描述

我正在使用杜松子酒和 gqlgen。 我需要从解析器设置 cookie,但我在解析器中拥有的只是来自 graphQL 的上下文和输入。 此问题已在 github 中得到解答。 但是这个不同,因为当您尝试传入 ctx.Writer.Write 时,我无法更改 ctx.Next 并且什么也没有。因为 gin 不是那样工作的。

func (r *mutationResolver) Login(ctx context.Context,email string,password string) (bool,error) {
        // You need ctx.Writer to set a cookie and can't access that from here
}

我已经解决了这个问题,我想在下面回答我自己的问题。

解决方法

middleware 中,您必须构建一个 struct 对象,将 ctx.Writer 传递给它并将指针设置为 ctx.Request.Context 并设置一个方法来为您设置 cookie。

type CookieAccess struct {
    Writer     http.ResponseWriter
    UserId     uint64
    IsLoggedIn bool
}
// method to write cookie
func (this *CookieAccess) SetToken(token string) {
    http.SetCookie(this.Writer,&http.Cookie{
        Name:     cookieName,Value:    token,HttpOnly: true,Path:     "/",Expires:  time.Now().Add(token_expire),})
}

在您的 middleware 中:

func extractUserId(ctx *gin.Context) (uint64,error) {
    c,err := ctx.Request.Cookie(cookieName)
    if err != nil {
        return 0,errors.New("There is no token in cookies")
    }

    userId,err := ParseToken(c.Value)
    if err != nil {
        return 0,err
    }
    return userId,nil
}

func setValInCtx(ctx *gin.Context,val interface{}) {
    newCtx := context.WithValue(ctx.Request.Context(),cookieAccessKeyCtx,val)
    ctx.Request = ctx.Request.WithContext(newCtx)
}

func Middleware() gin.HandlerFunc {
    return func(ctx *gin.Context) {
        cookieA := CookieAccess{
            Writer: ctx.Writer,}

        // &cookieA is a pointer so any changes in future is changing cookieA is context
        setValInCtx(ctx,&cookieA)

        userId,err := extractUserId(ctx)
        if err != nil {
            cookieA.IsLoggedIn = false
            ctx.Next()
            return
        }

        cookieA.UserId = userId
        cookieA.IsLoggedIn = true

       // calling the actual resolver
        ctx.Next()
       // here will execute after resolver and all other middlewares was called
       // so &cookieA is safe from garbage collector
    }
}

你必须在你的解析器中调用这个函数。 它正在获取 ctx 并返回 &cookieA

func GetCookieAccess(ctx context.Context) *CookieAccess {
    return ctx.Value(cookieAccessKeyCtx).(*CookieAccess)
}

最后在您的 Login 解析器中:

CA := security.GetCookieAccess(ctx)
CA.SetToken(token)
CA.UserId = userId

我希望这会对某人有所帮助:)))