Fix overwrite of existing cookiejar.

This commit is contained in:
y a t s
2026-06-18 10:02:16 -04:00
parent 1e9bd059f0
commit 72840af90e
5 changed files with 64 additions and 31 deletions
+18 -5
View File
@@ -122,18 +122,31 @@ func (kf *KF) TwoFactorAuth(ctx context.Context, resp *http.Response, code uint3
return kf.Do(req) return kf.Do(req)
} }
func (kf *KF) RefreshSession(ctx context.Context) error { func (kf *KF) IsLoggedIn() bool {
return getCookie(kf.client.Jar, kf.domain, "xf_user") != nil
}
func (kf *KF) RefreshSession(ctx context.Context) (string, error) {
const COOKIE_NAME = "xf_session"
jar := kf.client.Jar
// Clear any existing session token to request a new one. // Clear any existing session token to request a new one.
setCookie(kf.domain, kf.client.Jar, &http.Cookie{ setCookie(jar, kf.domain, &http.Cookie{
Name: "xf_session", Name: COOKIE_NAME,
Value: "", Value: "",
}) })
resp, err := kf.Get(ctx, kf.domain) resp, err := kf.Get(ctx, kf.domain)
if err != nil { if err != nil {
return err return "", err
} }
resp.Body.Close() resp.Body.Close()
return nil session := getCookie(jar, kf.domain, COOKIE_NAME)
if session == nil {
return "", errors.New("Failed to get new xf_session cookie.")
}
return session.Value, nil
} }
+7
View File
@@ -63,6 +63,13 @@ func TestLogin(t *testing.T) {
} }
t.Logf("2FA response: %+v\n", lr) t.Logf("2FA response: %+v\n", lr)
} }
session, err := kf.RefreshSession(ctx)
if err != nil {
t.Error(err)
return
}
t.Logf("xf_session: %s\n", session)
} }
func genTest2FACode() (uint32, error) { func genTest2FACode() (uint32, error) {
+1 -1
View File
@@ -1,6 +1,6 @@
module gitgud.io/yats/libkiwi module gitgud.io/yats/libkiwi
go 1.26.1 go 1.26.4
require ( require (
gitgud.io/yats/cerberus v0.0.0-20260214165307-66e6f74a4be9 gitgud.io/yats/cerberus v0.0.0-20260214165307-66e6f74a4be9
+27 -14
View File
@@ -14,25 +14,18 @@ import (
"golang.org/x/net/html/atom" "golang.org/x/net/html/atom"
) )
// Get XFToken (data-csrf) from page html. func getCookie(jar http.CookieJar, u *url.URL, name string) *http.Cookie {
func XFToken(page io.Reader) (string, error) { cookies := jar.Cookies(u)
z := html.NewTokenizer(page) for _, c := range cookies {
for i := z.Next(); i != html.ErrorToken; i = z.Next() { if c.Name == name {
tk := z.Token() return c
if tk.DataAtom == atom.Html {
for _, a := range tk.Attr {
switch a.Key {
case "data-csrf":
return a.Val, nil
}
}
} }
} }
return "", ErrNoXFToken return nil
} }
func setCookie(u *url.URL, jar http.CookieJar, newCookie *http.Cookie) { func setCookie(jar http.CookieJar, u *url.URL, newCookie *http.Cookie) {
cookies := jar.Cookies(u) cookies := jar.Cookies(u)
for i, c := range cookies { for i, c := range cookies {
@@ -48,6 +41,26 @@ func setCookie(u *url.URL, jar http.CookieJar, newCookie *http.Cookie) {
jar.SetCookies(u, cookies) jar.SetCookies(u, cookies)
} }
// Get XFToken (data-csrf) from page html.
func XFToken(page io.Reader) (string, error) {
z := html.NewTokenizer(page)
for i := z.Next(); i != html.ErrorToken; i = z.Next() {
tk := z.Token()
if tk.DataAtom != atom.Html {
continue
}
for _, a := range tk.Attr {
switch a.Key {
case "data-csrf":
return a.Val, nil
}
}
}
return "", ErrNoXFToken
}
func (kf *KF) Do(req *http.Request) (*http.Response, error) { func (kf *KF) Do(req *http.Request) (*http.Response, error) {
var ( var (
ctx = req.Context() ctx = req.Context()
+8 -8
View File
@@ -21,25 +21,25 @@ type KF struct {
} }
// Supply your own http.Client to route through any proxies. // Supply your own http.Client to route through any proxies.
func NewKF(hc http.Client, host *url.URL) (*KF, error) { func NewKF(hc http.Client, host *url.URL) (KF, error) {
u, err := url.Parse(fmt.Sprintf("https://%s", host.Hostname())) u, err := url.Parse(fmt.Sprintf("https://%s", host.Hostname()))
if err != nil { if err != nil {
return nil, err return KF{}, err
} }
if hc.Jar == nil {
jar, err := cookiejar.New(nil) jar, err := cookiejar.New(nil)
if err != nil { if err != nil {
return nil, err return KF{}, err
} }
hc.Jar = jar hc.Jar = jar
kf := &KF{
client: hc,
domain: u,
} }
return kf, nil return KF{
client: hc,
domain: u,
}, nil
} }
type User struct { type User struct {