stock-bot/libs/http/src/adapters/fetch-adapter.ts
2025-06-13 13:38:02 -04:00

74 lines
2.3 KiB
TypeScript

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<T = any>(config: RequestConfig, signal: AbortSignal): Promise<HttpResponse<T>> {
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<T> = {
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;
}
}