mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-09-11 14:47:58 +08:00
70 lines
2.6 KiB
Go
70 lines
2.6 KiB
Go
package homeplugins
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"sync/atomic"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/router-for-me/CLIProxyAPI/v7/internal/config"
|
|
internalpluginstore "github.com/router-for-me/CLIProxyAPI/v7/internal/pluginstore"
|
|
sdkpluginstore "github.com/router-for-me/CLIProxyAPI/v7/sdk/pluginstore"
|
|
)
|
|
|
|
type networkScopeDoer func(*http.Request) (*http.Response, error)
|
|
|
|
func (f networkScopeDoer) Do(req *http.Request) (*http.Response, error) { return f(req) }
|
|
|
|
func TestPluginStoreClientsShareProxyCooldown(t *testing.T) {
|
|
var proxyCalls atomic.Int32
|
|
proxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
|
proxyCalls.Add(1)
|
|
w.WriteHeader(http.StatusBadGateway)
|
|
}))
|
|
defer proxy.Close()
|
|
|
|
const tokenEnv = "HOME_PLUGIN_NETWORK_SCOPE_TEST_TOKEN"
|
|
t.Setenv(tokenEnv, t.Name())
|
|
auth := []sdkpluginstore.ResolvedAuthConfig{{
|
|
Match: "https://api.github.com/", Type: sdkpluginstore.AuthTypeGitHubToken,
|
|
Token: sdkpluginstore.Secret(t.Name()),
|
|
}}
|
|
expiresAt := time.Now().Add(time.Hour)
|
|
plugin := sdkpluginstore.Plugin{Repository: "https://github.com/test/home-network-scope"}
|
|
// Seed the same process-wide cooldown used by management and Home clients.
|
|
seed := sdkpluginstore.NewClientWithResolvedAuthExpiry(networkScopeDoer(func(*http.Request) (*http.Response, error) {
|
|
return &http.Response{StatusCode: http.StatusTooManyRequests, Header: http.Header{"Retry-After": {"3600"}}, Body: io.NopCloser(strings.NewReader("limited"))}, nil
|
|
}), "", auth, expiresAt).WithNetworkScope(proxy.URL)
|
|
_, errRelease := seed.FetchLatestRelease(context.Background(), plugin)
|
|
var rateLimit *internalpluginstore.RateLimitError
|
|
if !errors.As(errRelease, &rateLimit) {
|
|
t.Fatalf("seed cooldown: %v", errRelease)
|
|
}
|
|
|
|
cfg := &config.Config{}
|
|
cfg.ProxyURL = " " + proxy.URL + " "
|
|
cfg.Plugins.StoreAuth = []sdkpluginstore.AuthConfig{{
|
|
Match: "https://api.github.com/", Type: sdkpluginstore.AuthTypeGitHubToken, TokenEnv: tokenEnv,
|
|
}}
|
|
for name, client := range map[string]sdkpluginstore.Client{
|
|
"configured auth": newPluginStoreClient(cfg),
|
|
"resolved auth": newResolvedPluginStoreClient(cfg, auth, expiresAt),
|
|
} {
|
|
t.Run(name, func(t *testing.T) {
|
|
_, errRelease := client.FetchLatestRelease(context.Background(), plugin)
|
|
var rateLimit *internalpluginstore.RateLimitError
|
|
if !errors.As(errRelease, &rateLimit) {
|
|
t.Fatalf("Home client did not inherit the proxy cooldown: %v", errRelease)
|
|
}
|
|
})
|
|
}
|
|
if proxyCalls.Load() != 0 {
|
|
t.Fatalf("cooldown made %d proxy requests, want 0", proxyCalls.Load())
|
|
}
|
|
}
|