A standalone HTTP server that exposes a CacheHandler instance via HTTP API. Designed to work with FetchLayer from @nimpl/cache to enable distributed caching across multiple application instances.
- Types
- ESM
- CJS
- License
- MIT
- Deps
- 0
- Install Size
- 54.4 kB
- Vulns
- 0
- Published
npm install @nimpl/cache-serverpnpm add @nimpl/cache-serveryarn add @nimpl/cache-serverbun add @nimpl/cache-serverdeno add npm:@nimpl/cache-servervlt install @nimpl/cache-servervp add @nimpl/cache-server@nimpl/cache-server
A standalone HTTP server that exposes a CacheHandler instance via HTTP API. Designed to work with FetchLayer from @nimpl/cache to enable distributed caching across multiple application instances.
Installation
npm install @nimpl/cache-server @nimpl/cache
# or
pnpm add @nimpl/cache-server @nimpl/cache
Overview
@nimpl/cache-server provides an HTTP server that wraps any CacheHandler instance and exposes it through a standardized HTTP API. This enables you to:
- Share cache across multiple application instances in distributed deployments
- Run cache as a separate service for better scalability
- Use
FetchLayerin your applications to access the cache remotely
The server implements the HTTP API expected by FetchLayer, making it easy to set up distributed caching solutions.
Usage
Basic Setup
Create a cache handler and start the server:
import { run } from "@nimpl/cache-server";
import { CacheHandler, LruLayer, FsLayer } from "@nimpl/cache";
const cacheHandler = new CacheHandler({
ephemeralLayer: new LruLayer(),
persistentLayer: new FsLayer(),
});
run(cacheHandler);
The server will start on http://localhost:4000 by default.
Custom Configuration
import { run } from "@nimpl/cache-server";
import { CacheHandler, LruLayer, RedisLayer } from "@nimpl/cache";
const cacheHandler = new CacheHandler({
ephemeralLayer: new LruLayer(),
persistentLayer: new RedisLayer(),
});
run(cacheHandler, {
port: 8080,
host: "0.0.0.0",
verifyRequest: async (req) => {
// Add authentication/authorization logic
const authHeader = req.headers.authorization;
return authHeader === `Bearer ${process.env.CACHE_TOKEN}`;
},
});
Using with FetchLayer
In your application instances, use FetchLayer to connect to the cache server:
// cache-handler.js
import { CacheHandler, LruLayer, FetchLayer } from "@nimpl/cache";
export default new CacheHandler({
ephemeralLayer: new LruLayer(),
persistentLayer: new FetchLayer({
baseUrl: process.env.CACHE_SERVER_URL || "http://cache-server:4000",
}),
});
API
init(cacheHandler, options?)
Creates an HTTP server instance without starting it. Useful when you need to control when the server starts or integrate it with other server frameworks.
Parameters:
cacheHandler(CacheHandlerRoot): The cache handler instance to expose via HTTPoptions(CacheServerOptions): Optional configurationverifyRequest((req: IncomingMessage) => Promise<boolean>): Optional callback to verify/authenticate requests. Returnfalseto reject the request with 403 status.
Returns: http.Server - The HTTP server instance
Example:
import { init } from "@nimpl/cache-server";
import { CacheHandler, LruLayer, RedisLayer } from "@nimpl/cache";
const cacheHandler = new CacheHandler({
ephemeralLayer: new LruLayer(),
persistentLayer: new RedisLayer(),
});
const server = init(cacheHandler, {
verifyRequest: async (req) => {
// Custom authentication logic
return true;
},
});
// Start the server manually
server.listen(4000, "0.0.0.0", () => {
console.log("Cache server running on port 4000");
});
run(cacheHandler, options?)
Creates and starts an HTTP server that exposes the cache handler.
Parameters:
cacheHandler(CacheHandlerRoot): The cache handler instance to expose via HTTPoptions(CacheServerOptions): Optional configurationport(number): Port to run the server on. Default:4000host(string): Host to bind the server to. Default:"localhost"verifyRequest((req: IncomingMessage) => Promise<boolean>): Optional callback to verify/authenticate requests. Returnfalseto reject the request with 403 status.
Returns: http.Server - The HTTP server instance
Example:
import { run } from "@nimpl/cache-server";
import { CacheHandler, LruLayer, FsLayer } from "@nimpl/cache";
const cacheHandler = new CacheHandler({
ephemeralLayer: new LruLayer(),
persistentLayer: new FsLayer(),
});
run(cacheHandler, {
port: 4000,
host: "0.0.0.0",
});
HTTP API
The server implements the following HTTP endpoints expected by FetchLayer:
GET /?key=<key>
Retrieves a cache entry.
- Query Parameters:
key(required): The cache key
- Response:
200 OK: Returns the cache entry as a stream withx-cache-metadataheader404 Not Found: Cache entry not found400 Bad Request: Missing key parameter500 Internal Server Error: Server error
POST /?key=<key>
Stores a cache entry.
- Query Parameters:
key(required): The cache key
- Headers:
x-cache-metadata(required): JSON string containing cache metadata (tags, timestamp, stale, expire, revalidate)Content-Type:application/octet-stream
- Body: Stream containing the cache value
- Response:
200 OK: Entry stored successfully400 Bad Request: Missing key or metadata500 Internal Server Error: Server error
PUT /?key=<key>
Updates cache lifetimes for a single key using the handler’s updateKey method.
- Query Parameters:
key(required): The cache key to update
- Body: JSON object with optional
durationsobject (e.g.{ "durations": { "expire": 60 } })
PUT /
Updates tags for cache entries.
- Body: JSON object with
tags(array) and optionaldurationsobject - Response:
200 OK: Tags updated successfully400 Bad Request: Invalid request body500 Internal Server Error: Server error
DELETE /?key=<key>
Deletes a cache entry.
- Query Parameters:
key(required): The cache key
- Response:
200 OK: Entry deleted successfully400 Bad Request: Missing key parameter500 Internal Server Error: Server error
GET /keys
Returns all cache keys.
- Response:
200 OK: JSON array of cache keys500 Internal Server Error: Server error
GET /readiness
Health check endpoint.
- Response:
200 OK: JSON object withreadyboolean indicating cache handler readiness
Security
The server does not include built-in authentication. For production deployments, you should implement request verification using the verifyRequest option:
run(cacheHandler, {
verifyRequest: async (req) => {
// Example: Verify API token
const authHeader = req.headers.authorization;
const expectedToken = process.env.CACHE_SERVER_TOKEN;
if (!authHeader || !expectedToken) {
return false;
}
return authHeader === `Bearer ${expectedToken}`;
},
});
For additional security, consider:
- Running the server behind a reverse proxy with authentication (e.g., nginx, Traefik)
- Using network policies to restrict access to the cache server
- Implementing rate limiting
- Using TLS/HTTPS for encrypted communication
Deployment
Docker
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY . .
CMD ["node", "server.js"]
Kubernetes
The cache server can be deployed as a separate service in Kubernetes:
apiVersion: apps/v1
kind: Deployment
metadata:
name: cache-server
spec:
replicas: 1
selector:
matchLabels:
app: cache-server
template:
metadata:
labels:
app: cache-server
spec:
containers:
- name: cache-server
image: your-registry/cache-server:latest
ports:
- containerPort: 4000
env:
- name: REDIS_URL
valueFrom:
secretKeyRef:
name: cache-secrets
key: redis-url
Examples
See the external-store-server example for a complete setup demonstrating cache server with filesystem storage.