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

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

在 Node.js 中构建一个简单的静态文件 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}`);

输出