74 lines
2.3 KiB
TypeScript
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;
|
|
}
|
|
}
|