go – Save cookies for maintained session using fasthttp library

Exception or error:

I have been pulling my hair out recently, I need to find a way to save cookies after a post request to a URI, so that I can send requests to other endpoints and maintain that session. I am trying to add an item to cart but without saving the cookies the cart will be empty. (shopping cart) I am currently using this to handle cookies but doesn’t seem to forward the cookies to next request:

func (c *CookieClient) Do(req *fasthttp.Request, resp *fasthttp.Response) error {
for {
    zap.S().Info("Saving Cookie")
    if err := c.Client.Do(req, resp); err != nil {
        return err
    }

    statusCode := resp.Header.StatusCode()
    if statusCode != fasthttp.StatusMovedPermanently &&
        statusCode != fasthttp.StatusFound &&
        statusCode != fasthttp.StatusSeeOther &&
        statusCode != fasthttp.StatusTemporaryRedirect &&
        statusCode != fasthttp.StatusPermanentRedirect {
        break
    }

    location := resp.Header.PeekBytes(strLocation)
    if len(location) == 0 {
        return fmt.Errorf("Redirect with missing Location header")
    }

    u := req.URI()
    u.UpdateBytes(location)

    resp.Header.VisitAllCookie(func(key, value []byte) {
        c := fasthttp.AcquireCookie()
        defer fasthttp.ReleaseCookie(c)

        c.ParseBytes(value)

        if expire := c.Expire(); expire != fasthttp.CookieExpireUnlimited && expire.Before(time.Now()) {
            zap.S().Info("Deleting Expired Cookie")
            req.Header.DelCookieBytes(key)
        } else {
            req.Header.SetCookieBytesKV(key, c.Value())
        }
    })
}
return nil

}

How to solve:

Probably the authors can have an efficient way:

You can retrieve the cookie with the following method, then you can reassign it to another request.

func ParseTokenFromRequest(ctx *fasthttp.RequestCtx) string {
    token := string(ctx.Request.Header.Cookie("GoLog-Token")) // GoLog-Token is the hardcoded name of the cookie
    return token
}

Then you can create the cookie with the value already retrieved:

//CreateCookie Method that return a cookie valorized as input (GoLog-Token as key)
func CreateCookie(key string, value string, expire int) *fasthttp.Cookie {
    if strings.Compare(key, "") == 0 {
        key = "GoLog-Token"
    }
    log.Debug("CreateCookie | Creating Cookie | Key: ", key, " | Val: ", value)
    authCookie := fasthttp.Cookie{}
    authCookie.SetKey(key)
    authCookie.SetValue(value)
    authCookie.SetMaxAge(expire)
    authCookie.SetHTTPOnly(true)
    authCookie.SetSameSite(fasthttp.CookieSameSiteLaxMode)
    return &authCookie
}

And then you can forward the cookie or save it into a (maybe in-memory) db:

authcookie := CreateCookie("GoLog-Token", token, cfg.Redis.Token.Expire)
ctx.Response.Header.SetCookie(authcookie)
// store cookie here

Leave a Reply

Your email address will not be published. Required fields are marked *