Files
likedream/internal/application/cookiejar/all_save_jar.go
T
2025-11-10 14:40:38 +08:00

161 lines
3.3 KiB
Go

package cookiejar
import (
"bytes"
"encoding/gob"
"github.com/bytedance/sonic"
"io"
"likedream-goframe/internal/utils"
"net/http"
"net/url"
"strings"
"sync"
)
type domainMap map[string]cookieMap
// AllSavePersistCookieJar 支持泛域名的 Cookie Jar
// 不同的二级域名会共享相同主域名的 cookies
// 例如: passport2.chaoxing.com 和 mooc1-api.chaoxing.com 共享 .chaoxing.com 的 cookies
type AllSavePersistCookieJar struct {
domainMap domainMap
*sync.RWMutex
}
func NewAllSavePersistCookieJar() *AllSavePersistCookieJar {
return &AllSavePersistCookieJar{
domainMap: make(domainMap),
RWMutex: &sync.RWMutex{},
}
}
// extractMainDomain 提取主域名
// 例如: passport2.chaoxing.com -> chaoxing.com
//
// mooc1-api.chaoxing.com -> chaoxing.com
// www.example.co.uk -> example.co.uk
func extractMainDomain(host string) string {
// 移除端口号
if colonIndex := strings.Index(host, ":"); colonIndex != -1 {
host = host[:colonIndex]
}
parts := strings.Split(host, ".")
if len(parts) <= 2 {
// 已经是主域名或单级域名
return host
}
// 处理特殊的二级顶级域名,如 .co.uk, .com.cn 等
// 简化处理:取最后两部分
// 更复杂的情况可以使用 publicsuffix 包
return strings.Join(parts[len(parts)-2:], ".")
}
func (a *AllSavePersistCookieJar) SetCookies(u *url.URL, cookies []*http.Cookie) {
a.Lock()
defer a.Unlock()
// 提取主域名
mainDomain := extractMainDomain(u.Host)
if _, exists := a.domainMap[mainDomain]; !exists {
a.domainMap[mainDomain] = make(cookieMap)
}
for _, cookie := range cookies {
if a.domainMap[mainDomain] == nil {
a.domainMap[mainDomain] = make(cookieMap)
}
a.domainMap[mainDomain][cookie.Name] = cookie
}
}
func (a *AllSavePersistCookieJar) Cookies(u *url.URL) []*http.Cookie {
a.RLock()
defer a.RUnlock()
// 提取主域名
mainDomain := extractMainDomain(u.Host)
if cookies, exists := a.domainMap[mainDomain]; exists {
result := make([]*http.Cookie, 0, len(cookies))
for _, cookie := range cookies {
result = append(result, cookie)
}
return result
}
return nil
}
func (a *AllSavePersistCookieJar) Serialize() string {
a.RLock()
defer a.RUnlock()
json, err := sonic.Marshal(a.domainMap)
utils.OkOrPanic(err)
return string(json)
}
func (a *AllSavePersistCookieJar) Deserialize(content string) {
a.Lock()
defer a.Unlock()
if content == "" {
a.domainMap = make(domainMap)
return
}
var domainMap domainMap
err := sonic.Unmarshal([]byte(content), &domainMap)
utils.OkOrPanic(err)
a.domainMap = domainMap
}
func (a *AllSavePersistCookieJar) SerializeBytes() []byte {
a.RLock()
defer a.RUnlock()
ret := make([]byte, 0)
retWriter := bytes.NewBuffer(ret)
err := gob.NewEncoder(retWriter).
Encode(a.domainMap)
utils.OkOrPanic(err)
return retWriter.Bytes()
}
func (a *AllSavePersistCookieJar) DeserializeBytes(content []byte) {
a.Lock()
defer a.Unlock()
if len(content) == 0 {
a.domainMap = make(domainMap)
return
}
retReader := bytes.NewBuffer(content)
var domainMap domainMap
err := gob.NewDecoder(retReader).
Decode(&domainMap)
utils.OkOrPanic(err)
a.domainMap = domainMap
}
func (a *AllSavePersistCookieJar) DeserializeReader(reader io.Reader) {
a.Lock()
defer a.Unlock()
var domainMap domainMap
err := gob.NewDecoder(reader).
Decode(&domainMap)
utils.OkOrPanic(err)
a.domainMap = domainMap
}