问题描述
我正在使用杜松子酒和 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
我希望这会对某人有所帮助:)))