tamper - Response Body Middleware

raw JSON →
1.1.0 verified Thu Apr 23 auth: no javascript maintenance

tamper is a Node.js middleware designed for intercepting and modifying HTTP response bodies before they are sent to the client. It provides a simple API for Connect/Express-compatible applications, allowing developers to inspect request and response headers and conditionally apply transformations to the response body. The current stable version, 1.1.0, indicates a mature but largely feature-complete codebase with infrequent updates. Its primary differentiation lies in its focused scope of response body manipulation, offering a callback-based or Promise-based mechanism for transformations. It's particularly useful for tasks like injecting scripts, performing server-side content rewrites, or debugging response payloads without directly altering original handlers. It ships with TypeScript types, enhancing developer experience for type-safe applications.

error ReferenceError: require is not defined in ES module scope
cause Attempting to use `require` in an ES module file (`.mjs` or `package.json` `"type": "module"`).
fix
As tamper is a CommonJS module, you need to use import tamper from 'tamper' with a bundler that handles CJS-to-ESM conversion, or switch your file to CommonJS (.cjs or package.json "type": "commonjs").
error Error: Cannot find module 'tamper'
cause The `tamper` package is not installed or the import/require path is incorrect.
fix
Run npm install tamper or yarn add tamper to install the package. Verify the package is listed in node_modules and that require('tamper') is spelled correctly.
error RangeError: Invalid array length
cause This can sometimes occur when attempting to modify binary or already compressed data as if it were a string, or if `Content-Length` becomes severely mismatched.
fix
Always ensure your tamper logic explicitly checks res.getHeader('Content-Type') to only process text/html, text/plain, or other expected string-based content types. Place tamper before compression middleware.
gotcha Modifying response bodies implies buffering the entire response in memory. For very large responses, this can lead to significant memory consumption and increased latency. Consider alternatives for streaming modifications if performance is critical for large files.
fix Monitor memory usage for applications handling large responses. Limit `tamper` usage to specific routes or content types known to be small.
gotcha When modifying a response body, the `Content-Length` HTTP header (if present) becomes invalid. Clients relying on this header might receive truncated or incomplete data. `tamper` attempts to handle this, but manual verification is recommended.
fix Ensure `tamper` is configured correctly, and test responses with client-side tools to verify integrity. In some cases, it might be necessary to manually `res.removeHeader('Content-Length')` if issues persist.
gotcha If compression middleware (e.g., `compression`) is used *after* `tamper`, `tamper` will receive the uncompressed body, but the `Content-Length` issue still applies. If `compression` is used *before* `tamper`, `tamper` will receive and attempt to modify the compressed binary body, which will result in corrupted output.
fix Always place `tamper` middleware *before* any compression middleware (e.g., `express.compress()`, `compression`) in your middleware stack. This ensures `tamper` operates on the uncompressed text.
breaking `tamper` v1.x is a CommonJS module. Attempting to import it using ES module syntax (`import tamper from 'tamper';`) will fail in Node.js environments unless specific experimental flags or bundler configurations are used. This can be a breaking change when migrating older CJS applications to a modern ESM-first setup.
fix Continue using `const tamper = require('tamper');` for CommonJS compatibility. If strictly needing ESM, consider writing a wrapper or using dynamic `import()` within an async function, though this may complicate middleware chaining.
npm install tamper
yarn add tamper
pnpm add tamper

Demonstrates basic usage of `tamper` middleware with Express, showing how to conditionally modify HTML response bodies and leave other content types untouched.

import express, { Request, Response, NextFunction } from 'express';
import tamper from 'tamper'; // This would actually be 'const tamper = require("tamper")' for CJS

// For demonstration, let's pretend tamper supports ESM or use require syntax
const app = express();

app.use(tamper(function(req: Request, res: Response) {
  // Only modify HTML responses
  if (res.getHeader('Content-Type')?.toString().includes('text/html')) {
    console.log(`Tampering with HTML response for ${req.url}`);
    // Return a function to capture and modify the body
    return function(body: string) {
      // Replace all occurrences of 'foo' with 'bar'
      // Or inject a script tag for client-side analytics
      return body.replace(/foo/g, 'bar').replace('</body>', '<script>console.log("Body tampered!")</script></body>');
    };
  }
  // Return a falsy value to continue without body modification
  return;
}));

app.get('/', (req, res) => {
  res.status(200).set('Content-Type', 'text/html').send('<html><body><h1>Hello foo world!</h1></body></html>');
});

app.get('/json', (req, res) => {
  res.json({ message: 'This is JSON' });
});

const PORT = process.env.PORT ?? 3000;
app.listen(PORT, () => {
  console.log(`Server listening on port ${PORT}`);
  console.log('Try visiting http://localhost:3000 and http://localhost:3000/json');
});