@@ -3,17 +3,47 @@ package cookiejar
import (
"bytes"
"encoding/gob"
"fmt"
"github.com/bytedance/sonic"
"io"
"likedream-goframe/internal/utils"
"net/http"
"net/url"
"strings"
"sync"
)
type hostMap map [ string ] cookieMap
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 {
hostMap hostMap
* sync . RWMutex
@@ -40,7 +70,23 @@ func (p *PersistCookieJar) SetCookies(u *url.URL, cookies []*http.Cookie) {
if p . hostMap [ host ] == nil {
p . hostMap [ host ] = make ( cookieMap )
}
p . hostMap [ host ] [ cookie . Name ] = cookie
// 如果 cookie 没有设置 Path,使用默认值 "/"
cookiePath := cookie . Path
if cookiePath == "" {
cookiePath = "/"
}
// 使用 name 和 path 的组合作为 key
key := cookieKey ( cookie . Name , cookiePath )
// 如果 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
}
}
}
@@ -50,10 +96,23 @@ func (p *PersistCookieJar) Cookies(u *url.URL) []*http.Cookie {
defer p . RUnlock ( )
host := u . Host
requestPath := u . Path
if requestPath == "" {
requestPath = "/"
}
if cookies , exists := p . hostMap [ host ] ; exists {
result := make ( [ ] * http . Cookie , 0 , len ( cookies ) )
for _ , cookie := range cookies {
result = append ( result , cookie )
// 检查 cookie 的 path 是否匹配请求的 path
cookiePath := cookie . Path
if cookiePath == "" {
cookiePath = "/"
}
if pathMatch ( requestPath , cookiePath ) {
result = append ( result , cookie )
}
}
return result
}