Node.js 搭建静态 Web 服务器实战:核心逻辑与代码解析

作者:终端旅客时间:2026-10-30 05:03:13浏览:183

本文详解如何使用Node.js搭建一个具备完整功能的静态Web服务器。通过整合http、url、fs和path模块,实现HTML页面展示、JS/CSS等静态资源直接访问、图片显示及二进制文件下载。重点解析中文路径解码、目录索引生成以及非斜杠路径的301重定向逻辑,提供约140行核心代码及运行指南。

Node.js Web服务器搭建概述

利用Node.js构建Web服务器是掌握该技术的综合性入门实践。实现一个基础的Web服务器涉及多个关键模块的应用,包括处理HTTP协议的模块、文件系统操作、URL解析、路径处理以及301重定向机制。下文将简要阐述搭建简易Web服务器的具体步骤。

Web服务器核心功能需求

一个合格的Web服务器需要满足以下基本功能需求:

1、支持渲染以.html或.htm为后缀的Web页面;

2、直接输出以.js、.css、.json或.text为后缀的文件内容;

3、正确展示图片资源;

4、自动触发以.apk、.docx或.zip为后缀的文件下载;

5、当访问路径形如http://xxx.com/a/b/时,系统应优先查找b目录下是否存在index.html文件。若存在则直接显示;若不存在,则列出该目录下的所有文件和文件夹,并允许用户进一步访问子目录或文件。

6、当访问路径形如http://xxx.com/a/b(无末尾斜杠)时,执行301重定向至http://xxx.com/a/b/。此举旨在解决内部资源引用路径错位的问题。

首先引入实现上述功能所需的各个模块:

关键模块引入


//http协议模块
var http = require('http');
//url解析模块
var url = require('url');
//文件系统模块
var fs = require("fs");
//路径解析模块
var path = require("path");

创建HTTP服务并在指定端口进行监听:

服务创建与端口监听


//创建一个服务
var httpServer = http.createServer(this.processRequest.bind(this));

//在指定的端口监听服务
httpServer.listen(port,function(){
  console.log("[HttpServer][Start]","runing at http://"+ip+":"+port+"/");
  console.timeEnd("[HttpServer][Start]");
});

在服务创建过程中,需传递一个名为processRequest的匿名函数以处理请求。该函数接收两个参数:request和response。request对象封装了客户端请求的所有信息,而response对象用于设置响应头并向客户端返回数据。

请求处理逻辑详解


processRequest:function(request,response){
  var hasExt = true;
  var requestUrl = request.url;
  var pathName = url.parse(requestUrl).pathname;

  //对请求的路径进行解码,防止中文乱码
  pathName = decodeURI(pathName);

  //如果路径中没有扩展名
  if(path.extname(pathName) === ''){
    //如果不是以/结尾的,加/并作301重定向
    if (pathName.charAt(pathName.length-1) != "/"){
      pathName += "/";
      var redirect = "http://"+request.headers.host + pathName;
      response.writeHead(301, {
        location:redirect
      });
      response.end();
    }
    //添加默认的访问页面,但这个页面不一定存在,后面会处理
    pathName += "index.html";
    hasExt = false; //标记默认页面是程序自动添加的
  }

  //获取资源文件的相对路径
  var filePath = path.join("http/webroot",pathName);

  //获取对应文件的文档类型
  var contentType = this.getContentType(filePath);

  //如果文件名存在
  fs.exists(filePath,function(exists){
    if(exists){
      response.writeHead(200, {"content-type":contentType});
      var stream = fs.createReadStream(filePath,{flags:"r",encoding:null});
      stream.on("error", function() {
        response.writeHead(500,{"content-type": "text/html"});
        response.end("<h1>500 Server Error</h1>");
      });
      //返回文件内容
      stream.pipe(response);
    }else { //文件名不存在的情况
      if(hasExt){
        //如果这个文件不是程序自动添加的,直接返回404
        response.writeHead(404, {"content-type": "text/html"});
        response.end("<h1>404 Not Found</h1>");
      }else {
        //如果文件是程序自动添加的且不存在,则表示用户希望访问的是该目录下的文件列表
        var html = "<head><meta charset='utf-8'></head>";

        try{
          //用户访问目录
          var filedir = filePath.substring(0,filePath.lastIndexOf('\\'));
          //获取用户访问路径下的文件列表
          var files = fs.readdirSync(filedir);
          //将访问路径下的所以文件一一列举出来,并添加超链接,以便用户进一步访问
          for(var i in files){
            var filename = files[i];
            html += "<div><a href='"+filename+"'>"+filename+"</a></div>";
          }
        }catch (e){
          html += "<h1>您访问的目录不存在</h1>"
        }
        response.writeHead(200, {"content-type": "text/html"});
        response.end(html);
      }
    }
  });
},

在请求处理函数中,有几个关键逻辑需要特别注意:

针对路径中包含中文的情况,浏览器会自动对中文进行编码(英文字符保持不变)。因此,在接收到请求地址后,必须对路径进行解码处理,否则解析出的路径将与实际文件路径不一致。

若访问路径既不以具体文件后缀结尾,也不以斜杠/结尾,则需通过重定向添加末尾斜杠,以标识当前目录。若不进行此处理,当前路径下的静态资源可能无法被正确引用。

当访问路径指向一个目录时,系统应列出该目录下的所有文件和文件夹供用户点击访问。为确保中文目录名能正常显示,需在响应头中设置charset=utf-8。

代码获取与运行指南

核心代码量约为140行左右,完整代码已托管至Git仓库:https://github.com/git-onepixel/Node

如需运行演示Demo,请打开命令行工具(cmd)并切换至项目根目录,执行命令node start即可启动服务。

以上内容即为本文的全部讲解,希望对读者的学习有所帮助。

作者最新文章