Build a Simple static file web server in Node
In this article, we will build a static file web server which will list out all the files in the directory and on clicking the file name it displays the file content. Steps for creating a static file server is as follows:
- Step 1: Importing necessary modules, and defining MIME types which helps browser to understand the type of file that is being sent.
// Importing necessary modules
const http = require(
'http'
);
const url = require(
'url'
);
const fs = require(
'fs'
);
const path = require(
'path'
);
// Port on which the server will create
const PORT = 1800;
// Maps file extension to MIME types which
// helps the browser to understand what to
// do with the file
const mimeType = {
'.ico'
:
'image/x-icon'
,
'.html'
:
'text/html'
,
'.js'
:
'text/javascript'
,
'.json'
:
'application/json'
,
'.css'
:
'text/css'
,
'.png'
:
'image/png'
,
'.jpg'
:
'image/jpeg'
,
'.wav'
:
'audio/wav'
,
'.mp3'
:
'audio/mpeg'
,
'.svg'
:
'image/svg+xml'
,
'.pdf'
:
'application/pdf'
,
'.doc'
:
'application/msword'
,
'.eot'
:
'appliaction/vnd.ms-fontobject'
,
'.ttf'
:
'aplication/font-sfnt'
};
chevron_rightfilter_none - Step 2: Creating a server at the port specified (say 1800).
// Creating a server and listening the port 1800
http.createServer( (req, res) => {
}).listen(PORT);
chevron_rightfilter_none - Step 3: We will respond the URL “/” to list all the files in the directory. We will limit this article to the current working directory only. Add the below code to the server’s function call.
// Parsing the requested URL
const parsedUrl = url.parse(req.url);
// If requested url is "/" like "http://localhost:8100/"
if
(parsedUrl.pathname===
"/"
) {
var
filesLink=
"<ul>"
;
res.setHeader(
'Content-type'
,
'text/html'
);
var
filesList=fs.readdirSync(
"./"
);
filesList.forEach(element => {
if
(fs.statSync(
"./"
+element).isFile()) {
filesLink +=`<br/><li><a href=
'./${element}'
>
${element}
</a></li>` ;
}
});
filesLink+=
"</ul>"
;
res.end(
"<h1>List of files:</h1> "
+ filesLink);
}
chevron_rightfilter_none - Step 4: Preprocessing the requested file pathname to avoid directory traversal (like http://localhost:1800/../fileOutofContext.txt) by replacing ‘../’ with ‘ ’.
/* processing the requested file pathname to
avoid directory traversal like,
by limiting to the current directory only */
const sanitizePath =
path.normalize(parsedUrl.pathname).replace(/^(\.\.[\/\\])+/,
''
);
let pathname = path.join(__dirname, sanitizePath);
chevron_rightfilter_none - Step 5: Finally, check whether the file exists. If exists then send the file with the proper header ‘Content-type’ having value as per the file extension mapped with the MIME type above. Else if not exist then send File not found! with 404 status code.
if
(!fs.existsSync(pathname)) {
// If the file is not found, return 404
res.statusCode = 404;
res.end(`File ${pathname} not found!`);
}
else
{
// Read file from file system limit to the
// current directory only.
fs.readFile(pathname,
function
(err, data) {
if
(err) {
res.statusCode = 500;
res.end(`Error
in
getting the file.`);
}
else
{
// Based on the URL path, extract the file
// extention. Ex .js, .doc, ...
const ext = path.parse(pathname).ext;
// If the file is found, set Content-type
// and send data
res.setHeader(
'Content-type'
,
mimeType[ext] ||
'text/plain'
);
res.end(data);
}
});
}
chevron_rightfilter_none
Complete Code:
/* Node.js static file web server */ // Importing necessary modules const http = require( 'http' ); const url = require( 'url' ); const fs = require( 'fs' ); const path = require( 'path' ); // Port on which the server will create const PORT = 1800; // Maps file extension to MIME types which // helps browser to understand what to do // with the file const mimeType = { '.ico' : 'image/x-icon' , '.html' : 'text/html' , '.js' : 'text/javascript' , '.json' : 'application/json' , '.css' : 'text/css' , '.png' : 'image/png' , '.jpg' : 'image/jpeg' , '.wav' : 'audio/wav' , '.mp3' : 'audio/mpeg' , '.svg' : 'image/svg+xml' , '.pdf' : 'application/pdf' , '.doc' : 'application/msword' , '.eot' : 'appliaction/vnd.ms-fontobject' , '.ttf' : 'aplication/font-sfnt' }; // Creating a server and listening at port 1800 http.createServer( (req, res) => { // Parsing the requested URL const parsedUrl = url.parse(req.url); // If requested url is "/" like "http://localhost:1800/" if (parsedUrl.pathname=== "/" ){ var filesLink= "<ul>" ; res.setHeader( 'Content-type' , 'text/html' ); var filesList=fs.readdirSync( "./" ); filesList.forEach(element => { if (fs.statSync( "./" +element).isFile()){ filesLink+=`<br/><li><a href= './${element}' > ${element} </a></li>` ; } }); filesLink+= "</ul>" ; res.end( "<h1>List of files:</h1> " + filesLink); } /* Processing the requested file pathname to avoid directory traversal like, by limiting to the current directory only. */ const sanitizePath = path.normalize(parsedUrl.pathname).replace(/^(\.\.[\/\\])+/, '' ); let pathname = path.join(__dirname, sanitizePath); if (!fs.existsSync(pathname)) { // If the file is not found, return 404 res.statusCode = 404; res.end(`File ${pathname} not found!`); } else { // Read file from file system limit to // the current directory only. fs.readFile(pathname, function (err, data) { if (err){ res.statusCode = 500; res.end(`Error in getting the file.`); } else { // Based on the URL path, extract the // file extention. Ex .js, .doc, ... const ext = path.parse(pathname).ext; // If the file is found, set Content-type // and send data res.setHeader( 'Content-type' , mimeType[ext] || 'text/plain' ); res.end(data); } }); } }).listen(PORT); console.log(`Server listening on port ${PORT}`); |
chevron_right
filter_none
Output