我用的是杜松子酒和gqlgen。我需要从解析器设置cookie,但我的解析器中只有上下文和来自graphQL的输入。这个问题已经在github中得到了回答。但这一次不同,因为当你尝试传入ctx.Next时,我不能改变ctx.Writer.Write和任何东西。因为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
}我已经解决了这个问题,下面我想回答我自己的问题。
发布于 2021-02-08 01:08:42
在middleware中,您必须构建一个结构对象,将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我希望这能帮助到某些人:))
https://stackoverflow.com/questions/66090686
复制相似问题