{"id":17814,"library":"modify-response-middleware","title":"Express Response Modification Middleware","description":"The `modify-response-middleware` package provides an Express middleware designed to intercept and transform HTTP response bodies before they are sent to the client. It transparently handles various compression encodings like Gzip, Brotli, Deflate, and Br, allowing developers to modify response data regardless of its original compression status. As of version 1.1.0, it supports both uncompressed and compressed payloads, offering options to disable caching (`noCache`). This middleware is particularly useful for injecting data, sanitizing output, or performing last-minute transformations on API responses. Its release cadence appears stable but infrequent, typical for a focused utility. A key differentiator is its built-in handling of common compression algorithms, abstracting away the complexities of decompression and re-compression during modification.","status":"active","version":"1.1.0","language":"javascript","source_language":"en","source_url":"https://github.com/zuojiang/modify-response-middleware","tags":["javascript","express","modify","response","middleware","zlib","brotli","gzip","deflate"],"install":[{"cmd":"npm install modify-response-middleware","lang":"bash","label":"npm"},{"cmd":"yarn add modify-response-middleware","lang":"bash","label":"yarn"},{"cmd":"pnpm add modify-response-middleware","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"This is an Express.js middleware and requires Express to function.","package":"express","optional":false}],"imports":[{"note":"The package primarily uses an ESM default export. While CommonJS `require()` might work due to transpilation, `import` is the idiomatic way. For older CJS environments, `const modifyRes = require('modify-response-middleware').default` might be necessary if it's strictly ESM.","wrong":"const modifyRes = require('modify-response-middleware')","symbol":"modifyRes","correct":"import modifyRes from 'modify-response-middleware'"},{"note":"While `Buffer` is globally available in Node.js, explicit import from `node:buffer` or `buffer` is good practice, especially in TypeScript or bundled environments. The middleware's callback expects a Buffer as a return type.","wrong":"import { Buffer } from 'buffer'","symbol":"Buffer","correct":"import { Buffer } from 'node:buffer'"}],"quickstart":{"code":"import express from 'express';\nimport modifyRes from 'modify-response-middleware';\n\nconst app = express();\n\napp.use(express.json()); // Ensure JSON body parsing for incoming requests if needed\n\n// Apply the modification middleware early in the stack\napp.use(modifyRes((content, req, res) => {\n  if (content && res.get('Content-Type')?.includes('application/json')) {\n    try {\n      const data = JSON.parse(content.toString());\n      // Example: Modify the age property of the JSON response\n      data.age = (data.age || 0) + 2;\n      data.message = 'Response modified by middleware!';\n      return Buffer.from(JSON.stringify(data));\n    } catch (e) {\n      console.error('Failed to parse or modify JSON content:', e);\n      // Return original content if modification fails\n      return content;\n    }\n  }\n  // Always return content, even if no modification occurred or type didn't match\n  return content;\n}, {\n  noCache: true, // Prevents 304 Not Modified responses, useful for dynamic content\n}));\n\napp.get('/user', (req, res) => {\n  res.json({\n    name: 'Tom',\n    age: 18,\n    status: 'active'\n  });\n});\n\napp.get('/html', (req, res) => {\n  res.send('<h1>Hello, World!</h1><p>This is an HTML response.</p>');\n});\n\nconst PORT = 3000;\napp.listen(PORT, () => {\n  console.log(`Server listening on port ${PORT}`);\n  console.log(`Test with: curl http://localhost:${PORT}/user`);\n  console.log(`Test with: curl http://localhost:${PORT}/html`);\n});","lang":"typescript","description":"This quickstart demonstrates how to integrate `modify-response-middleware` into an Express application to intercept and modify JSON response bodies before they are sent to the client."},"warnings":[{"fix":"Ensure `app.use(modifyRes(...))` is declared early in your Express application's middleware stack, ideally before route definitions. If using router-level middleware, place it before route-specific handlers within that router.","message":"Middleware order is critical. `modify-response-middleware` must be applied *before* any route handlers or other middleware that send responses (e.g., `res.send()`, `res.json()`). Placing it after these handlers will result in it never being invoked for those responses, as headers might have already been sent.","severity":"breaking","affected_versions":">=1.0.0"},{"fix":"Profile your application with and without the middleware in production scenarios. Consider applying the middleware only to specific routes (using `app.use('/path', modifyRes(...))`) or conditionally based on response size if performance becomes an issue.","message":"Modifying response bodies, especially after decompression and before re-compression, can introduce performance overhead. For very large responses or high-traffic applications, this can significantly impact server throughput and latency due to CPU usage for (de)compression and memory for buffering.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"If `noCache` is not suitable, ensure your modified response handler explicitly removes or recalculates `Content-Length` and `ETag` headers if the body size changes significantly. Monitor network responses to ensure headers align with modified content.","message":"When modifying response content, `Content-Length` and `ETag` headers can become invalid. The `noCache: true` option helps mitigate `ETag` issues by setting `Cache-Control: no-cache`, but if `Content-Length` is present and incorrect, it can lead to client-side issues or truncated responses. The middleware attempts to handle this, but explicit verification is sometimes needed.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Always validate the content type (e.g., `res.get('Content-Type')`) within your `modifyRes` callback before attempting type-specific parsing (e.g., `JSON.parse()`). Wrap parsing logic in `try...catch` blocks to handle malformed or unexpected data gracefully. Return the original `content` buffer if parsing/modification fails.","message":"The callback function provided to `modifyRes` expects `content` to be a `Buffer`. If your modification logic assumes a specific content type (e.g., JSON) and attempts parsing without proper checks, it can throw errors for other content types (e.g., HTML, plain text, images).","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-23T00:00:00.000Z","next_check":"2026-07-22T00:00:00.000Z","problems":[{"fix":"Before parsing, check `res.get('Content-Type')` within your `modifyRes` callback to ensure it's `application/json`. Add a `try...catch` block around `JSON.parse()` to handle non-JSON or malformed responses gracefully.","cause":"Attempting to `JSON.parse()` a non-JSON response, often an HTML error page or another content type, because the `Content-Type` header was not checked.","error":"SyntaxError: Unexpected token < in JSON at position 0"},{"fix":"Always add a check `if (content && Buffer.isBuffer(content))` before calling `content.toString()` or attempting to process `content`. For empty responses, `content` might legitimately be `null` or an empty buffer, in which case it should be returned as is.","cause":"The `content` parameter passed to your callback is `null`, `undefined`, or not a `Buffer` instance, often for empty responses or if upstream middleware unexpectedly altered the body format.","error":"TypeError: content.toString is not a function"},{"fix":"When the response body is modified, the middleware should ideally reset or remove the `Content-Length` header. If issues persist, ensure the middleware or your callback removes `res.removeHeader('Content-Length')` or explicitly sets `res.setHeader('Content-Length', Buffer.byteLength(newContent))` for non-compressed content.","cause":"The `Content-Length` header sent by the server does not match the actual byte length of the modified response body, causing client-side errors or incomplete downloads.","error":"(Client-side) ERR_CONTENT_LENGTH_MISMATCH or truncated responses"}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null}