🐛 尝试解决cookie jar的问题

This commit is contained in:
sugarBecomer
2025-11-17 12:03:47 +08:00
parent 1fff983d37
commit 29fc69d022
3 changed files with 127 additions and 66 deletions
+54 -5
View File
@@ -67,7 +67,23 @@ func (a *AllSavePersistCookieJar) SetCookies(u *url.URL, cookies []*http.Cookie)
if a.domainMap[mainDomain] == nil { if a.domainMap[mainDomain] == nil {
a.domainMap[mainDomain] = make(cookieMap) a.domainMap[mainDomain] = make(cookieMap)
} }
a.domainMap[mainDomain][cookie.Name] = cookie
// 查找是否存在相同 name, path 和 domain 的 cookie
existingCookies := a.domainMap[mainDomain][cookie.Name]
found := false
for i, existing := range existingCookies {
if existing.Path == cookie.Path && existing.Domain == cookie.Domain {
// 找到完全匹配的 cookie,替换它
existingCookies[i] = cookie
found = true
break
}
}
if !found {
// 没有找到匹配的,添加新的 cookie
a.domainMap[mainDomain][cookie.Name] = append(a.domainMap[mainDomain][cookie.Name], cookie)
}
} }
} }
@@ -78,10 +94,43 @@ func (a *AllSavePersistCookieJar) Cookies(u *url.URL) []*http.Cookie {
// 提取主域名 // 提取主域名
mainDomain := extractMainDomain(u.Host) mainDomain := extractMainDomain(u.Host)
if cookies, exists := a.domainMap[mainDomain]; exists { if cookiesList, exists := a.domainMap[mainDomain]; exists {
result := make([]*http.Cookie, 0, len(cookies)) result := make([]*http.Cookie, 0, len(cookiesList))
for _, cookie := range cookies { requestPath := u.Path
result = append(result, cookie) if requestPath == "" {
requestPath = "/"
}
for _, cookies := range cookiesList {
// 如果只有一个 cookie,直接返回
if len(cookies) == 1 {
result = append(result, cookies[0])
continue
}
// 有多个同名 cookie,选择最匹配的(path 最长且匹配请求路径的)
var bestMatch *http.Cookie
bestMatchLen := -1
for _, cookie := range cookies {
cookiePath := cookie.Path
if cookiePath == "" {
cookiePath = "/"
}
// 检查 path 是否匹配
if pathMatch(requestPath, cookiePath) {
if len(cookiePath) > bestMatchLen {
bestMatch = cookie
bestMatchLen = len(cookiePath)
}
}
}
// 如果找到匹配的,添加到结果中
if bestMatch != nil {
result = append(result, bestMatch)
}
} }
return result return result
} }
+70 -58
View File
@@ -3,47 +3,19 @@ package cookiejar
import ( import (
"bytes" "bytes"
"encoding/gob" "encoding/gob"
"fmt"
"github.com/bytedance/sonic"
"io" "io"
"likedream-goframe/internal/utils" "likedream-goframe/internal/utils"
"net/http" "net/http"
"net/url" "net/url"
"strings" "strings"
"sync" "sync"
"github.com/bytedance/sonic"
) )
type hostMap map[string]cookieMap type hostMap map[string]cookieMap
type cookieMap map[string]*http.Cookie type cookieMap map[string][]*http.Cookie
// cookieKey 生成 cookie 的唯一标识 key,使用 name 和 path 的组合
func cookieKey(name, path string) string {
return fmt.Sprintf("%s|%s", name, path)
}
// pathMatch 检查请求路径是否匹配 cookie 的 path
// 根据 RFC 6265 Section 5.1.4
func pathMatch(requestPath, cookiePath string) bool {
// 如果路径完全相同
if requestPath == cookiePath {
return true
}
// 如果 cookie path 是请求 path 的前缀
if strings.HasPrefix(requestPath, cookiePath) {
// cookie path 以 / 结尾,或者请求 path 在 cookie path 后紧跟 /
if strings.HasSuffix(cookiePath, "/") {
return true
}
if len(requestPath) > len(cookiePath) && requestPath[len(cookiePath)] == '/' {
return true
}
}
return false
}
type PersistCookieJar struct { type PersistCookieJar struct {
hostMap hostMap hostMap hostMap
*sync.RWMutex *sync.RWMutex
@@ -63,7 +35,7 @@ func (p *PersistCookieJar) SetCookies(u *url.URL, cookies []*http.Cookie) {
host := u.Host host := u.Host
if _, exists := p.hostMap[host]; !exists { if _, exists := p.hostMap[host]; !exists {
p.hostMap = make(hostMap) p.hostMap[host] = make(cookieMap)
} }
for _, cookie := range cookies { for _, cookie := range cookies {
@@ -71,21 +43,21 @@ func (p *PersistCookieJar) SetCookies(u *url.URL, cookies []*http.Cookie) {
p.hostMap[host] = make(cookieMap) p.hostMap[host] = make(cookieMap)
} }
// 如果 cookie 没有设置 Path,使用默认值 "/" // 查找是否存在相同 name, path 和 domain 的 cookie
cookiePath := cookie.Path existingCookies := p.hostMap[host][cookie.Name]
if cookiePath == "" { found := false
cookiePath = "/" for i, existing := range existingCookies {
if existing.Path == cookie.Path && existing.Domain == cookie.Domain {
// 找到完全匹配的 cookie,替换它
existingCookies[i] = cookie
found = true
break
}
} }
// 使用 name 和 path 的组合作为 key if !found {
key := cookieKey(cookie.Name, cookiePath) // 没有找到匹配的,添加新的 cookie
p.hostMap[host][cookie.Name] = append(p.hostMap[host][cookie.Name], cookie)
// 如果 MaxAge=0 或 MaxAge<0,表示删除 cookie
// 只删除完全匹配的 cookie(name 和 path 都相同)
if cookie.MaxAge < 0 || (cookie.MaxAge == 0 && cookie.Value == "") {
delete(p.hostMap[host], key)
} else {
p.hostMap[host][key] = cookie
} }
} }
@@ -96,22 +68,42 @@ func (p *PersistCookieJar) Cookies(u *url.URL) []*http.Cookie {
defer p.RUnlock() defer p.RUnlock()
host := u.Host host := u.Host
requestPath := u.Path if cookiesList, exists := p.hostMap[host]; exists {
if requestPath == "" { result := make([]*http.Cookie, 0, len(cookiesList))
requestPath = "/" requestPath := u.Path
} if requestPath == "" {
requestPath = "/"
}
if cookies, exists := p.hostMap[host]; exists { for _, cookies := range cookiesList {
result := make([]*http.Cookie, 0, len(cookies)) // 如果只有一个 cookie,直接返回
for _, cookie := range cookies { if len(cookies) == 1 {
// 检查 cookie 的 path 是否匹配请求的 path result = append(result, cookies[0])
cookiePath := cookie.Path continue
if cookiePath == "" {
cookiePath = "/"
} }
if pathMatch(requestPath, cookiePath) { // 有多个同名 cookie,选择最匹配的(path 最长且匹配请求路径的)
result = append(result, cookie) var bestMatch *http.Cookie
bestMatchLen := -1
for _, cookie := range cookies {
cookiePath := cookie.Path
if cookiePath == "" {
cookiePath = "/"
}
// 检查 path 是否匹配
if pathMatch(requestPath, cookiePath) {
if len(cookiePath) > bestMatchLen {
bestMatch = cookie
bestMatchLen = len(cookiePath)
}
}
}
// 如果找到匹配的,添加到结果中
if bestMatch != nil {
result = append(result, bestMatch)
} }
} }
return result return result
@@ -119,6 +111,26 @@ func (p *PersistCookieJar) Cookies(u *url.URL) []*http.Cookie {
return nil return nil
} }
// pathMatch 检查请求路径是否匹配 cookie 的 path
// 根据 RFC 6265 的规则
func pathMatch(requestPath, cookiePath string) bool {
if requestPath == cookiePath {
return true
}
if strings.HasPrefix(requestPath, cookiePath) {
// cookiePath 以 / 结尾,或者 requestPath 的下一个字符是 /
if strings.HasSuffix(cookiePath, "/") {
return true
}
if len(requestPath) > len(cookiePath) && requestPath[len(cookiePath)] == '/' {
return true
}
}
return false
}
func (p *PersistCookieJar) Serialize() string { func (p *PersistCookieJar) Serialize() string {
p.RLock() p.RLock()
defer p.RUnlock() defer p.RUnlock()
+3 -3
View File
@@ -450,11 +450,11 @@ func submitCasKickOut(ctx context.Context, requestUrl string, doc *goquery.Docum
} }
func getCasValidLoginUrl(info *school.SchoolDetailInfo) string { func getCasValidLoginUrl(info *school.SchoolDetailInfo) string {
if strings.Contains(info.AmpUrl, "campusphere") { if strings.Contains(info.AmpUrl, "campusphere") || strings.Contains(info.AmpUrl, "wec-portal-mobile") {
return info.AmpUrl return info.AmpUrl
} else if strings.Contains(info.AmpUrl2, "campusphere") { } else if strings.Contains(info.AmpUrl2, "campusphere") || strings.Contains(info.AmpUrl2, "wec-portal-mobile") {
return info.AmpUrl2 return info.AmpUrl2
} else if strings.Contains(info.AmpUrl3, "campusphere") { } else if strings.Contains(info.AmpUrl3, "campusphere") || strings.Contains(info.AmpUrl3, "wec-portal-mobile") {
return info.AmpUrl3 return info.AmpUrl3
} }