mirror of
https://github.com/krau/SaveAny-Bot.git
synced 2026-09-08 17:16:37 +08:00
fix: skip login refresh for token-only alist storage
401 responses surface the auth error instead of sending a credential-less login; the refresh window never exceeds TokenExp.
This commit is contained in:
@@ -125,6 +125,11 @@ func (a *Alist) Save(ctx context.Context, reader io.Reader, storagePath string)
|
|||||||
if resp.StatusCode == http.StatusUnauthorized || resp.StatusCode == http.StatusForbidden {
|
if resp.StatusCode == http.StatusUnauthorized || resp.StatusCode == http.StatusForbidden {
|
||||||
status := resp.Status
|
status := resp.Status
|
||||||
resp.Body.Close()
|
resp.Body.Close()
|
||||||
|
// Token-only configurations cannot refresh credentials: surface the
|
||||||
|
// auth error instead of sending a login request with no credentials.
|
||||||
|
if a.loginInfo == nil {
|
||||||
|
return fmt.Errorf("failed to save file to Alist: %s", status)
|
||||||
|
}
|
||||||
if err := a.getToken(ctx); err != nil {
|
if err := a.getToken(ctx); err != nil {
|
||||||
return fmt.Errorf("failed to refresh alist token: %w", err)
|
return fmt.Errorf("failed to refresh alist token: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-3
@@ -13,14 +13,23 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// minTokenRefreshInterval deduplicates login storms: a successful refresh is
|
// minTokenRefreshInterval deduplicates login storms: a successful refresh is
|
||||||
// reused for this window instead of hitting the login endpoint again.
|
// reused for this window instead of hitting the login endpoint again. It is
|
||||||
|
// capped by the configured token expiry so refreshes never go stale.
|
||||||
const minTokenRefreshInterval = 30 * time.Second
|
const minTokenRefreshInterval = 30 * time.Second
|
||||||
|
|
||||||
|
func (a *Alist) tokenRefreshWindow() time.Duration {
|
||||||
|
window := minTokenRefreshInterval
|
||||||
|
if exp := time.Duration(a.config.TokenExp) * time.Second; exp > 0 && exp < window {
|
||||||
|
window = exp
|
||||||
|
}
|
||||||
|
return window
|
||||||
|
}
|
||||||
|
|
||||||
// getToken refreshes the JWT, deduplicating concurrent calls so parallel
|
// getToken refreshes the JWT, deduplicating concurrent calls so parallel
|
||||||
// uploads and the background refresher share one login request.
|
// uploads and the background refresher share one login request.
|
||||||
func (a *Alist) getToken(ctx context.Context) error {
|
func (a *Alist) getToken(ctx context.Context) error {
|
||||||
a.tokenMu.RLock()
|
a.tokenMu.RLock()
|
||||||
fresh := !a.lastLoginAt.IsZero() && time.Since(a.lastLoginAt) < minTokenRefreshInterval
|
fresh := !a.lastLoginAt.IsZero() && time.Since(a.lastLoginAt) < a.tokenRefreshWindow()
|
||||||
a.tokenMu.RUnlock()
|
a.tokenMu.RUnlock()
|
||||||
if fresh {
|
if fresh {
|
||||||
return nil
|
return nil
|
||||||
@@ -28,7 +37,7 @@ func (a *Alist) getToken(ctx context.Context) error {
|
|||||||
_, err, _ := a.tokenFlight.Do("token", func() (any, error) {
|
_, err, _ := a.tokenFlight.Do("token", func() (any, error) {
|
||||||
// Another waiter may have refreshed while this call was queued.
|
// Another waiter may have refreshed while this call was queued.
|
||||||
a.tokenMu.RLock()
|
a.tokenMu.RLock()
|
||||||
fresh := !a.lastLoginAt.IsZero() && time.Since(a.lastLoginAt) < minTokenRefreshInterval
|
fresh := !a.lastLoginAt.IsZero() && time.Since(a.lastLoginAt) < a.tokenRefreshWindow()
|
||||||
a.tokenMu.RUnlock()
|
a.tokenMu.RUnlock()
|
||||||
if fresh {
|
if fresh {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@@ -39,6 +48,9 @@ func (a *Alist) getToken(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *Alist) fetchToken(ctx context.Context) error {
|
func (a *Alist) fetchToken(ctx context.Context) error {
|
||||||
|
if a.loginInfo == nil {
|
||||||
|
return fmt.Errorf("token-only alist storage cannot refresh credentials")
|
||||||
|
}
|
||||||
loginBody, err := json.Marshal(a.loginInfo)
|
loginBody, err := json.Marshal(a.loginInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to marshal login request: %w", err)
|
return fmt.Errorf("failed to marshal login request: %w", err)
|
||||||
|
|||||||
Reference in New Issue
Block a user