Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: panic on go1.23 #535

Merged
merged 1 commit into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bot.go
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ func (b *Bot) DumpTo(writer io.Writer) error {
jar := b.Caller.Client.Jar()
item := HotReloadStorageItem{
BaseRequest: b.Storage.Request,
Jar: fromCookieJar(jar),
Jar: jar,
LoginInfo: b.Storage.LoginInfo,
WechatDomain: b.Caller.Client.Domain,
SyncKey: b.Storage.Response.SyncKey,
Expand Down
6 changes: 3 additions & 3 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,15 +166,15 @@ func (c *Client) Do(req *http.Request) (*http.Response, error) {

// Jar 返回当前client的 http.CookieJar
// this http.CookieJar must be *Jar type
func (c *Client) Jar() http.CookieJar {
return c.client.Jar
func (c *Client) Jar() *Jar {
return c.client.Jar.(*Jar)
}

// SetCookieJar 设置cookieJar
// 这里限制了cookieJar必须是Jar类型
// 否则进行cookie序列化的时候因为字段的私有性无法进行所有字段的导出
func (c *Client) SetCookieJar(jar *Jar) {
c.client.Jar = jar.AsCookieJar()
c.client.Jar = jar
}

// HTTPClient 返回http.Client
Expand Down
26 changes: 0 additions & 26 deletions cookie_entry_go1.23.go

This file was deleted.

27 changes: 0 additions & 27 deletions cookie_entry_pre_go1.23.go

This file was deleted.

63 changes: 45 additions & 18 deletions cookiejar.go
Original file line number Diff line number Diff line change
@@ -1,41 +1,68 @@
package openwechat

import (
"encoding/json"
"net/http"
"net/http/cookiejar"
"sync"
"unsafe"
"net/url"
)

// Jar is a struct which as same as cookiejar.Jar
// cookiejar.Jar's fields are private, so we can't use it directly
type Jar struct {
PsList cookiejar.PublicSuffixList

// mu locks the remaining fields.
mu sync.Mutex
jar *cookiejar.Jar
hosts map[string]*url.URL
}

// Entries is a set of entries, keyed by their eTLD+1 and subkeyed by
// their name/Domain/path.
Entries map[string]map[string]entry
// UnmarshalJSON implements the json.Unmarshaler interface
func (j *Jar) UnmarshalJSON(bytes []byte) error {
var cookies map[string][]*http.Cookie
if err := json.Unmarshal(bytes, &cookies); err != nil {
return err
}
if j.jar == nil {
j.jar, _ = cookiejar.New(nil)
}
for u, cs := range cookies {
u, err := url.Parse(u)
if err != nil {
return err
}
j.jar.SetCookies(u, cs)
}
return nil
}

// nextSeqNum is the next sequence number assigned to a new cookie
// created SetCookies.
NextSeqNum uint64
// MarshalJSON implements the json.Marshaler interface
func (j *Jar) MarshalJSON() ([]byte, error) {
var cookies = make(map[string][]*http.Cookie)
for path, u := range j.hosts {
cookies[path] = append(cookies[path], j.jar.Cookies(u)...)
}
return json.Marshal(cookies)
}

// AsCookieJar unsafe convert to http.CookieJar
func (j *Jar) AsCookieJar() http.CookieJar {
return (*cookiejar.Jar)(unsafe.Pointer(j))
func (j *Jar) SetCookies(u *url.URL, cookies []*http.Cookie) {
if j.hosts == nil {
j.hosts = make(map[string]*url.URL)
}
path := u.Scheme + "://" + u.Host
if _, exists := j.hosts[path]; !exists {
j.hosts[path] = u
}
j.jar.SetCookies(u, cookies)
}

func fromCookieJar(jar http.CookieJar) *Jar {
return (*Jar)(unsafe.Pointer(jar.(*cookiejar.Jar)))
func (j *Jar) Cookies(u *url.URL) []*http.Cookie {
return j.jar.Cookies(u)
}

func NewJar() *Jar {
jar, _ := cookiejar.New(nil)
return fromCookieJar(jar)
return &Jar{
jar: jar,
hosts: make(map[string]*url.URL),
}
}

// CookieGroup is a group of cookies
Expand Down
Loading