📌  相关文章
📜  在 Node 中构建一个简单的静态文件 Web 服务器

📅  最后修改于: 2022-05-13 01:56:57.383000             🧑  作者: Mango

在 Node 中构建一个简单的静态文件 Web 服务器

在本文中,我们将构建一个静态文件 Web 服务器,它将列出目录中的所有文件,并在单击文件名时显示文件内容。创建静态文件服务器的步骤如下:

  • 步骤 1:导入必要的模块,并定义 MIME 类型,这有助于浏览器了解正在发送的文件类型。
Javascript
// 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': 'application/vnd.ms-fontobject',
    '.ttf': 'application/font-sfnt'
};


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


Javascript
// Parsing the requested URL
const parsedUrl = url.parse(req.url);
  
// If requested url is "/" like "http://localhost:8100/"
if(parsedUrl.pathname==="/") {
    var filesLink="
    ";     res.setHeader('Content-type', 'text/html');     var filesList=fs.readdirSync("./");           filesList.forEach(element => {         if(fs.statSync("./"+element).isFile()) {             filesLink +=`
  •                 ${element}             
  • ` ;                }     });     filesLink+="
";          res.end("

List of files:

" + filesLink); }


Javascript
/* processing the requested file pathname to
avoid directory traversal like,
http://localhost:1800/../fileOutofContext.txt
by limiting to the current directory only */
const sanitizePath =
path.normalize(parsedUrl.pathname).replace(/^(\.\.[\/\\])+/, '');
 
let pathname = path.join(__dirname, sanitizePath);


Javascript
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
            // extension. 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);
        }
    });
}


Javascript
/* 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': 'application/vnd.ms-fontobject',
    '.ttf': 'application/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="
    ";         res.setHeader('Content-type', 'text/html');         var filesList=fs.readdirSync("./");         filesList.forEach(element => {             if(fs.statSync("./"+element).isFile()){                 filesLink+=`
  •                     ${element}                 
  • ` ;                    }         });                   filesLink+="
";                res.end("

List of files:

" + filesLink);     }        /* Processing the requested file pathname to     avoid directory traversal like,     http://localhost:1800/../fileOutofContext.txt     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 extension. 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}`);


  • 第 2 步:在指定的端口(比如 1800)创建一个服务器。

Javascript

// Creating a server and listening the port 1800
http.createServer( (req, res) => {
 
}).listen(PORT);
  • 步骤3:我们将响应URL“/”以列出目录中的所有文件。我们将把这篇文章限制在当前的工作目录中。将以下代码添加到服务器的函数调用中。

Javascript

// Parsing the requested URL
const parsedUrl = url.parse(req.url);
  
// If requested url is "/" like "http://localhost:8100/"
if(parsedUrl.pathname==="/") {
    var filesLink="
    ";     res.setHeader('Content-type', 'text/html');     var filesList=fs.readdirSync("./");           filesList.forEach(element => {         if(fs.statSync("./"+element).isFile()) {             filesLink +=`
  •                 ${element}             
  • ` ;                }     });     filesLink+="
";          res.end("

List of files:

" + filesLink); }
  • 第 4 步:预处理请求的文件路径名以避免目录遍历(如 http://localhost:1800/../fileOutofContext.txt),将 '../' 替换为 ' '。

Javascript



/* processing the requested file pathname to
avoid directory traversal like,
http://localhost:1800/../fileOutofContext.txt
by limiting to the current directory only */
const sanitizePath =
path.normalize(parsedUrl.pathname).replace(/^(\.\.[\/\\])+/, '');
 
let pathname = path.join(__dirname, sanitizePath);
  • 第五步:最后,检查文件是否存在。如果存在,则根据与上述 MIME 类型映射的文件扩展名发送具有正确标题“内容类型”的文件。否则,如果不存在,则发送找不到文件!带有404状态代码。

Javascript

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
            // extension. 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);
        }
    });
}

完整代码:

Javascript

/* 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': 'application/vnd.ms-fontobject',
    '.ttf': 'application/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="
    ";         res.setHeader('Content-type', 'text/html');         var filesList=fs.readdirSync("./");         filesList.forEach(element => {             if(fs.statSync("./"+element).isFile()){                 filesLink+=`
  •                     ${element}                 
  • ` ;                    }         });                   filesLink+="
";                res.end("

List of files:

" + filesLink);     }        /* Processing the requested file pathname to     avoid directory traversal like,     http://localhost:1800/../fileOutofContext.txt     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 extension. 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}`);

输出