fix(extensions): bound cookie runtime state

This commit is contained in:
zarzet
2026-07-16 10:24:13 +07:00
parent b69f67a786
commit 07c9cf034f
3 changed files with 78 additions and 13 deletions
+57
View File
@@ -0,0 +1,57 @@
package gobackend
import (
"net/http"
"net/url"
"testing"
"time"
)
func TestSimpleCookieJarReplacesAndExpiresCookies(t *testing.T) {
jar, err := newSimpleCookieJar()
if err != nil {
t.Fatalf("newSimpleCookieJar: %v", err)
}
u, _ := url.Parse("https://api.example.com/path")
jar.SetCookies(u, []*http.Cookie{{Name: "session", Value: "old", Path: "/"}})
jar.SetCookies(u, []*http.Cookie{{Name: "session", Value: "new", Path: "/"}})
cookies := jar.Cookies(u)
if len(cookies) != 1 || cookies[0].Value != "new" {
t.Fatalf("replacement cookies = %#v", cookies)
}
jar.SetCookies(u, []*http.Cookie{{
Name: "session",
Value: "expired",
Path: "/",
Expires: time.Now().Add(-time.Hour),
MaxAge: -1,
}})
if cookies := jar.Cookies(u); len(cookies) != 0 {
t.Fatalf("expired cookies = %#v", cookies)
}
}
func TestSimpleCookieJarClearAndScope(t *testing.T) {
jar, err := newSimpleCookieJar()
if err != nil {
t.Fatalf("newSimpleCookieJar: %v", err)
}
apiURL, _ := url.Parse("https://api.example.com/private/resource")
otherURL, _ := url.Parse("https://other.example.com/private/resource")
publicURL, _ := url.Parse("https://api.example.com/public")
jar.SetCookies(apiURL, []*http.Cookie{{Name: "session", Value: "value", Path: "/private"}})
if len(jar.Cookies(apiURL)) != 1 {
t.Fatal("expected cookie for matching host and path")
}
if len(jar.Cookies(otherURL)) != 0 || len(jar.Cookies(publicURL)) != 0 {
t.Fatal("cookie escaped its host or path scope")
}
jar.Clear()
if len(jar.Cookies(apiURL)) != 0 {
t.Fatal("Clear retained cookies")
}
}
+20 -10
View File
@@ -5,6 +5,7 @@ import (
"fmt"
"net"
"net/http"
"net/http/cookiejar"
"net/url"
"slices"
"strconv"
@@ -494,27 +495,36 @@ func isPrivateIPAddr(ip net.IP) bool {
}
type simpleCookieJar struct {
cookies map[string][]*http.Cookie
mu sync.RWMutex
mu sync.RWMutex
jar *cookiejar.Jar
}
func newSimpleCookieJar() (*simpleCookieJar, error) {
return &simpleCookieJar{
cookies: make(map[string][]*http.Cookie),
}, nil
jar, err := cookiejar.New(nil)
if err != nil {
return nil, err
}
return &simpleCookieJar{jar: jar}, nil
}
func (j *simpleCookieJar) SetCookies(u *url.URL, cookies []*http.Cookie) {
j.mu.Lock()
defer j.mu.Unlock()
key := u.Host
j.cookies[key] = append(j.cookies[key], cookies...)
j.mu.RLock()
defer j.mu.RUnlock()
j.jar.SetCookies(u, cookies)
}
func (j *simpleCookieJar) Cookies(u *url.URL) []*http.Cookie {
j.mu.RLock()
defer j.mu.RUnlock()
return j.cookies[u.Host]
return j.jar.Cookies(u)
}
func (j *simpleCookieJar) Clear() {
jar, _ := cookiejar.New(nil)
j.mu.Lock()
j.jar = jar
j.mu.Unlock()
}
func (r *extensionRuntime) SetSettings(settings map[string]any) {
+1 -3
View File
@@ -292,9 +292,7 @@ func (r *extensionRuntime) httpMethodShortcut(method string, call goja.FunctionC
func (r *extensionRuntime) httpClearCookies(call goja.FunctionCall) goja.Value {
if jar, ok := r.cookieJar.(*simpleCookieJar); ok {
jar.mu.Lock()
jar.cookies = make(map[string][]*http.Cookie)
jar.mu.Unlock()
jar.Clear()
GoLog("[Extension:%s] Cookies cleared\n", r.extensionID)
return r.vm.ToValue(true)
}