snippetjavascriptTip
Create a static file server with Node.js
Viewed 0 times
javascriptfilestaticwithservernodecreate
Problem
One of the simplest beginner backend projects you can create is a static file server. In its simplest form, a static file server will listen for requests and try to match the requested URL to a file on the local filesystem. Here's a minimal example of that in action:
In this code example, we're using the
In theory, one could stop here and have a very basic static file server. However, there are a few considerations that could be taken into account. Let's explore them one by one, and see how we can address them.
First and foremost, we don't necessarily want to serve files from the same directory as our Node.js server. To address this problem, we would have to change the directory
Here's a short code snippet on how to resolve a file path using the
In this code example, we're using the
fs module to read the file at __dirname + req.url. If the file doesn't exist, we'll return a 404 error. Otherwise, we'll return the file. The http module is used to create the server that listens on port 8000.In theory, one could stop here and have a very basic static file server. However, there are a few considerations that could be taken into account. Let's explore them one by one, and see how we can address them.
First and foremost, we don't necessarily want to serve files from the same directory as our Node.js server. To address this problem, we would have to change the directory
fs.readFile() looks for the file in. To accomplish this, we can specify a directory to serve files from and use the path module to resolve files from that directory. This way, we can also better handle different operating systems and environments.Here's a short code snippet on how to resolve a file path using the
path module:Solution
import { readFile } from 'fs';
import { createServer } from 'http';
createServer((req, res) => {
readFile(__dirname + req.url, (err, data) => {
if (err) {
res.writeHead(404, { 'Content-Type': 'text/html' });
res.end('404: File not found');
} else {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(data);
}
});
}).listen(8000);In theory, one could stop here and have a very basic static file server. However, there are a few considerations that could be taken into account. Let's explore them one by one, and see how we can address them.
First and foremost, we don't necessarily want to serve files from the same directory as our Node.js server. To address this problem, we would have to change the directory
fs.readFile() looks for the file in. To accomplish this, we can specify a directory to serve files from and use the path module to resolve files from that directory. This way, we can also better handle different operating systems and environments.Here's a short code snippet on how to resolve a file path using the
path module:Our next concern is security. Obviously, we don't want users prying around our machine unauthorized. Currently, it's not impossible to get access to files outside of the specified root directory (e.g.
GET /../../../). To address this, we can use the path module again to check if the requested file is inside the root directory.Similarly, we can ensure that users don't get access to sensitive files by checking the file type. For this to work, we can specify an array or object of supported file types and check the file's extension using the
path module once again.A staple of most websites is the ability to omit the file extension from the URL when requesting an HTML page. It's a small quality of life improvement that users expect and it would be really nice to add to our static file server.
Code Snippets
import { readFile } from 'fs';
import { createServer } from 'http';
createServer((req, res) => {
readFile(__dirname + req.url, (err, data) => {
if (err) {
res.writeHead(404, { 'Content-Type': 'text/html' });
res.end('404: File not found');
} else {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(data);
}
});
}).listen(8000);import { readFile } from 'fs';
import { join } from 'path';
const directoryName = './public';
const requestUrl = 'index.html';
const filePath = join(directoryName, requestUrl);
readFile(filePath, (err, data) => {
// ...
});import { join, normalize, resolve } from 'path';
const directoryName = './public';
const root = normalize(resolve(directoryName));
const requestUrl = 'index.html';
const filePath = join(root, fileName);
const isPathUnderRoot = normalize(resolve(filePath)).startsWith(root);Context
From 30-seconds-of-code: nodejs-static-file-server
Revisions (0)
No revisions yet.