Simple HTTP File Server
The `file-server` package provides a minimalistic HTTP file and directory serving library for Node.js, currently at stable version 2.2.1. It offers a low-level API to create custom file-serving handlers, supporting features like ETag-based caching, configurable `max-age`, and GZIP compression (inferred from package keywords). Updates appear infrequent, suggesting a maintenance-focused cadence rather than active feature development, with the last major update (v2.0.0) removing support for Node.js versions older than 8. Its key differentiators include a callback-based error handling system and explicit control over MIME types and directory access, offering a fundamental building block for custom static file servers rather than an opinionated middleware solution.
Common errors
-
Error: Cannot find module 'file-server'
cause The `file-server` package has not been installed or is not resolvable in the current project context.fixInstall the package using npm: `npm install file-server`. -
TypeError: fileServer.serveFile is not a function
cause This error typically occurs if `FileServer` was not correctly imported or instantiated, leading to `fileServer` being undefined or not an instance of `FileServer`.fixVerify that `const FileServer = require('file-server');` is correctly used and `const fileServer = new FileServer((error, req, res) => {...});` is called before attempting to use its methods. -
Error: Not Found (or 404 in error callback) when serving a directory
cause When using `fileServer.serveDirectory`, a 404 error is returned if a requested file's extension is not explicitly listed in the `mimeTypes` object provided to the `serveDirectory` method.fixUpdate the `mimeTypes` configuration for `serveDirectory` to include the specific file extension and its correct MIME type for the file being requested. -
Error: The "path" argument must be of type string or an instance of Buffer or URL. Received undefined (when using serveDirectory without fileName argument)
cause If `fileServer.serveDirectory(root, mimeTypes)` is called without a `fileName` argument in its returned handler, it expects `request.url` to provide the path. If `request.url` is `undefined` or invalid, this error can occur.fixEnsure that `request.url` is properly populated when passing the handler directly to `http.createServer` or explicitly pass the `filename` argument to the handler: `serveDirectoryHandler(request, response, request.url);`.
Warnings
- breaking Version 2.0.0 removed support for Node.js versions older than 8. Ensure your Node.js environment is version 8 or higher.
- gotcha Error handling is exclusively callback-based. Modern Node.js applications often use Promises or async/await, which are not directly supported for error interception within `file-server`'s API.
- gotcha When using `fileServer.serveDirectory`, the `mimeTypes` argument strictly defines which file extensions are allowed. Requesting a file with an extension not specified in this object will result in a 404 error, even if the file exists.
- gotcha File watchers opened by `file-server` are automatically closed on process exit. However, in scenarios like testing or frequent server restarts within a long-running process, you must manually call `fileServer.close()` to release file handles and prevent resource leaks.
Install
-
npm install file-server -
yarn add file-server -
pnpm add file-server
Imports
- FileServer
import FileServer from 'file-server';
const FileServer = require('file-server');
Quickstart
const FileServer = require('file-server');
const http = require('http');
const path = require('path');
const fs = require('fs');
// Create a dummy file and directory for the example
const tempDir = path.join(__dirname, 'temp-static');
const robotTxtPath = path.join(tempDir, 'robots.txt');
const imagesDir = path.join(tempDir, 'images');
if (!fs.existsSync(tempDir)) fs.mkdirSync(tempDir);
if (!fs.existsSync(imagesDir)) fs.mkdirSync(imagesDir);
fs.writeFileSync(robotTxtPath, 'User-agent: *\nDisallow: /private/', 'utf8');
fs.writeFileSync(path.join(imagesDir, 'test.png'), 'dummy image content', 'utf8'); // In a real scenario, this would be binary
const fileServer = new FileServer((error, request, response) => {
response.statusCode = error.code || 500;
response.end(`Error: ${error.message || 'Internal Server Error'}`);
});
const serveRobots = fileServer.serveFile(robotTxtPath, 'text/plain');
const serveImagesDirectory = fileServer.serveDirectory(imagesDir, {
'.png': 'image/png',
'.jpg': 'image/jpeg'
});
const server = http.createServer((request, response) => {
if (request.url === '/robots.txt') {
serveRobots(request, response);
} else if (request.url.startsWith('/images/')) {
// The serveDirectory method automatically infers filename from request.url if not provided.
serveImagesDirectory(request, response);
} else {
response.statusCode = 404;
response.end('Not Found');
}
});
const PORT = 8080;
server.listen(PORT, () => {
console.log(`File server listening on http://localhost:${PORT}`);
console.log(`Try: http://localhost:${PORT}/robots.txt`);
console.log(`Try: http://localhost:${PORT}/images/test.png`);
}).on('close', () => {
fileServer.close(() => {
console.log('File server watchers closed.');
// Cleanup temporary files/directories after server closes
fs.rmSync(tempDir, { recursive: true, force: true });
});
});
// To stop the server gracefully
// process.on('SIGINT', () => { server.close(); });