Overview
Make HTTP requests with automatic retries using native fetch.
Features
- Native fetch
- Automatic retries
- Timeout handling
Installation
npx hanma add elysia-http-client --framework elysia
Code
/**
* Bun-native HTTP client with retry logic
* Uses native fetch API available in Bun
*/
interface HttpClientOptions extends RequestInit {
retries?: number;
backoff?: number;
}
interface HttpResponse<T> {
data: T;
status: number;
headers: Headers;
}
export class HttpClient {
private baseURL: string;
private defaultOptions: HttpClientOptions;
constructor(baseURL: string = "", defaultOptions: HttpClientOptions = {}) {
this.baseURL = baseURL;
this.defaultOptions = {
retries: 3,
backoff: 1000,
...defaultOptions,
};
}
private async request<T>(
url: string,
options: HttpClientOptions = {}
): Promise<HttpResponse<T>> {
const { retries, backoff, ...fetchOptions } = {
...this.defaultOptions,
...options,
};
const fullUrl = url.startsWith("http") ? url : `${this.baseURL}${url}`;
let lastError: Error | null = null;
for (let attempt = 1; attempt <= (retries || 3); attempt++) {
try {
const response = await fetch(fullUrl, {
...fetchOptions,
headers: {
"Content-Type": "application/json",
...fetchOptions.headers,
},
});
if (!response.ok) {
if (response.status >= 500 && attempt < (retries || 3)) {
throw new Error(`Server error: ${response.status}`);
}
const errorData = await response.json().catch(() => ({}));
throw new Error(
errorData.message || `HTTP error! status: ${response.status}`
);
}
const data = (await response.json()) as T;
return {
data,
status: response.status,
headers: response.headers,
};
} catch (error: any) {
lastError = error;
if (attempt < (retries || 3)) {
const delay = (backoff || 1000) * Math.pow(2, attempt - 1);
console.warn(
`[HTTP] Attempt ${attempt} failed, retrying in ${delay}ms...`
);
await Bun.sleep(delay);
}
}
}
throw lastError || new Error("Request failed");
}
async get<T>(url: string, options?: HttpClientOptions): Promise<HttpResponse<T>> {
return this.request<T>(url, { ...options, method: "GET" });
}
async post<T>(
url: string,
body?: any,
options?: HttpClientOptions
): Promise<HttpResponse<T>> {
return this.request<T>(url, {
...options,
method: "POST",
body: JSON.stringify(body),
});
}
async put<T>(
url: string,
body?: any,
options?: HttpClientOptions
): Promise<HttpResponse<T>> {
return this.request<T>(url, {
...options,
method: "PUT",
body: JSON.stringify(body),
});
}
async patch<T>(
url: string,
body?: any,
options?: HttpClientOptions
): Promise<HttpResponse<T>> {
return this.request<T>(url, {
...options,
method: "PATCH",
body: JSON.stringify(body),
});
}
async delete<T>(url: string, options?: HttpClientOptions): Promise<HttpResponse<T>> {
return this.request<T>(url, { ...options, method: "DELETE" });
}
}
// Simple function-based API
export async function httpClient<T>(
url: string,
options: HttpClientOptions = {}
): Promise<T> {
const client = new HttpClient();
const response = await client.request<T>(url, options);
return response.data;
}
/* USAGE:
// Class-based
const client = new HttpClient("https://api.example.com", {
retries: 3,
backoff: 1000,
});
const { data, status } = await client.get<User>("/users/1");
// Function-based
const user = await httpClient<User>("https://api.example.com/users/1", {
retries: 3,
backoff: 1000,
});
*/
Usage
import { httpClient } from './libs/http-client';
Dependencies
No external dependencies required.
Frequently Asked Questions
How do I install HTTP Client?
Run the following command:
npx hanma add elysia-http-client --framework elysiaHow do I use this snippet?
Copy the code and paste it into your project. The snippet will be saved to
src/libs/http-client.ts.Can I customize this snippet?
Yes! All snippets are copy-paste code that you own. Feel free to modify them to fit your needs.
Does this work with other frameworks?
This snippet is designed for the specific framework. Check the other framework pages for equivalent implementations.