[fix]: 当用户自定义http client的时候 cookie 无法被反序列化的问题 (#205)
This commit is contained in:
parent
63143f9364
commit
30da2df475
6
bot.go
6
bot.go
@ -285,10 +285,10 @@ func (b *Bot) DumpHotReloadStorage() error {
|
||||
// DumpTo 将热登录需要的数据写入到指定的 io.Writer 中
|
||||
// 注: 写之前最好先清空之前的数据
|
||||
func (b *Bot) DumpTo(writer io.Writer) error {
|
||||
cookies := b.Caller.Client.GetCookieJar()
|
||||
jar := b.Caller.Client.Jar()
|
||||
item := HotReloadStorageItem{
|
||||
BaseRequest: b.Storage.Request,
|
||||
Jar: cookies,
|
||||
Jar: fromCookieJar(jar),
|
||||
LoginInfo: b.Storage.LoginInfo,
|
||||
WechatDomain: b.Caller.Client.Domain,
|
||||
UUID: b.uuid,
|
||||
@ -320,7 +320,7 @@ func (b *Bot) reload() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b.Caller.Client.Jar = item.Jar.AsCookieJar()
|
||||
b.Caller.Client.SetCookieJar(item.Jar)
|
||||
b.Storage.LoginInfo = item.LoginInfo
|
||||
b.Storage.Request = item.BaseRequest
|
||||
b.Caller.Client.Domain = item.WechatDomain
|
||||
|
67
client.go
67
client.go
@ -15,7 +15,6 @@ import (
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -33,30 +32,44 @@ func (u UserAgentHook) BeforeRequest(req *http.Request) {
|
||||
req.Header.Add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36")
|
||||
}
|
||||
|
||||
func (u UserAgentHook) AfterRequest(response *http.Response, err error) {}
|
||||
func (u UserAgentHook) AfterRequest(_ *http.Response, _ error) {}
|
||||
|
||||
// Client http请求客户端
|
||||
// 客户端需要维持Session会话
|
||||
// 并且客户端不允许跳转
|
||||
type Client struct {
|
||||
// 设置一些client的请求行为
|
||||
// see normalMode desktopMode
|
||||
mode Mode
|
||||
|
||||
// client http客户端
|
||||
client *http.Client
|
||||
|
||||
// Domain 微信服务器请求域名
|
||||
// 这个参数会在登录成功后被赋值
|
||||
// 之后所有的请求都会使用这个域名
|
||||
// 在登录热登录和扫码登录时会被重新赋值
|
||||
Domain WechatDomain
|
||||
|
||||
// HttpHooks 请求上下文钩子
|
||||
HttpHooks HttpHooks
|
||||
*http.Client
|
||||
Domain WechatDomain
|
||||
mode Mode
|
||||
mu sync.Mutex
|
||||
|
||||
// MaxRetryTimes 最大重试次数
|
||||
MaxRetryTimes int
|
||||
}
|
||||
|
||||
func NewClient() *Client {
|
||||
timeout := 30 * time.Second
|
||||
return &Client{
|
||||
Client: &http.Client{
|
||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
},
|
||||
Jar: newCookieJar(),
|
||||
Timeout: timeout,
|
||||
}}
|
||||
httpClient := &http.Client{
|
||||
// 设置客户端不自动跳转
|
||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
},
|
||||
// 设置30秒超时
|
||||
// 因为微信同步消息时是一个时间长达25秒的长轮训
|
||||
Timeout: 30 * time.Second,
|
||||
}
|
||||
client := &Client{client: httpClient}
|
||||
client.SetCookieJar(NewJar())
|
||||
return client
|
||||
}
|
||||
|
||||
// DefaultClient 自动存储cookie
|
||||
@ -81,7 +94,7 @@ func (c *Client) do(req *http.Request) (*http.Response, error) {
|
||||
err error
|
||||
)
|
||||
for i := 0; i < c.MaxRetryTimes; i++ {
|
||||
resp, err = c.Client.Do(req)
|
||||
resp, err = c.client.Do(req)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
@ -101,9 +114,17 @@ func (c *Client) Do(req *http.Request) (*http.Response, error) {
|
||||
return c.do(req)
|
||||
}
|
||||
|
||||
// GetCookieJar 获取当前client的所有的有效的client
|
||||
func (c *Client) GetCookieJar() *Jar {
|
||||
return fromCookieJar(c.Client.Jar)
|
||||
// Jar 返回当前client的 http.CookieJar
|
||||
// this http.CookieJar must be *Jar type
|
||||
func (c *Client) Jar() http.CookieJar {
|
||||
return c.client.Jar
|
||||
}
|
||||
|
||||
// SetCookieJar 设置cookieJar
|
||||
// 这里限制了cookieJar必须是Jar类型
|
||||
// 否则进行cookie序列化的时候因为字段的私有性无法进行所有字段的导出
|
||||
func (c *Client) SetCookieJar(jar *Jar) {
|
||||
c.client.Jar = jar.AsCookieJar()
|
||||
}
|
||||
|
||||
// GetLoginUUID 获取登录的uuid
|
||||
@ -114,7 +135,7 @@ func (c *Client) GetLoginUUID() (*http.Response, error) {
|
||||
// GetLoginQrcode 获取登录的二维吗
|
||||
func (c *Client) GetLoginQrcode(uuid string) (*http.Response, error) {
|
||||
path := qrcode + uuid
|
||||
return c.Get(path)
|
||||
return c.client.Get(path)
|
||||
}
|
||||
|
||||
// CheckLogin 检查是否登录
|
||||
@ -336,7 +357,7 @@ func (c *Client) WebWxUploadMediaByChunk(file *os.File, request *BaseRequest, in
|
||||
|
||||
path.RawQuery = params.Encode()
|
||||
|
||||
cookies := c.Jar.Cookies(path)
|
||||
cookies := c.Jar().Cookies(path)
|
||||
webWxDataTicket := getWebWxDataTicket(cookies)
|
||||
|
||||
uploadMediaRequest := map[string]interface{}{
|
||||
@ -576,7 +597,7 @@ func (c *Client) WebWxGetMedia(msg *Message, info *LoginInfo) (*http.Response, e
|
||||
params.Add("encryfilename", msg.EncryFileName)
|
||||
params.Add("fromuser", strconv.FormatInt(info.WxUin, 10))
|
||||
params.Add("pass_ticket", info.PassTicket)
|
||||
params.Add("webwx_data_ticket", getWebWxDataTicket(c.Jar.Cookies(path)))
|
||||
params.Add("webwx_data_ticket", getWebWxDataTicket(c.Jar().Cookies(path)))
|
||||
path.RawQuery = params.Encode()
|
||||
req, _ := http.NewRequest(http.MethodGet, path.String(), nil)
|
||||
req.Header.Add("Referer", c.Domain.BaseHost()+"/")
|
||||
|
12
jar.go
12
jar.go
@ -16,7 +16,7 @@ type Jar struct {
|
||||
mu sync.Mutex
|
||||
|
||||
// Entries is a set of entries, keyed by their eTLD+1 and subkeyed by
|
||||
// their name/domain/path.
|
||||
// their name/Domain/path.
|
||||
Entries map[string]map[string]entry
|
||||
|
||||
// nextSeqNum is the next sequence number assigned to a new cookie
|
||||
@ -29,15 +29,15 @@ func (j *Jar) AsCookieJar() http.CookieJar {
|
||||
return (*cookiejar.Jar)(unsafe.Pointer(j))
|
||||
}
|
||||
|
||||
func newCookieJar() http.CookieJar {
|
||||
jar, _ := cookiejar.New(nil)
|
||||
return jar
|
||||
}
|
||||
|
||||
func fromCookieJar(jar http.CookieJar) *Jar {
|
||||
return (*Jar)(unsafe.Pointer(jar.(*cookiejar.Jar)))
|
||||
}
|
||||
|
||||
func NewJar() *Jar {
|
||||
jar, _ := cookiejar.New(nil)
|
||||
return fromCookieJar(jar)
|
||||
}
|
||||
|
||||
type entry struct {
|
||||
Name string
|
||||
Value string
|
||||
|
Loading…
x
Reference in New Issue
Block a user