Go’s cookiejar doesn’t have any function to persistence cookies, so you need to do something to save cookies to a local file. To make it easy, you can use juju/persistent-cookiejar instead.
       juju
       / 
        persistent-cookiejar
      
        juju
       / 
        persistent-cookiejar
      
    
    cookiejar is a fork of net/http/cookiejar that allows serialisation of the stored cookies
cookiejar
-- import "github.com/juju/persistent-cookiejar"
Package cookiejar implements an in-memory RFC 6265-compliant http.CookieJar.
This implementation is a fork of net/http/cookiejar which also implements methods for dumping the cookies to persistent storage and retrieving them.
Usage
func DefaultCookieFile
func DefaultCookieFile() string
DefaultCookieFile returns the default cookie file to use for persisting cookie data. The following names will be used in decending order of preference:
- the value of the $GOCOOKIES environment variable.
- $HOME/.go-cookies
type Jar
type Jar struct {
}
Jar implements the http.CookieJar interface from the net/http package.
func New
func New(o *Options) (*Jar, error)
New returns a new cookie jar. A nil *Options is equivalent to a zero Options.
New will return an error if the cookies could not be loaded from the file for any reason than if the file does not exist.
func (*Jar) Cookies
func (j…Usage
You can use it as same as net/http/cookiejar, and can save cookies by Save.
jar, _ := cookiejar.New(nil)
http.DefaultClient.Jar = jar
// Some tasks
jar.Save()
Where to save is decided by an option you put into New; it is set to $GOCOOKIES or $HOME/.go-cookies by default. If the file doesn't exist, it returns no errors and creates it when saving.
jar, _ := cookiejar.New(&cookiejar.Options{Filename: "path/to/cookie"})
Try to use
This is a sample program to log in to AtCoder. It outputs Already logged in! if you've already logged in, or asks your username and password if not yet.
code
  
Some error handlings were omitted.
package main
import (
    "fmt"
    "log"
    "net/http"
    "net/url"
    "os"
    "strings"
    "github.com/PuerkitoBio/goquery"
    "github.com/juju/persistent-cookiejar"
    "golang.org/x/term"
)
func main() {
    jar, _ := cookiejar.New(nil)
    http.DefaultClient.Jar = jar
    defer jar.Save()
    // If the file exists, check whether logged in
    _, err := os.Stat(cookiejar.DefaultCookieFile())
    if err == nil {
        doc, _ := getDocument("https://atcoder.jp/home")
        navbarRight := doc.Find("div#navbar-collapse > ul.navbar-right")
        if navbarRight.Children().Length() == 2 {
            fmt.Println("Already logged in!")
            return
        }
    }
    var username string
    fmt.Print("Username: ")
    fmt.Scan(&username)
    fmt.Print("Password: ")
    // Don't press ctrl+c while Go reads password because your terminal won't display any inputs after that.
    // To resolve it, see gist.github.com/montanaflynn/5ae3eeae7212b0ba232f46e88f1ab67f
    bypePassword, _ := term.ReadPassword(int(os.Stdin.Fd()))
    loginUrl := "https://atcoder.jp/login"
    doc, _ := getDocument(loginUrl)
    token, found := doc.Find(`form input[type="hidden"]`).Attr("value")
    if !found {
        log.Fatal("error: cannot find CSRF token")
    }
    values := url.Values{
        "username":   {username},
        "password":   {string(bypePassword)},
        "csrf_token": {token},
    }
    req, _ := http.NewRequest("POST", loginUrl, strings.NewReader(values.Encode()))
    req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()
    if resp.Request.URL.String() == loginUrl {
        log.Fatal("Failed to login. Check your username/password")
    }
    fmt.Println("Successfully logged in!")
}
func getDocument(url string) (*goquery.Document, error) {
    resp, err := http.Get(url)
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()
    return goquery.NewDocumentFromReader(resp.Body)
}
Now you can find the cookie as a file.
$ cat ~/.go-cookies
[{"Name":"REVEL_SESSION","Value":"xxxxx...","Domain":"atcoder.jp","Path":"/","Secure":true,"HttpOnly":true,"Persistent":true,"HostOnly":true,"Expires":"2022-09-13T18:19:25.9840269+09:00","Creation":"2022-03-17T18:19:15.4703732+09:00","LastAccess":"2022-03-17T18:19:25.9840269+09:00","Updated":"2022-03-17T18:19:25.9840269+09:00","CanonicalHost":"atcoder.jp"}]
If you execute it again when the file exists,
$ go run main.go
Already logged in!
it won't ask you username/password.
 

 
    
Top comments (0)