JSPM

  • Created
  • Published
  • Downloads 85
  • Score
    100M100P100Q93752F
  • License MIT

A high-performance, universal HTTP client for Node.js with caching, retries, queueing, rate limiting, cookies and logging.

Package Exports

  • hyperttp/http-client
  • hyperttp/index
  • hyperttp/url-extractor

Readme

Hyperttp ⚡

English | Русский

npm version npm downloads license typescript


🌐 Language



Hyperttp is a batteries-included, high-performance HTTP client for Node.js, Bun, Deno, and Browser environments. It is a feature-rich, production-ready extension over the optimized @hyperttp/core engine, shipping with caching, rate limiting, request queuing, inflight deduplication, performance metrics, and a fluent chainable API — all pre-wired and ready to use.


🔥 Key Features

  • 🎯 Smart Response Parsing: Automatically parses responses based on responseType (json, text, xml, html, buffer, blob, stream).
  • 🔀 Concurrency Management: Built-in queue plugin (withQueue) to strictly enforce concurrent request limits.
  • 💾 Smart LRU Caching: Dedicated caching layer (withCache) with TTL support to prevent redundant network drift.
  • 🚦 Rate Limiting: Built-in Token Bucket algorithm to protect against external API blocks and rate limits.
  • 🛡️ Inflight Deduplication: Prevents duplicate simultaneous requests to the same endpoint if the first is pending.
  • 📈 Real-Time Metrics: Out-of-the-box telemetry tracking latencies, RPS, cache hits, and overall client health.
  • 🔌 Modular Architecture: Clean pipeline approach allowing custom plugins, serialization layers, and interceptors.
  • 💎 Fluent Request Builder API: Clean, chainable API syntax to compose and configure requests with ease.
  • 🗜️ Transparent Decompression: Automatic handling of gzip, deflate, and br (Brotli) out of the box.

📦 Ecosystem Packages

Package Description Repository
hyperttp (you are here) High-level client with all plugins pre-wired GitHub
@hyperttp/core Low-level core with transport pipeline GitHub
@hyperttp/types Shared TypeScript type definitions GitHub
@hyperttp/transport-bun Native Bun transport GitHub
@hyperttp/transport-undici Undici transport for Node.js GitHub
@hyperttp/parser Response body parser (JSON/XML/HTML) GitHub
@hyperttp/serializer Request body serializer GitHub
@hyperttp/cache HTTP response caching GitHub
@hyperttp/queue Request queueing GitHub
@hyperttp/ratelimit Rate limiting GitHub
@hyperttp/inflight In-flight request deduplication GitHub
@hyperttp/interceptors Request/response interceptors GitHub
@hyperttp/metrics Performance metrics GitHub

Which package should I use?

  • Just need HTTP requests with caching, retries, and parsing? → Use hyperttp (this package)
  • Need full control over the pipeline? → Use @hyperttp/core
  • Building a custom transport or plugin? → Use @hyperttp/types

🚀 Installation

npm install hyperttp

# Optional: install a specific transport
npm install @hyperttp/transport-bun    # for Bun
npm install @hyperttp/transport-undici # for Node.js

📦 Quick Start

Simply import HyperClient and start dispatching requests. Core features like caching, queue management, and rate limiting are instantly preconfigured and active out of the box.

import { HyperClient } from "hyperttp";

const client = new HyperClient();

// Simple GET request (instantly resolves to the pre-parsed type-safe body)
const data = await client.get<MyDataType>("https://api.example.com/data");

// POST request specifying expected response type alongside body payload
const newItem = await client.post<Item>("https://api.example.com/items", "json", {
  name: "New Item Structure",
});

// Explicit response type
const html = await client.get<string>("https://example.com", "text");
const xml = await client.get<XmlDoc>("https://api.example.com/feed.xml", "xml");

// Streaming responses (e.g., LLM completions)
const chatStream = await client.stream("https://api.openai.com/v1/chat/completions");
const reader = chatStream.body.getReader();

💎 Fluent Builder API

Invoke the .request(url) chain to programmatically craft highly specific request structures on the fly:

const user = await client
  .request("https://api.example.com/users")
  .post() // Specify HTTP Method (Defaults to GET)
  .query({ include: "profile" }) // Safely append and encode Query Parameters
  .headers({ "X-Request-ID": crypto.randomUUID() })
  .jsonBody({ name: "John", email: "john@example.com" }) // Automatically serializes and sets Content-Type header
  .json<User>() // Asserts expected response format (.text(), .buffer(), .stream())
  .timeout(5000) // Instantiates a contextual, request-scoped AbortSignal timeout
  .send();

⚙️ Advanced Configuration

Fine-tune every infrastructure layer by supplying a configuration object directly to the HyperClient constructor:

import { HyperClient } from "hyperttp";

