英文:
CookieJar does not catch incoming cookies
问题
我正在尝试使用Go在网页上提交一个表单来模拟登录。然后,我尝试使用cookies来保持一个持久的会话,以便再次调用子页面。
我能够成功地进行登录,没有任何问题,只是在捕获返回服务器设置的cookies时遇到了问题。我想知道是否因为他们的登录脚本进行了几次重定向?(我正在获取输出)。
有什么想法为什么我没有捕获到返回的cookies吗?
以下是我使用的代码:
import (
"crypto/tls"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strings"
"sync"
)
type Jar struct {
lk sync.Mutex
cookies map[string][]*http.Cookie
}
var CookieJar *Jar
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 NewClient() *http.Client {
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: false},
}
CookieJar = NewJar()
client := &http.Client{
Transport: tr,
CheckRedirect: nil,
Jar: CookieJar,
}
return client
}
func Login() {
client := NewClient()
api := "https://www.statuscake.com/App/"
uri, _ := url.Parse("https://www.statuscake.com")
fmt.Printf("uri: %s\n", uri)
values := url.Values{}
values.Add("username", username)
values.Add("password", password)
values.Add("Login", "yes")
values.Add("redirect", "")
str := values.Encode()
req, err := http.NewRequest("POST", api, strings.NewReader(str))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Accept", "text/html")
req.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.65 Safari/537.36")
cookies := CookieJar.Cookies(uri)
for i := 0; i < len(cookies); i++ {
fmt.Printf("Cookie[%d]: %s", i, cookies[i])
req.AddCookie(cookies[i])
}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
fmt.Printf("Response: %v\n", resp)
fmt.Printf("Response.Cookies: %v\n", resp.Cookies())
cookies = resp.Cookies()
CookieJar.SetCookies(uri, cookies)
defer resp.Body.Close()
if resp.StatusCode == 200 {
fmt.Printf("\n\n-----\n")
fmt.Println("HTTP Code: ", resp.StatusCode)
fmt.Println("Response Cookies: ", resp.Cookies())
fmt.Println("Request Headers: ", req.Header)
fmt.Println("Request Cookies: ", req.Cookies())
fmt.Println("Response Headers: ", resp.Header)
fmt.Printf("-----\n\n")
}
}
希望对你有帮助!
英文:
I'm trying to have Go submit a form on a webpage for me to simulate a login. From there I'm trying to use the cookies to keep a persistent session for one more call to a sub-page.
I'm able to successfully do the log in with no issues, I'm just having issues catching the cookies being set by the returning server. I'm wondering if it's because their login script does several redirects? (I am getting an output).
Any ideas why I'm not catching the cookies being returned?
Here is the code I'm using:
import (
"crypto/tls"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strings"
"sync"
)
type Jar struct {
lk sync.Mutex
cookies map[string][]*http.Cookie
}
var CookieJar *Jar
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 NewClient() *http.Client {
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: false},
}
CookieJar = NewJar()
client := &http.Client{
Transport: tr,
CheckRedirect: nil,
Jar: CookieJar,
}
return client
}
func Login() {
client := NewClient()
api := "https://www.statuscake.com/App/"
uri, _ := url.Parse("https://www.statuscake.com")
fmt.Printf("uri: %s\n", uri)
values := url.Values{}
values.Add("username", username)
values.Add("password", password)
values.Add("Login", "yes")
values.Add("redirect", "")
str := values.Encode()
req, err := http.NewRequest("POST", api, strings.NewReader(str))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Accept", "text/html")
req.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.65 Safari/537.36")
cookies := CookieJar.Cookies(uri)
for i := 0; i < len(cookies); i++ {
fmt.Printf("Cookie[%d]: %s", i, cookies[i])
req.AddCookie(cookies[i])
}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
fmt.Printf("Response: %v\n", resp)
fmt.Printf("Response.Cookies: %v\n", resp.Cookies())
cookies = resp.Cookies()
CookieJar.SetCookies(uri, cookies)
defer resp.Body.Close()
if resp.StatusCode == 200 {
fmt.Printf("\n\n-----\n")
fmt.Println("HTTP Code: ", resp.StatusCode)
fmt.Println("Response Cookies: ", resp.Cookies())
fmt.Println("Request Headers: ", req.Header)
fmt.Println("Request Cookies: ", req.Cookies())
fmt.Println("Response Headers: ", resp.Header)
fmt.Printf("-----\n\n")
}
}
答案1
得分: 0
不确定问题出在哪里,但有两点需要注意:
-
如果你的客户端有一个可用的 Jar,就没有必要手动填充请求的 cookies。客户端应该透明地处理所有的 cookie 相关事务:它从响应中提取 cookies 并存储在 jar 中,并使用 jar 中的 cookies 填充响应(即使在重定向期间也是如此)。也许这会覆盖你手动设置的 cookies。
-
不要自己编写 CookieJar 实现。处理 cookie 是很糟糕的(你可以相信我)。只需使用 http://golang.org/pkg/net/http/cookiejar/,也许结合 code.google.com/p/go.net/publicsuffix 使用。
英文:
Not sure where the problem really is, but two notes:
-
There is no need to populate the request manually with cookies if your Client has a working Jar. The client should handle all cookie stuff transparently for you: It extracts cookies from the response and store in the jar and populates the response with cookies from the jar (even during redirects). Maybe this overwrites your manually set cookies.
-
Do not roll your own CookieJar implementation. Cookie handling is awful (you may believe me). Just use http://golang.org/pkg/net/http/cookiejar/ maybe in combination with code.google.com/p/go.net/publicsuffix
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论