Question

I'm trying to use Go to log into a website and store the cookies for later use.

Could you give example code for posting a form, storing the cookies, and accessing another page using the cookies?

I think I might need to make a Client to store the cookies, by studying http://gotour.golang.org/src/pkg/net/http/client.go

package main

import ("net/http"
        "log"
        "net/url"
        )

func Login(user, password string) string {
        postUrl := "http://www.pge.com/eum/login"

        // Set up Login
        values := make(url.Values)
        values.Set("user", user)
        values.Set("password", password)

        // Submit form
        resp, err := http.PostForm(postUrl, values)
        if err != nil {
                log.Fatal(err)
        }
        defer resp.Body.Close()

        // How do I store cookies?
        return "Hello"
}

func ViewBill(url string, cookies) string {

//What do I put here?

}
Was it helpful?

Solution

Go 1.1 introduced a cookie jar implementation net/http/cookiejar.

import (
    "net/http"
    "net/http/cookiejar"
)

jar, err := cookiejar.New(nil)
if err != nil { // error handling }

client := &http.Client{
    Jar: jar,
}

OTHER TIPS

First you'll need to implement the http.CookieJar interface. You can then pass this into the client you create and it will be used for requests made with the client. As a basic example:

package main

import (
    "fmt"
    "net/http"
    "net/url"
    "io/ioutil"
    "sync"
)

type Jar struct {
    lk      sync.Mutex
    cookies map[string][]*http.Cookie
}

func NewJar() *Jar {
    jar := new(Jar)
    jar.cookies = make(map[string][]*http.Cookie)
    return jar
}

// SetCookies handles the receipt of the cookies in a reply for the
// given URL.  It may or may not choose to save the cookies, depending
// on the jar's policy and implementation.
func (jar *Jar) SetCookies(u *url.URL, cookies []*http.Cookie) {
    jar.lk.Lock()
    jar.cookies[u.Host] = cookies
    jar.lk.Unlock()
}

// Cookies returns the cookies to send in a request for the given URL.
// It is up to the implementation to honor the standard cookie use
// restrictions such as in RFC 6265.
func (jar *Jar) Cookies(u *url.URL) []*http.Cookie {
    return jar.cookies[u.Host]
}

func main() {
    jar := NewJar()
    client := http.Client{nil, nil, jar}

    resp, _ := client.PostForm("http://www.somesite.com/login", url.Values{
        "email": {"myemail"},
        "password": {"mypass"},
    })
    resp.Body.Close()

    resp, _ = client.Get("http://www.somesite.com/protected")

    b, _ := ioutil.ReadAll(resp.Body)
    resp.Body.Close()

    fmt.Println(string(b))
}

At the version 1.5 of Go, we can use http.NewRequest to make a post request with cookie.

package main                                                                                              
import "fmt"
import "net/http"
import "io/ioutil"
import "strings"

func main() {
    // Declare http client
    client := &http.Client{}

    // Declare post data
    PostData := strings.NewReader("useId=5&age=12")

    // Declare HTTP Method and Url
    req, err := http.NewRequest("POST", "http://localhost/", PostData)

    // Set cookie
    req.Header.Set("Cookie", "name=xxxx; count=x")
    resp, err := client.Do(req)
    // Read response
    data, err := ioutil.ReadAll(resp.Body)

    // error handle
    if err != nil {
        fmt.Printf("error = %s \n", err);
    }   

    // Print response
    fmt.Printf("Response = %s", string(data));
}           

net/http/cookiejar is a good option, but I like to know what cookies are actually required when I am making my requests. You can get the response cookies like this:

package main
import "net/http"

func main() {
   r, e := http.Get("https://stackoverflow.com")
   if e != nil {
      panic(e)
   }
   for _, c := range r.Cookies() {
      println(c.Name, c.Value)
   }
}

and you can add cookies like this:

package main
import "net/http"

func main() {
   r, e := http.NewRequest("GET", "https://stackoverflow.com", nil)
   if e != nil {
      panic(e)
   }
   r.AddCookie(&http.Cookie{Name: "west", Value: "left"})
}

Another way of doing it. Works in Go 1.8.

    expiration := time.Now().Add(5 * time.Minute)
    cookie := http.Cookie{Name: "myCookie", Value: "Hello World", Expires: expiration}
    http.SetCookie(w, &cookie)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top