{"id":17179,"library":"bouncy","title":"bouncy HTTP Proxy and Router","description":"bouncy is a low-level Node.js library that provides HTTP proxy and routing capabilities by wrapping `net.Server`. It allows programmatic redirection of raw HTTP traffic based on request headers (like `Host`), paths, or methods. Developers define routing logic within a callback function, gaining fine-grained control over request and response streams for tasks like load balancing or host-based multiplexing. Version `3.2.2` was published in October 2014, and the project shows no significant activity since then, indicating it is abandoned. It differs from higher-level HTTP frameworks by operating directly with Node.js's `net` and `tls` modules, offering a more primitive, stream-oriented approach to proxying.","status":"abandoned","version":"3.2.2","language":"javascript","source_language":"en","source_url":"git://github.com/substack/bouncy","tags":["javascript","http","proxy","router","load","balancer"],"install":[{"cmd":"npm install bouncy","lang":"bash","label":"npm"},{"cmd":"yarn add bouncy","lang":"bash","label":"yarn"},{"cmd":"pnpm add bouncy","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"bouncy is a CommonJS module. Direct ESM import (`import bouncy from 'bouncy'`) will result in a runtime error or require an explicit CommonJS wrapper or bundler configuration in modern Node.js environments.","wrong":"import bouncy from 'bouncy';","symbol":"bouncy","correct":"const bouncy = require('bouncy');"},{"note":"The `bouncy` function returns a `net.Server` instance, so you call `.listen()` on the returned server object, not on `bouncy` itself.","wrong":"bouncy.listen(8000);","symbol":"server.listen","correct":"server.listen(8000);"},{"note":"The callback function passed to `bouncy` will receive `(req, res, bounce)` if its arity is 3, otherwise it receives `(req, bounce)`. If you need access to the `res` object to manipulate the response directly (e.g., set status codes for unhandled requests), ensure your function signature includes `res`.","wrong":"bouncy(function (req, bounce) { /* ... */ }); // If you need 'res'","symbol":"bounce callback arity (req, res, bounce)","correct":"bouncy(function (req, res, bounce) { /* ... */ });"}],"quickstart":{"code":"const bouncy = require('bouncy');\nconst http = require('http');\n\n// Create a simple backend server 1\nconst backend1 = http.createServer((req, res) => {\n    res.writeHead(200, { 'Content-Type': 'text/plain' });\n    res.end(`Hello from backend 8001 (Host: ${req.headers.host}, Path: ${req.url})`);\n});\nbackend1.listen(8001, () => console.log('Backend 8001 listening.'));\n\n// Create a simple backend server 2\nconst backend2 = http.createServer((req, res) => {\n    res.writeHead(200, { 'Content-Type': 'text/plain' });\n    res.end(`Hello from backend 8002 (Host: ${req.headers.host}, Path: ${req.url})`);\n});\nbackend2.listen(8002, () => console.log('Backend 8002 listening.'));\n\n// Create the bouncy proxy server\nconst proxyServer = bouncy(function (req, res, bounce) {\n    console.log(`Incoming request for Host: ${req.headers.host}, URL: ${req.url}`);\n\n    if (req.headers.host === 'beep.example.com') {\n        console.log('Routing to 8001');\n        bounce(8001);\n    } else if (req.headers.host === 'boop.example.com') {\n        console.log('Routing to 8002');\n        bounce(8002, { path: '/custom-path' }); // Example of path modification\n    } else if (req.url === '/admin') {\n        // Example of direct response from proxy without bouncing\n        res.statusCode = 200;\n        res.end('Admin dashboard via proxy.');\n    } else {\n        console.log('No route found, sending 404.');\n        res.statusCode = 404;\n        res.end('No such host or route found.');\n    }\n});\n\nproxyServer.listen(8000, () => console.log('Proxy server listening on port 8000.'));\n\nconsole.log('\\nTo test, use curl or modify your /etc/hosts file:\\n');\nconsole.log('  curl -H \"Host: beep.example.com\" http://localhost:8000');\nconsole.log('  curl -H \"Host: boop.example.com\" http://localhost:8000');\nconsole.log('  curl http://localhost:8000/admin');\nconsole.log('  curl http://localhost:8000/unknown-host');","lang":"javascript","description":"This quickstart demonstrates how to use `bouncy` to create a host-based HTTP router. It sets up two backend servers on ports 8001 and 8002, and a `bouncy` proxy on port 8000. Requests are routed to different backends based on the `Host` header, or handled directly by the proxy, showing basic routing and direct response capabilities."},"warnings":[{"fix":"Consider migrating to a actively maintained proxy library like `http-proxy`, `node-http-proxy`, or `express-http-proxy` for modern Node.js applications.","message":"The `bouncy` package is abandoned and has not been updated since 2014. It is unlikely to receive security patches, bug fixes, or compatibility updates for newer Node.js versions or HTTP standards. Using it in production environments is highly discouraged due to potential security vulnerabilities and lack of maintenance.","severity":"breaking","affected_versions":">=3.2.2"},{"fix":"Ensure `opts.key`, `opts.cert`, and `opts.SNICallback` (if needed) are correctly supplied to the `bouncy` constructor according to the Node.js `tls` module documentation. Test with tools like `openssl s_client` or `curl -v` to diagnose SSL/TLS handshake issues.","message":"When configuring an HTTPS router using `bouncy`, `opts.key` and `opts.cert` are required. For environments with multiple SSL certificates requiring Server Name Indication (SNI), `opts.SNICallback` must be provided, following Node.js `tls.createServer` documentation. Misconfiguration can lead to failed HTTPS connections or certificate errors.","severity":"gotcha","affected_versions":">=3.0.0"},{"fix":"Always declare the callback function with three arguments, `function (req, res, bounce)`, if you intend to interact with the HTTP response object (e.g., `res.statusCode = 404; res.end('Not Found');`).","message":"The callback function passed to `bouncy` receives different arguments based on its arity. A function declared with two arguments (`function (req, bounce)`) will not receive the `res` (response) object, which is crucial for sending direct responses or modifying headers before bouncing. To access `res`, the function must be declared with three arguments (`function (req, res, bounce)`).","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Be aware that `bouncy` provides a foundational proxy mechanism. Integrate `bouncy` within a larger application structure or use it for simpler, dedicated proxy tasks. For complex API gateways or advanced routing, consider full-featured proxy solutions or web frameworks with built-in proxy capabilities.","message":"`bouncy` operates at a relatively low level, directly piping streams. This means it doesn't automatically handle higher-level HTTP features or complex middleware chains common in modern web frameworks. Custom logic for things like authentication, rate limiting, or advanced request manipulation must be implemented manually within the `bouncy` callback.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Ensure your project is configured for CommonJS, or use `const bouncy = require('bouncy');` in a CommonJS module. If you must use ESM, consider a dynamic `import('bouncy')` after `require` is globally defined, or use a bundler that handles CJS-to-ESM conversion.","cause":"Attempting to use `bouncy` in a modern Node.js ESM context with `import bouncy from 'bouncy';` without proper configuration.","error":"TypeError: bouncy is not a function"},{"fix":"Verify that `opts.key` and `opts.cert` point to valid SSL certificate and private key files. For self-signed certificates in development, you might need to use `NODE_TLS_REJECT_UNAUTHORIZED=0` (not for production) or configure your client to trust the self-signed certificate.","cause":"Incorrect or incomplete SSL/TLS configuration (`opts.key`, `opts.cert`) for an HTTPS proxy, or issues with certificate authorities.","error":"Error: self-signed certificate in certificate chain (or similar SSL/TLS error)"},{"fix":"Ensure that the port argument passed to `bounce()` or `server.listen()` is a valid integer between 1 and 65535. For example, `bounce(8001);` not `bounce('8001');` (though `bouncy`'s sugar syntax might handle string ports, it's best practice to use numbers).","cause":"Providing a non-numeric value or an invalid port number to the `bounce()` function or `server.listen()`.","error":"RangeError: 'port' option should be a number"}],"ecosystem":"npm","meta_description":null}