/** * HTTP interceptors for auth, rate limiting, retry, etc. * * Why interceptor pattern: Separates cross-cutting concerns (auth, retry) * from business logic (API calls). Each interceptor is independently testable. */ import type { InterceptorConfig } from '../types/profile.js'; import { MetricsCollector } from '../core/metrics.js'; import type { MetricsContextLabels } from '../core/metrics.js'; import { SSRFValidator } from '../security/ssrf-validator.js'; import { Logger } from '../core/logger.js'; export interface RequestContext { method: string; url: string; headers: Record; body?: unknown; operationId?: string; } export interface ResponseContext { status: number; headers: Record; body: unknown; } export interface AuthCredentials { headers: Record; queryParams?: { key: string; value: string; }; } export type InterceptorFn = (ctx: RequestContext, next: () => Promise) => Promise; export declare class InterceptorChain { config: InterceptorConfig; private authToken?; private interceptors; private metrics; private metricsContext; private readonly cacheSessionPartitionId; constructor(config: InterceptorConfig, authToken?: string | undefined); private buildChain; private createCacheInterceptor; setMetricsCollector(metrics: MetricsCollector | null, context?: MetricsContextLabels): void; private recordCacheEvent; private getSensitiveCacheHeaders; /** * Auth interceptor: adds auth header/query from env or session token * * Why env-based: Keeps secrets out of config files. Config defines WHERE * to get the token, runtime provides the value. * * Supports: * - bearer: Standard HTTP Authorization: Bearer * - query: API key in URL (?api_key=) * - custom-header: Custom header (e.g., X-API-Key: ) * * Note: For multi-auth, uses the primary (first/lowest priority) non-OAuth config. * OAuth is handled separately in HTTP transport, not in InterceptorChain. */ private createAuthInterceptor; /** * Rate limiter: token bucket algorithm with per-endpoint overrides * * Why token bucket: Allows bursts while enforcing average rate. Better UX * than strict per-request delays. * * Supports per-endpoint overrides via operationId matching. */ private createRateLimitInterceptor; /** * Retry interceptor: exponential backoff * * Why exponential: Reduces server load during outages. Linear backoff * can cause thundering herd on recovery. */ private createRetryInterceptor; execute(ctx: RequestContext, finalHandler: () => Promise): Promise; /** * Extract auth credentials (headers + query params) without making a request * * Why separate: ProxyDownloadExecutor needs auth for direct fetch calls, * but can't use InterceptorChain (fetch doesn't go through chain). * This extracts the same credentials the chain would apply. * * Returns: * - Bearer auth: { headers: { Authorization: 'Bearer token' }, queryParams: undefined } * - Custom-header auth: { headers: { 'X-API-Key': 'token' }, queryParams: undefined } * - Query auth: { headers: {}, queryParams: { key: 'api_key', value: 'token' } } * - No auth: { headers: {}, queryParams: undefined } */ getAuthCredentials(): AuthCredentials; } /** * HTTP client with interceptor support */ export declare class HttpClient { private baseUrl; private interceptors; private metrics; private metricsContext; private logger; private ssrfValidator; constructor(baseUrl: string, interceptors: InterceptorChain, metrics?: MetricsCollector | null, logger?: Logger, ssrfValidator?: SSRFValidator, metricsContext?: MetricsContextLabels); setMetricsCollector(metrics: MetricsCollector | null): void; /** * Get base URL (for testing) */ getBaseUrl(): string; /** * Get interceptors config (for testing) */ getInterceptorsConfig(): InterceptorConfig; /** * Get auth credentials (headers and query params) for direct HTTP calls * Used by ProxyDownloadExecutor for authenticated file downloads */ getAuthCredentials(): AuthCredentials; /** * Serialize parameters including arrays * * Why different formats: APIs use different conventions for array parameters. * Rails/GitLab: scope[]=value, PHP: scope[0]=value, Express: scope=value (repeat) */ private serializeParams; request(method: string, path: string, options?: { params?: Record; body?: unknown; headers?: Record; operationId?: string; timeout_ms?: number; }): Promise; private getSensitiveRedirectHeaderNames; private stripSensitiveHeaders; private isSameOrigin; private getErrorType; } //# sourceMappingURL=interceptors.d.ts.map