Fasthttp: Cookie support for client?

Created on 27 Oct 2018  路  2Comments  路  Source: valyala/fasthttp

If I do a request to any page behind cloudflare it always tells me "Please enable cookies". (How) can I do this with fasthttp?

Most helpful comment

Both Client and HostClient currently don't handle cookies during redirects. I guess this is something we should add at some point as it can be quite useful.

For now you could wrap Client using the following code. I have only quickly tested this so there might be cases where this doesn't work properly.

package main

import (
    "fmt"
    "time"

    "github.com/valyala/fasthttp"
)

var (
    strLocation = []byte("Location")
)

type CookieClient struct {
    fasthttp.Client
}

func (c *CookieClient) Do(req *fasthttp.Request, resp *fasthttp.Response) error {
    for {
        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()) {
                req.Header.DelCookieBytes(key)
            } else {
                req.Header.SetCookieBytesKV(key, c.Value())
            }
        })
    }

    return nil
}

func main() {
    c := CookieClient{}

    req := fasthttp.AcquireRequest()
    defer fasthttp.ReleaseRequest(req)
    resp := fasthttp.AcquireResponse()
    defer fasthttp.ReleaseResponse(resp)

    req.SetRequestURI("https://dubbelboer.com/cookietest/test.php?1")

    if err := c.Do(req, resp); err != nil {
        panic(err)
    }

    println(string(resp.Body()))
}

All 2 comments

You can use this library instead of peeking field by field in Request/Response. https://github.com/dgrr/cookiejar

Both Client and HostClient currently don't handle cookies during redirects. I guess this is something we should add at some point as it can be quite useful.

For now you could wrap Client using the following code. I have only quickly tested this so there might be cases where this doesn't work properly.

package main

import (
    "fmt"
    "time"

    "github.com/valyala/fasthttp"
)

var (
    strLocation = []byte("Location")
)

type CookieClient struct {
    fasthttp.Client
}

func (c *CookieClient) Do(req *fasthttp.Request, resp *fasthttp.Response) error {
    for {
        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()) {
                req.Header.DelCookieBytes(key)
            } else {
                req.Header.SetCookieBytesKV(key, c.Value())
            }
        })
    }

    return nil
}

func main() {
    c := CookieClient{}

    req := fasthttp.AcquireRequest()
    defer fasthttp.ReleaseRequest(req)
    resp := fasthttp.AcquireResponse()
    defer fasthttp.ReleaseResponse(resp)

    req.SetRequestURI("https://dubbelboer.com/cookietest/test.php?1")

    if err := c.Do(req, resp); err != nil {
        panic(err)
    }

    println(string(resp.Body()))
}
Was this page helpful?
0 / 5 - 0 ratings