{"id":15978,"library":"cacheable-request","title":"Cacheable HTTP/HTTPS Requests","description":"cacheable-request provides RFC 7234 compliant HTTP caching for Node.js's native HTTP and HTTPS modules. It is a low-level wrapper, not a high-level request library, designed to add caching capabilities directly to `http.request` or `https.request`. The current stable version is 13.0.18, with frequent patch and minor updates, and occasional breaking changes between major versions as seen in recent changelogs. Key differentiators include its strict adherence to RFC 7234 for cache validation and storage logic, out-of-the-box in-memory caching, and a highly pluggable architecture for various storage adapters, prominently featuring Keyv for flexible backend integration. It handles fresh and stale cache entries, revalidation with `If-None-Match`/`If-Modified-Since`, and 304 responses, updating the `Age` header accordingly.","status":"active","version":"13.0.18","language":"javascript","source_language":"en","source_url":"https://github.com/jaredwray/cacheable","tags":["javascript","HTTP","HTTPS","cache","caching","layer","cacheable","RFC 7234","RFC","typescript"],"install":[{"cmd":"npm install cacheable-request","lang":"bash","label":"npm"},{"cmd":"yarn add cacheable-request","lang":"bash","label":"yarn"},{"cmd":"pnpm add cacheable-request","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Used as the primary storage mechanism and adapter for various cache backends. Required for custom storage configurations.","package":"keyv","optional":false}],"imports":[{"note":"Package is pure ESM since v9. CommonJS `require` is not supported. Use dynamic `import()` for CJS contexts.","wrong":"const CacheableRequest = require('cacheable-request');","symbol":"CacheableRequest","correct":"import CacheableRequest from 'cacheable-request';"},{"note":"The `Request` type can be imported for TypeScript usage when defining custom request wrappers or extending functionality.","symbol":"Request","correct":"import CacheableRequest, { Request } from 'cacheable-request';"},{"note":"Import `Options` type for configuring `CacheableRequest` instances in TypeScript.","symbol":"Options","correct":"import { Options } from 'cacheable-request';"}],"quickstart":{"code":"import http from 'http';\nimport CacheableRequest from 'cacheable-request';\n\n// Create a basic HTTP server to simulate responses\nconst server = http.createServer((req, res) => {\n  if (req.url === '/cached') {\n    res.setHeader('Cache-Control', 'max-age=10');\n    res.setHeader('ETag', '\"abc\"');\n    res.end('Hello from cacheable server!');\n  } else {\n    res.end('Not cached content');\n  }\n});\n\nserver.listen(3000, async () => {\n  console.log('Server listening on http://localhost:3000');\n\n  // Instantiate CacheableRequest with Node's native http.request\n  const cacheable = new CacheableRequest(http.request).request();\n\n  const makeRequest = (url) => {\n    return new Promise((resolve, reject) => {\n      const req = cacheable(url, (response) => {\n        let data = '';\n        response.on('data', (chunk) => (data += chunk));\n        response.on('end', () => {\n          console.log(`\nURL: ${url}`);\n          console.log(`Status: ${response.statusCode}`);\n          console.log(`From Cache: ${response.fromCache ? 'Yes' : 'No'}`);\n          console.log(`Data: ${data}`);\n          resolve({ statusCode: response.statusCode, fromCache: response.fromCache, data });\n        });\n      });\n      req.on('request', (req) => req.end());\n      req.on('error', reject);\n    });\n  };\n\n  console.log('--- First request ---');\n  await makeRequest('http://localhost:3000/cached');\n\n  console.log('\\n--- Second request (should be from cache) ---');\n  await makeRequest('http://localhost:3000/cached');\n\n  console.log('\\n--- Request to non-cached path ---');\n  await makeRequest('http://localhost:3000/non-cached');\n\n  server.close(() => console.log('\\nServer closed.'));\n});","lang":"typescript","description":"This quickstart demonstrates how to wrap Node.js native `http.request` with `cacheable-request` to add RFC-compliant caching. It includes a small server to serve cacheable content and then performs multiple requests to show caching in action, distinguishing between initial requests and cached responses."},"warnings":[{"fix":"Initialize `Keyv` separately and pass the instance: `import Keyv from '@keyv/redis'; const cache = new Keyv('redis://...'); new CacheableRequest(http.request, { cache }).request();`","message":"Starting with v13.0.0, the `CacheableRequest` constructor no longer accepts a direct connection string for Keyv. Instead, you must pass an already instantiated Keyv instance or a Keyv storage adapter instance.","severity":"breaking","affected_versions":">=13.0.0"},{"fix":"Change `const cacheableRequest = new CacheableRequest(http.request);` to `const cacheableRequest = new CacheableRequest(http.request).request();`","message":"As of v10.0.0, after instantiating `new CacheableRequest(http.request)`, you must explicitly call the `.request()` method on the instance to get the callable function. Direct instantiation no longer returns the request function.","severity":"breaking","affected_versions":">=10.0.0"},{"fix":"Migrate your project to use ES Modules (e.g., set `\"type\": \"module\"` in `package.json` and use `import`). For existing CommonJS projects, consider staying on v8 or lower, or use dynamic `import()` for `cacheable-request`.","message":"Version 9 and higher of `cacheable-request` are pure ESM modules. CommonJS `require()` is no longer supported and will result in an `ERR_REQUIRE_ESM` error.","severity":"breaking","affected_versions":">=9.0.0"},{"fix":"Understand that you will still interact with Node's native `IncomingMessage` and `ClientRequest` objects. If you need a higher-level API, integrate `cacheable-request` with a compatible client library or use a different client that offers built-in caching.","message":"This package is a low-level wrapper for Node.js's native `http.request` and `https.request`. It is not a high-level HTTP client library like `axios` or `node-fetch`. It provides caching functionality but does not abstract away the complexities of native HTTP requests.","severity":"gotcha","affected_versions":"*"},{"fix":"Review your cache eviction strategies if using `node-cache` storage. Consider implementing alternative memory management or switching to a Keyv adapter with explicit size limits if `maxKeys` functionality is critical.","message":"In the monorepo, `node-cache` (which can be used as a storage adapter for `cacheable-request`) removed the `maxKeys` limit feature in a recent patch version within the v13 series. If you relied on this limit for in-memory NodeCacheStore, it's no longer available.","severity":"breaking","affected_versions":">=13.0.0"}],"env_vars":null,"last_verified":"2026-04-21T00:00:00.000Z","next_check":"2026-07-20T00:00:00.000Z","problems":[{"fix":"Update your project to use ES Modules (e.g., `\"type\": \"module\"` in `package.json` and `import CacheableRequest from 'cacheable-request';`) or use dynamic `import()` if you must remain in a CommonJS context: `const { default: CacheableRequest } = await import('cacheable-request');`","cause":"`cacheable-request` is an ES Module, but you are trying to import it using CommonJS `require()`.","error":"ERR_REQUIRE_ESM: require() of ES Module .../node_modules/cacheable-request/index.js from ... not supported."},{"fix":"Change `const cacheableRequest = new CacheableRequest(http.request);` to `const cacheableRequest = new CacheableRequest(http.request).request();`","cause":"After `new CacheableRequest(...)`, you did not call the `.request()` method, so `cacheableRequest` is an object, not the callable request function.","error":"TypeError: cacheableRequest is not a function"},{"fix":"Instantiate Keyv with the connection string first, then pass the Keyv instance to `CacheableRequest`: `const cache = new Keyv('redis://localhost:6379'); const cacheableRequest = new CacheableRequest(http.request, { cache }).request();`","cause":"Attempting to pass a connection string directly to the `CacheableRequest` constructor in v13+.","error":"KeyvConnectionError: Invalid connection string"},{"fix":"Ensure you are using the correct function signature, or cast the argument if you are certain of its compatibility, e.g., `cacheableRequest('http://example.com', { /* options */ }, callback);` or ensure the `request` function is correctly typed if you've wrapped it.","cause":"Attempting to pass a URL string directly to the `cacheableRequest` function expecting `ClientRequestArgs` in TypeScript without proper overload.","error":"Argument of type 'string' is not assignable to parameter of type 'ClientRequestArgs'"}],"ecosystem":"npm"}