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.
    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    // 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_right

    
    

  • Step 2: Creating a server at the port specified (say 1800).
    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    // Creating a server and listening the port 1800
    http.createServer( (req, res) => {
      
    }).listen(PORT);

    chevron_right

    
    

  • 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.
    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    // 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_right

    
    

  • Step 4: Preprocessing the requested file pathname to avoid directory traversal (like http://localhost:1800/../fileOutofContext.txt) by replacing ‘../’ with ‘ ’.
    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    /* 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_right

    
    

  • 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.
    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    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_right

    
    

Complete Code:

filter_none

edit
close

play_arrow

link
brightness_4
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


Output



My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.




Article Tags :

Be the First to upvote.


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.