import { ProxyManager } from '../proxy-manager'; import type { HttpResponse, RequestConfig } from '../types'; import { HttpError } from '../types'; import type { RequestAdapter } from './types'; /** * Fetch adapter for HTTP/HTTPS proxies and non-proxy requests */ export class FetchAdapter implements RequestAdapter { canHandle(config: RequestConfig): boolean { // Fetch handles non-proxy requests and HTTP/HTTPS proxies if (typeof config.proxy === 'string') { return config.proxy.startsWith('http'); } return !config.proxy || config.proxy.protocol === 'http' || config.proxy.protocol === 'https'; } async request(config: RequestConfig, signal: AbortSignal): Promise> { const { url, method = 'GET', headers, data, proxy } = config; // Prepare fetch options const fetchOptions: RequestInit = { method, headers, signal, }; // Add body for non-GET requests if (data && method !== 'GET') { fetchOptions.body = typeof data === 'string' ? data : JSON.stringify(data); if (typeof data === 'object') { fetchOptions.headers = { 'Content-Type': 'application/json', ...fetchOptions.headers }; } } // Add proxy if needed (using Bun's built-in proxy support) if (typeof proxy === 'string') { // If proxy is a URL string, use it directly (fetchOptions as any).proxy = proxy; } else if (proxy) { // If proxy is a ProxyInfo object, create a proxy URL (fetchOptions as any).proxy = ProxyManager.createProxyUrl(proxy); } const response = await fetch(url, fetchOptions); // Parse response based on content type let responseData: T; const contentType = response.headers.get('content-type') || ''; if (contentType.includes('application/json')) { responseData = (await response.json()) as T; } else { responseData = (await response.text()) as T; } const httpResponse: HttpResponse = { data: responseData, status: response.status, headers: Object.fromEntries(response.headers.entries()), ok: response.ok, }; // Throw HttpError for non-2xx status codes if (!response.ok) { throw new HttpError( `Request failed with status ${response.status}`, response.status, httpResponse ); } return httpResponse; } }