Search code examples
gofasthttp

How to create HTTP Session in Go


I am currently using fasthttp for sending my requests my question is, is there a way to have a persistent session? I need the cookies and data to stick.

c := fasthttp.Client{ Name: "Add To Cart",}

store, err := session.Start() // ?????
args := fasthttp.AcquireArgs()
defer fasthttp.ReleaseArgs(args)

args.Add("pid", sizepid)
args.Add("options", "[]")
args.Add("quantity", "1")

statusCode, body, err := c.Post(nil, "URL", args)
if err != nil {
    panic(err)
}`

Solution

  • Based on your question I think this is already clear to you, but just in case: Sessions aren't started on the client, they are started on the server. The server checks to see if a specific cookie exists; if it does it resumes the session that the cookie identifies; if it doesn't it creates a new session and sends the identifier back to the client as a cookie. All the client needs to do is send the correct cookie to the server.

    So, you need to read and write cookies. The fasthttp.Client.Post() interface doesn't allow you to do that. So instead of that nice interface, things become rather ugly.

    You need to ask fasthttp for both a Request and Response object before you do the request. Once you've done the initial request, you need to either look all cookies, or read out a specific cookie. You can now use those values for your next request.

    I've written a short example of how you would do this.

    func main() {
        c := fasthttp.Client{}
    
        // Create a request
        req := fasthttp.AcquireRequest()
        defer fasthttp.ReleaseRequest(req)
        req.SetRequestURI(`https://www.google.com/`)
    
        // Create a response
        resp := fasthttp.AcquireResponse()
        defer fasthttp.ReleaseResponse(resp)
    
        // Execute the request, writing to the response object
        err := c.Do(req, resp)
        if err != nil {
            panic(err)
        }
    
        //  Loop over all cookies; usefull if you want to just send everything back on consecutive requests
        resp.Header.VisitAllCookie(func(key, value []byte) {
            log.Printf("Cookie %s: %s\n", key, value)
        })
    
        // Read a specific cookie
        nid := fasthttp.AcquireCookie()
        defer fasthttp.ReleaseCookie(nid)
        nid.SetKey(`NID`)
        if resp.Header.Cookie(nid) {
            log.Println("Value for NID Cookie: " + string(nid.Value()))
    
            // Create a second request and set the cookie from the first
            req2 := fasthttp.AcquireRequest()
            defer fasthttp.ReleaseRequest(req2)
            req2.SetRequestURI(`https://www.google.com/`)
            req2.Header.SetCookie(`NID`, string(nid.Value()))
    
            // Now you can execute this request again using c.Do() - don't forget to acquire a new Response!
        }
    }
    

    Note: you can chose to skip the fasthttp.AcquireXXX() and defer fasthttp.ReleaseXXX(yyy) steps - but that would negate much (maybe most) of the performance benefits over using standard net/http, so if you go that route maybe just ditch fasthttp all together.