{"id":14906,"library":"send","title":"Node.js HTTP Static File Streaming","description":"The `send` library provides a low-level utility for streaming static files directly from the file system in Node.js, specifically designed for HTTP responses. It expertly handles features like partial content responses via Range headers, conditional-GET negotiation using If-Match, If-None-Match, If-Modified-Since, and ETag generation. It offers granular control over aspects such as caching (Cache-Control, maxAge, immutable), dotfile handling, and automatic file extension resolution. While a `1.x.x` series exists (up to 1.2.1), the most recent stable release is currently `0.19.2`, indicating a somewhat unconventional release cadence or a focus shift. It is a foundational component often leveraged by higher-level static file serving middleware like `serve-static` within web frameworks.","status":"active","version":"1.2.1","language":"javascript","source_language":"en","source_url":"https://github.com/pillarjs/send","tags":["javascript","static","file","server"],"install":[{"cmd":"npm install send","lang":"bash","label":"npm"},{"cmd":"yarn add send","lang":"bash","label":"yarn"},{"cmd":"pnpm add send","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Used for parsing `maxAge` option values, which can be provided as a string (e.g., '1h').","package":"ms","optional":false},{"reason":"Used for HTTP conditional-GET negotiation (e.g., If-None-Match, If-Modified-Since headers). Updated to v2 in `send@1.2.0`.","package":"fresh","optional":false},{"reason":"Used for determining and setting the appropriate 'Content-Type' HTTP header based on file extension. Updated to v3.0.1 in `send@1.2.0`.","package":"mime-types","optional":false},{"reason":"Used for URL-encoding paths, ensuring proper handling of special characters in URLs. Updated in `send@0.19.1`.","package":"encodeurl","optional":false}],"imports":[{"note":"The primary export is a default function. Named imports are not supported. Works in Node.js environments with 'type: module' in package.json or '.mjs' files.","wrong":"import { send } from 'send'","symbol":"send","correct":"import send from 'send'"},{"note":"CommonJS `require` is the traditional way to import. The package exports a default function, so destructuring won't work.","wrong":"const { send } = require('send')","symbol":"send","correct":"const send = require('send')"},{"note":"Import the `SendStream` type for use with TypeScript when interacting with the event emitter returned by `send()`.","symbol":"SendStream (type)","correct":"import type { SendStream } from 'send'"}],"quickstart":{"code":"import http from 'http';\nimport path from 'path';\nimport send from 'send';\nimport { fileURLToPath } from 'url';\n\n// In an ESM module, __dirname is not directly available. Recreate it.\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n// Create a simple HTTP server\nconst server = http.createServer((req, res) => {\n  const filePath = path.join(__dirname, 'public', req.url || 'index.html');\n  \n  // Basic example of creating a public directory and a file\n  // For a real application, ensure 'public' directory exists with files\n  // or adjust `root` option accordingly.\n  // Example: echo '<h1>Hello from send!</h1>' > public/index.html\n\n  send(req, req.url || '/', { root: path.join(__dirname, 'public') })\n    .on('error', (err) => {\n      if (err.statusCode === 404) {\n        res.statusCode = 404;\n        res.end('File not found');\n      } else {\n        res.statusCode = 500;\n        res.end('Internal Server Error: ' + err.message);\n      }\n    })\n    .on('directory', () => {\n      // Redirect or serve index.html for directory requests if desired\n      res.statusCode = 301;\n      res.setHeader('Location', req.url + '/index.html');\n      res.end('Redirecting to index.html');\n    })\n    .on('end', () => {\n      console.log(`Served: ${req.url}`);\n    })\n    .pipe(res);\n});\n\nconst PORT = 3000;\nserver.listen(PORT, () => {\n  console.log(`Server listening on http://localhost:${PORT}`);\n  console.log(`Try http://localhost:${PORT}/index.html (create 'public/index.html' first)`);\n});\n","lang":"typescript","description":"Demonstrates how to set up a basic Node.js HTTP server using `send` to serve static files from a 'public' directory, handling errors and directory requests."},"warnings":[{"fix":"Upgrade your Node.js environment to version 18 or higher. Alternatively, pin `send` to a `0.x.x` version.","message":"Node.js 18 or newer is now required. Older Node.js versions (below 18) are no longer supported by `send@1.1.0` and above. Users on older Node versions must upgrade their environment or stick to `send@0.x.x` versions.","severity":"breaking","affected_versions":">=1.1.0"},{"fix":"Ensure that your application explicitly handles requests for directory paths (e.g., `/images/`) and redirects them to an appropriate resource (e.g., `/images/index.html`) or configures `index` option if `send` is meant to resolve them.","message":"Security hardening in `send@1.1.0` explicitly prevents serving files when a requested path ends with a `/`. This changes previous behavior where such paths might have implicitly served an `index.html` or similar. This is a deliberate change to prevent potential path traversal or directory listing issues.","severity":"breaking","affected_versions":">=1.1.0"},{"fix":"For explicit control over dotfile handling, set the `dotfiles` option to `'deny'`, `'allow'`, or `'ignore'` as appropriate for your application's security requirements. For example: `send(req, path, { dotfiles: 'deny' })`.","message":"The `dotfiles` option's default behavior ('ignore') is subtly different from explicitly setting `'deny'`. The default will ignore dotfiles (e.g., `.env`), but *not* ignore files within directories that begin with a dot (e.g., `/.git/HEAD`). For strict security, explicitly set `dotfiles: 'deny'` to prevent serving any dotfiles or files within dot directories.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"Ensure the `path` argument is a URL-encoded string derived from `req.url` or a similar source. If constructing the path manually, use `encodeURIComponent()` if necessary, but generally `req.url` is already suitable.","message":"The `path` argument passed to `send(req, path, options)` must be a URL-encoded path, not a direct file-system path. Incorrectly providing a raw file-system path will likely result in 'File not found' errors or unexpected routing.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"When installing, consider `npm install send@latest` to get the version tagged as `latest` by the maintainers. Refer to the official GitHub repository or npm page for the intended release line and support status.","message":"The `send` package has shown an unusual release pattern, with version `0.19.2` being released *after* `1.2.1`. This can lead to confusion about the current stable or recommended version. Always verify the `npm` registry's `latest` tag and release dates.","severity":"gotcha","affected_versions":"all"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Use `const send = require('send')` for CommonJS or `import send from 'send'` for ESM. The `send` package provides a default export, not named exports.","cause":"Attempting to destructure `send` from a `require` or `import` statement, or using `require('send')` in an ESM context where only default imports are allowed implicitly.","error":"TypeError: send is not a function"},{"fix":"Double-check the `root` option to ensure it points to the correct base directory. Verify that the `path` argument accurately reflects the URL path (which `send` resolves relative to `root`). Ensure the file actually exists on the filesystem and has correct permissions. Remember `path` is URL-encoded, not a raw filesystem path.","cause":"The file specified by the `path` argument combined with the `root` option does not exist, or the `root` option is misconfigured, or the `path` argument is not URL-encoded.","error":"Error: ENOENT: no such file or directory, stat '/path/to/my/app/myFile.txt'"},{"fix":"If your project is CommonJS, ensure `send` is installed as a CJS-compatible version or configure your build system to handle ESM. If your project is ESM (e.g., `\"type\": \"module\"` in `package.json`), use `import send from 'send'`. Node.js 18+ generally handles interoperability well, but conflicts can arise if `send` is configured as ESM-only without CJS fallback.","cause":"Trying to `require()` the `send` package in a CommonJS module when `send` itself might be compiled as an ES Module in newer versions, or vice versa, `import`ing a CJS module in an ESM context without proper handling.","error":"Node.js: `require()` of ES Module ... not supported. Instead change the require to a dynamic import()"}],"ecosystem":"npm"}