Overview
The @1stdigital/prism-http package provides middleware for vanilla Node.js HTTP servers, without requiring any framework. Perfect for lightweight APIs or custom HTTP implementations.Zero Dependencies
Works with raw http/https modules
Framework-Free
No Express, Fastify, or other framework needed
Lightweight
Minimal overhead, maximum performance
Installation
- npm
- yarn
Copy
npm install @1stdigital/prism-http
Copy
yarn add @1stdigital/prism-http
Quick Start
Copy
const http = require("http");
const { prismPaymentMiddleware } = require("@1stdigital/prism-http");
// Create middleware
const middleware = prismPaymentMiddleware(
{
apiKey: "dev-key-123",
baseUrl: "https://prism-api.test.1stdigital.tech",
},
{
"/api/premium": {
price: 0.01, // $0.01 USD
description: "Premium API",
},
},
);
// Create HTTP server
const server = http.createServer((req, res) => {
// Apply middleware
middleware(req, res, () => {
// This runs only if payment verified
if (req.url === "/api/premium") {
res.writeHead(200, { "Content-Type": "application/json" });
res.end(
JSON.stringify({
message: "Premium content",
payer: req.payer, // Wallet address
}),
);
} else {
res.writeHead(404);
res.end("Not Found");
}
});
});
server.listen(3000);
Configuration
Copy
interface PrismMiddlewareConfig {
apiKey: string;
baseUrl?: string;
debug?: boolean;
}
interface RoutePaymentConfig {
price: number | string; // USD price
description: string;
mimeType?: string;
}
Routing
URL-based Routing
Copy
const server = http.createServer((req, res) => {
middleware(req, res, () => {
const url = new URL(req.url, `http://${req.headers.host}`);
if (url.pathname === "/api/premium") {
res.writeHead(200, { "Content-Type": "application/json" });
res.end(
JSON.stringify({
message: "Premium",
payer: req.payer,
}),
);
} else if (url.pathname === "/api/weather") {
res.writeHead(200, { "Content-Type": "application/json" });
res.end(
JSON.stringify({
location: "SF",
temperature: 72,
payer: req.payer,
}),
);
} else {
res.writeHead(404);
res.end("Not Found");
}
});
});
Accessing Payment Info
Copy
const server = http.createServer((req, res) => {
middleware(req, res, () => {
// Access payer address
const payer = req.payer;
// '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb'
// Access payment object (in res.locals)
const payment = res.locals?.payment;
res.writeHead(200, { "Content-Type": "application/json" });
res.end(
JSON.stringify({
message: "Data",
payer,
network: payment?.network,
}),
);
});
});
Settlement Validation
HTTP middleware interceptsres.end() to validate settlement:
Copy
// Internal implementation (automatic!)
const originalEnd = res.end.bind(res);
res.end = async function(chunk, encoding, callback) {
const settlementResult = await core.settlementCallback(...);
if (!settlementResult || !settlementResult.success) {
// ❌ Settlement failed
res.statusCode = 402;
res.setHeader('Content-Type', 'application/json');
return originalEnd(JSON.stringify({
error: 'Payment settlement failed'
}));
}
// ✅ Settlement succeeded
res.setHeader('X-PAYMENT-RESPONSE', settlementResult.transaction);
return originalEnd(chunk, encoding, callback);
};
Testing
Copy
const http = require("http");
const { prismPaymentMiddleware } = require("@1stdigital/prism-http");
describe("HTTP Payment Middleware", () => {
let server;
beforeAll(() => {
const middleware = prismPaymentMiddleware(
{ apiKey: "test-key" },
{ "/api/premium": { price: 0.01, description: "Test" } },
);
server = http.createServer((req, res) => {
middleware(req, res, () => {
res.writeHead(200);
res.end(JSON.stringify({ message: "OK", payer: req.payer }));
});
});
server.listen(0); // Random port
});
afterAll(() => server.close());
test("returns 402 without payment", async () => {
const port = server.address().port;
const response = await fetch(`http://localhost:${port}/api/premium`);
expect(response.status).toBe(402);
});
});