const client = new HyperClient({
  // 🌐 Core Network Level Settings (NetworkOptions)
  network: {
    timeout: 10000, // Request timeout in milliseconds
    maxConcurrent: 50, // Maximum simultaneous active sockets (0 = unlimited)
    pipelining: 1, // Pipelined requests per connection limit
    keepAliveTimeout: 30000, // Keep-alive socket preservation time in ms
    rejectUnauthorized: true, // Reject untrusted or self-signed SSL certificates
    followRedirects: true, // Automatically follow HTTP redirects
    maxRedirects: 5, // Maximum follow threshold for redirects
    maxResponseBytes: 10 * 1024 * 1024, // Prevents OOM by capping response body size (10 MB)
    userAgent: "HyperClient/2.0", // Global fallback User-Agent header
    headers: {
      // Default baseline headers appended to every request
      "X-App-Client": "Backend",
    },
    validateStatus: (status) => status >= 200 && status < 300, // Status success validation rules
  },

  // 🔄 Automated Retry Logic (RetryOptions)
  retry: {
    maxRetries: 3, // Number of recovery attempts before failing
    baseDelay: 1000, // Initial delay baseline between retries (ms)
    maxDelay: 10000, // Maximum cap for retry delay intervals (ms)
    retryStatusCodes: [408, 429, 502, 503, 504], // Target status codes that trigger a retry
    jitter: true, // Randomized delay variations to avoid thundering herd crashes
  },

  // 📈 Telemetry and Engine Logging
  trackMetrics: true, // Enables global system performance collection
  verbose: false, // Toggles internal micro-logs output
  logger: (level, message, meta) => {
    // Custom logging implementation sink
    console.log(`[${level}] ${message}`, meta ?? "");
  },

  // 💾 Extended Plugin Configurations (Injected via HyperttpPluginsExtension)
  cache: {
    enabled: true,
    ttl: 300000, // 5 minutes cache lifespan
    maxSize: 500, // Max item limit for local LRU storage
  },
  rateLimit: {
    enabled: true,
    maxRequests: 100,
    windowMs: 60000,
  },
  inflight: {
    enabled: true,
  },
});

🔌 Pre-Wired Plugins

When using HyperClient, the following plugins are automatically registered:

Plugin Purpose
withParser Parses response bodies based on responseType
withQueue Queues requests when concurrency limit is reached
withRateLimit Enforces rate limits
withInflight Deduplicates in-flight requests
withCache Caches responses based on HTTP headers
withInterceptors Request/response interceptors
withMetrics Collects performance metrics

Custom Plugins

Extend the client with your own hooks:

client.use({
  name: "performance-logger",
  priority: 100, // Sorted execution priority (higher runs first)
  mode: "background", // Forces onResponse to run as a non-blocking side-effect

  setup: (ctx) => {
    ctx.config.logger?.info?.("Plugin active");
  },

  onRequest: async (req, ctx) => {
    req.meta.startTime = performance.now();
  },

  onResponse: async (res, req, ctx) => {
    const duration = performance.now() - (req.meta.startTime as number);
    console.log(`[${req.method}] ${req.url} -> ${res.status} (${duration.toFixed(2)}ms)`);
  },

  onError: async (error, req, ctx) => {
    console.error(`Request failed to ${req.url}: ${error.message}`);
    // Return a response object here to bypass/recover from the failure
  },
});

Plugin Phases

Phase Hook Description
REQUEST onRequest Intercepts before execution. Supports short-circuiting.
DATA onResponseData Transforms raw transport responses before mapping.
FORMAT onResponse Modifies client-facing responses.
ERROR onError Catches and recovers from errors.

🏗️ Architecture Pipeline

HyperClient structures outbound and inbound requests across a sequential pipeline composed of granular plugins:

┌─────────────────────────────────────────────────────────────────┐
│                        HyperClient                              │
│   (Auto-wires: Parser → Queue → RateLimit →                     │
│    Inflight → Cache → Interceptors → Metrics)                   │
└──────────────────────────┬──────────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────────────┐
│                         HyperCore                               │
│                                                                 │
│  1. Request Pipeline (onRequest) ─── short-circuit capable      │
│                     │                                           │
│  2. Transport Execution (HyperTransport)                        │
│     ├─ BunTransport (native Bun fetch)                          │
│     ├─ UndiciTransport (Node.js)                                │
│     └─ NodeTransport (global fetch)                             │
│                     │                                           │
│  3. Response Data Pipeline (onResponseData)                     │
│                     │                                           │
│  4. Internal Processing (decompression, mapping)                │
│                     │                                           │
│  5. Response Pipeline (onResponse)                              │
│     ├─ Mutators (sync/async modification)                       │
│     └─ Side Effects (background, non-blocking)                  │
│                     │                                           │
│  6. Error Pipeline (onError) ─── recovery capable               │
└─────────────────────────────────────────────────────────────────┘

🛠️ Advanced Features

Statistics, Cache, and Metrics Engine

// Inspect pipeline internals (active connections, active queue payloads)
const stats = client.getStats();
console.log(stats);

// Retrieve aggregated historical latency and performance metrics
const allMetrics = client.getAllMetrics();
console.log(allMetrics);

// Flush the entire local response cache programmatically
await client.clearCache();

// Identify the execution context's current driving transport layout
const transportName = await client.getTransportName();
console.log(`Current Active Transport Driver: ${transportName}`);

// Gracefully teardown the client instance, draining keep-alive pools and sockets
await client.destroy();

Stream Handlers

// Returns an HttpResponse interface carrying a custom ReadableStream with clone() support
const streamResponse = await client.stream("https://stream.example.com/audio.mp3");
const reader = streamResponse.body.getReader();

Extending Configuration

Create derived clients with merged configuration:

const authenticatedClient = client.extend({
  network: { headers: { Authorization: "Bearer token_abc" } },
});

🔄 Migration from axios

If you're migrating from axios, Hyperttp provides a familiar API:

// axios
import axios from "axios";
const { data } = await axios.get("/users/123");

// hyperttp (drop-in replacement)
import { HyperClient } from "hyperttp";
const client = new HyperClient();
const data = await client.get("/users/123");

📊 Benchmarks

For detailed benchmarks across Bun and Node.js runtimes with various transports, see the @hyperttp/core benchmarks.

Key takeaways:

  • Bun + BunTransport: ~15.22K RPS with all plugins enabled
  • Node.js + UndiciTransport: ~10.82K RPS with all plugins enabled
  • Plugin Overhead: Only ~9-14% compared to the bare @hyperttp/core
  • Zero Error Rate: 0% errors across all benchmark scenarios

📄 License

MIT


dirold2