{"id":17354,"library":"reserve","title":"REserve: Regex-Configurable HTTP Server","description":"REserve is a lightweight and versatile HTTP server package, currently at stable version 2.3.5. It specializes in serving static files, acting as a reverse proxy, and aggregating resources from multiple sources. The core functionality relies on declarative, regular expression-based mappings defined in a JSON configuration, offering fine-grained control over request routing and handling. The project demonstrates an active release cadence, with frequent minor updates and bug fixes. Its key differentiators include a minimal footprint with zero runtime dependencies, efficient performance (updated to `punycache`@`1.0.1` in v2.3.0), and the power of embedded regular expressions for highly flexible and dynamic server configurations, making it well-suited for development environments and complex routing scenarios without the overhead of larger frameworks.","status":"active","version":"2.3.5","language":"javascript","source_language":"en","source_url":"https://github.com/ArnaudBuchholz/reserve","tags":["javascript","http","serve","static","json","regexp","typescript"],"install":[{"cmd":"npm install reserve","lang":"bash","label":"npm"},{"cmd":"yarn add reserve","lang":"bash","label":"yarn"},{"cmd":"pnpm add reserve","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"The `serve` function is the primary export for embedding the server. CommonJS `require` works but ESM `import` is preferred in modern Node.js.","wrong":"const serve = require('reserve')","symbol":"serve","correct":"import { serve } from 'reserve'"},{"note":"TypeScript type for defining the server's configuration object. Essential for type-safe server setup.","symbol":"Configuration","correct":"import { Configuration } from 'reserve'"},{"note":"TypeScript type for the object returned by `serve()`, which exposes event emitters and the `close` method.","symbol":"Server","correct":"import { Server } from 'reserve'"}],"quickstart":{"code":"import { serve, Configuration, Server } from 'reserve';\nimport * as path from 'path';\n\nconst config: Configuration = {\n  port: 8080,\n  mappings: [\n    {\n      // Serve files from the current working directory\n      match: '^/(.*)',\n      file: path.join(process.cwd(), '$1') // Ensures serving from the correct absolute path\n    },\n    {\n      // Default catch-all for unmatched requests\n      status: 404\n    }\n  ]\n};\n\nlet serverInstance: Server | null = null; // To hold the server instance for graceful shutdown\n\nserve(config)\n  .on('ready', ({ url }: { url: string }) => {\n    serverInstance = serverInstance; // Capture the instance\n    console.log(`REserve server running at ${url}`);\n    console.log(`Try accessing http://localhost:${config.port}/package.json if this file exists in your current directory.`);\n  })\n  .on('error', (error: Error) => {\n    console.error('REserve server encountered an error:', error.message);\n  })\n  .on('abort', () => {\n    console.log('REserve server aborted.');\n  });\n\n// Implement graceful shutdown on process termination signals\nprocess.on('SIGINT', async () => {\n  console.log('SIGINT received. Shutting down REserve server...');\n  if (serverInstance) {\n    try {\n      await serverInstance.close();\n      console.log('REserve server gracefully closed.');\n    } catch (err) {\n      console.error('Error closing REserve server:', err);\n    }\n  }\n  process.exit(0);\n});\n\nprocess.on('SIGTERM', async () => {\n  console.log('SIGTERM received. Shutting down REserve server...');\n  if (serverInstance) {\n    try {\n      await serverInstance.close();\n      console.log('REserve server gracefully closed.');\n    } catch (err) {\n      console.error('Error closing REserve server:', err);\n    }\n  }\n  process.exit(0);\n});","lang":"typescript","description":"Demonstrates how to embed and start a `reserve` HTTP server in a TypeScript application with basic static file serving, including event handling for ready, error, and graceful shutdown on process signals."},"warnings":[{"fix":"Update your `file` handler mappings to explicitly include `\"static\": true` if you intend for directory listings or other static file behaviors.","message":"The `static` option for `file` handlers now defaults to `false` instead of `true`. If your configuration relied on `static: true` by default, explicitly set it in your mappings.","severity":"breaking","affected_versions":">=2.3.0"},{"fix":"Use online regex testers or Node.js `RegExp` to validate your patterns. Start with simple matches and incrementally increase complexity. Ensure patterns are anchored (e.g., `^/path/(.*)$`) to prevent partial matches.","message":"Regular expression matching is fundamental to `reserve` configuration. Incorrect or overly broad regex patterns can lead to unexpected routing, resource exposure, or 404 errors. Carefully test your `match` patterns.","severity":"gotcha","affected_versions":">=1.0"},{"fix":"Upgrade to `reserve@2.3.0` or higher to utilize the `force` option with `serverInstance.close({ force: true })` for more reliable server shutdowns.","message":"In earlier versions, `Server.close()` might not have forcefully closed all pending connections, potentially leading to processes hanging. Version 2.3.0 introduced options to force closing.","severity":"gotcha","affected_versions":"<2.3.0"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Change the `port` in your `reserve` configuration to an unused port, or terminate the process currently occupying the port (e.g., using `lsof -i :8080` and `kill <PID>` on Linux/macOS, or Resource Monitor on Windows).","cause":"The specified port (e.g., 8080) is already being used by another application or a previously failed server instance.","error":"Error: listen EADDRINUSE: address already in use :::8080"},{"fix":"Review your `mappings` array. Ensure your `match` regular expressions correctly capture the intended URLs. Check `file` handler paths for correctness relative to the server's working directory or use absolute paths.","cause":"No mapping in the `reserve` configuration matched the incoming request URL, or a `file` handler pointed to a non-existent file.","error":"404 Not Found (from reserve server)"},{"fix":"Ensure you are calling `.on()` methods directly on the `serve` function's return value, which is an event emitter (Promise-like with `.on()` methods). Do not `await serve(config)` if you intend to chain `.on()` immediately. If using `async/await`, await after chaining events, or capture the returned instance.","cause":"Attempting to chain `.on()` calls directly after `serve()` without correctly handling its return type or in a context where `serve` is awaited prematurely.","error":"Property 'on' does not exist on type 'void' or 'Promise<void>'"}],"ecosystem":"npm","meta_description":null}