@entropy-tamer/reynard-http-client
v0.17.1
Published
HTTP client system for Reynard framework with middleware support, retry logic, and comprehensive error handling
Maintainers
Readme
Reynard HTTP Client
A robust, feature-rich HTTP client for the Reynard ecosystem with middleware support, retry logic, and circuit breaker patterns.
Features
- Middleware System: Pluggable middleware for authentication, logging, and custom logic
- Retry Logic: Configurable retry strategies with exponential backoff
- Circuit Breaker: Automatic failure detection and recovery
- TypeScript Support: Full type safety with comprehensive interfaces
- Error Handling: Structured error responses with detailed information
- Request/Response Interceptors: Hook into request and response lifecycle
- Timeout Management: Configurable timeouts for different scenarios
Installation
pnpm add reynard-http-clientBasic Usage
import { HTTPClient, createAuthMiddleware } from "reynard-http-client";
// Create a client instance
const client = new HTTPClient({
baseUrl: "https://api.example.com",
timeout: 10000,
});
// Add authentication middleware
const authMiddleware = createAuthMiddleware({
type: "bearer",
getToken: () => localStorage.getItem("token"),
});
client.use(authMiddleware);
// Make requests
const response = await client.get("/users");
console.log(response.data);Configuration
HTTPClientOptions
interface HTTPClientOptions {
baseUrl?: string;
timeout?: number;
retries?: number;
retryDelay?: number;
circuitBreaker?: CircuitBreakerConfig;
headers?: Record<string, string>;
}Circuit Breaker Configuration
interface CircuitBreakerConfig {
failureThreshold: number; // Number of failures before opening
recoveryTimeout: number; // Time to wait before attempting recovery
monitoringPeriod: number; // Time window for failure counting
}Middleware
Built-in Middleware
Authentication Middleware
import { createAuthMiddleware } from "reynard-http-client";
const authMiddleware = createAuthMiddleware({
type: "bearer", // or "basic"
getToken: () => localStorage.getItem("token"),
getCredentials: () => ({ username: "user", password: "pass" }),
});Logging Middleware
import { createLoggingMiddleware } from "reynard-http-client";
const loggingMiddleware = createLoggingMiddleware({
logRequests: true,
logResponses: true,
logErrors: true,
});Custom Middleware
import { HTTPMiddleware } from "reynard-http-client";
const customMiddleware: HTTPMiddleware = {
name: "custom",
async processRequest(request, next) {
// Modify request
request.headers["X-Custom-Header"] = "value";
// Continue to next middleware
const response = await next(request);
// Modify response
return response;
},
};
client.use(customMiddleware);Error Handling
The HTTP client provides structured error handling:
try {
const response = await client.get("/users");
console.log(response.data);
} catch (error) {
if (error instanceof HTTPError) {
console.log("Status:", error.status);
console.log("Message:", error.message);
console.log("Data:", error.data);
}
}Response Format
All responses follow a consistent format:
interface HTTPResponse<T = any> {
data: T;
status: number;
statusText: string;
headers: Record<string, string>;
config: HTTPRequestOptions;
}Advanced Usage
Request Interceptors
client.addRequestInterceptor(request => {
// Add timestamp to all requests
request.headers["X-Request-Time"] = Date.now().toString();
return request;
});Response Interceptors
client.addResponseInterceptor(response => {
// Log response time
const requestTime = response.config.headers["X-Request-Time"];
if (requestTime) {
const duration = Date.now() - parseInt(requestTime);
console.log(`Request took ${duration}ms`);
}
return response;
});Retry Configuration
const client = new HTTPClient({
retries: 3,
retryDelay: 1000,
retryCondition: error => {
// Only retry on network errors or 5xx status codes
return error.status >= 500 || !error.status;
},
});Integration with Reynard Auth
The HTTP client integrates seamlessly with Reynard Auth:
import { HTTPClient, createAuthMiddleware } from "reynard-http-client";
import { useAuth } from "reynard-auth";
const { tokenManager } = useAuth();
const client = new HTTPClient({
baseUrl: "https://api.example.com",
});
client.use(
createAuthMiddleware({
type: "bearer",
getToken: () => tokenManager.getAccessToken(),
})
);Testing
The HTTP client includes comprehensive test utilities:
import { createMockHTTPClient } from "reynard-http-client/testing";
const mockClient = createMockHTTPClient();
mockClient.mockGet("/users", { data: [{ id: 1, name: "John" }] });
// Use in tests
const response = await mockClient.get("/users");
expect(response.data).toEqual([{ id: 1, name: "John" }]);API Reference
Classes
HTTPClient- Main HTTP client classHTTPError- Error class for HTTP-related errorsCircuitBreaker- Circuit breaker implementation
Interfaces
HTTPRequestOptions- Request configurationHTTPResponse- Response formatHTTPMiddleware- Middleware interfaceCircuitBreakerConfig- Circuit breaker configuration
Functions
createAuthMiddleware()- Create authentication middlewarecreateLoggingMiddleware()- Create logging middlewarecreateRetryMiddleware()- Create retry middleware
License
MIT License - see LICENSE file for details.
