package quota import ( "context" "fmt" "io" "net/http" "strings" ) // FetchUsage GETs the provider usage endpoint with bearer auth. The key is // resolved per call from the [quota] key_ref and never logged; error paths // carry only status codes and redacted/truncated bodies (same discipline as // the keyproxy hop). func FetchUsage(ctx context.Context, client *http.Client, usageURL, key string) ([]byte, error) { req, err := http.NewRequestWithContext(ctx, http.MethodGet, usageURL, nil) if err != nil { return nil, fmt.Errorf("usage request: %w", err) } req.Header.Set("Authorization", "Bearer "+key) req.Header.Set("Accept", "application/json") resp, err := client.Do(req) if err != nil { return nil, fmt.Errorf("usage poll: %w", redactQuery(err)) } defer resp.Body.Close() body, _ := io.ReadAll(io.LimitReader(resp.Body, 1<<20)) if resp.StatusCode < 200 || resp.StatusCode >= 300 { return nil, fmt.Errorf("usage poll: HTTP %d: %s", resp.StatusCode, truncateBody(string(body))) } return body, nil } func redactQuery(err error) error { msg := err.Error() if i := strings.Index(msg, "?"); i >= 0 { msg = msg[:i] + "?..." } return fmt.Errorf("%s", msg) } func truncateBody(s string) string { s = strings.TrimSpace(s) if len(s) > 200 { s = s[:200] + "..." } return s }