基于 Node 实现简易 serve静态资源服务器的示例详解

目录
  • 前言
  • 基础示例
  • 简易 serve 实现
    • arg - 命令行参数读取
    • chalk - 控制台信息输出
    • 源码
  • 扩展
    • rewrite 和 redirect 的区别?

前言

静态资源服务器(HTTP 服务器)可以将静态文件(如 js、css、图片)等通过 HTTP 协议展现给客户端。本文介绍如何基于 Node 实现一个简易的静态资源服务器(类似于 serve)。

基础示例

const fs = require("node:fs");
const fsp = require("node:fs/promises");
const http = require("node:http");

const server = http.createServer(async (req, res) => {
  const stat = await fsp.stat("./index.html");
  res.setHeader("content-length", stat.size);
  fs.createReadStream("./index.html").pipe(res);
});

server.listen(3000, () => {
  console.log("Listening 3000...");
});

在上述示例中,我们创建了一个 http server,并以 stream 的方式返回一个 index.html 文件。其中,分别引入引入了 Node 中的 fs、fsp、http 模块,各个模块的作用如下:

  • fs: 文件系统模块,用于文件读写。
  • fsp: 使用 promise 形式的文件系统模块。
  • http: 用于搭建 HTTP 服务器。

简易 serve 实现

serve 的核心功能非常简单,它以命令行形式指定服务的文件根路径和服务端口,并创建一个 http 服务。

arg - 命令行参数读取

使用 npm 包 arg 读取命令行参数,www.npmjs.com/package/arg

chalk - 控制台信息输出

使用 npm 包 chalk 在控制台输出带有颜色的文字信息,方便调试预览。

源码

// Native - Node built-in module
const fs = require("node:fs");
const fsp = require("node:fs/promises");
const http = require("node:http");
const path = require("node:path");

// Packages
const arg = require("arg");
const chalk = require("chalk");

var config = {
  entry: "",
  rewrites: [],
  redirects: [],
  etag: false,
  cleanUrls: false,
  trailingSlash: false,
  symlink: false,
};

/**
 * eg: --port <string> or --port=<string>
 * node advance.js -p 3000 | node advance.js --port 3000
 */
const args = arg({
  "--port": Number,
  "--entry": String,
  "--rewrite": Boolean,
  "--redirect": Boolean,
  "--etag": Boolean,
  "--cleanUrls": Boolean,
  "--trailingSlash": Boolean,
  "--symlink": Boolean,
});

const resourceNotFound = (response, absolutePath) => {
  response.statusCode = 404;
  fs.createReadStream(path.join("./html", "404.html")).pipe(response);
};

const processDirectory = async (absolutePath) => {
  const newAbsolutePath = path.join(absolutePath, "index.html");

  try {
    const newStat = await fsp.lstat(newAbsolutePath);
    return [newStat, newAbsolutePath];
  } catch (e) {
    return [null, newAbsolutePath];
  }
};

/**
 * @param { http.IncomingMessage } req
 * @param { http.ServerResponse } res
 * @param { config } config
 */
const handler = async (request, response, config) => {
  // 从 request 中获取 pathname
  const pathname = new URL(request.url, `http://${request.headers.host}`)
    .pathname;

  // 获取绝对路径
  let absolutePath = path.resolve(
    config["--entry"] || "",
    path.join(".", pathname)
  );

  let statusCode = 200;
  let fileStat = null;

  // 获取文件状态
  try {
    fileStat = await fsp.lstat(absolutePath);
  } catch (e) {
    // console.log(chalk.red(e));
  }

  if (fileStat?.isDirectory()) {
    [fileStat, absolutePath] = await processDirectory(absolutePath);
  }

  if (fileStat === null) {
    return resourceNotFound(response, absolutePath);
  }

  let headers = {
    "Content-Length": fileStat.size,
  };

  response.writeHead(statusCode, headers);

  fs.createReadStream(absolutePath).pipe(response);
};

const startEndpoint = (port, config) => {
  const server = http.createServer((request, response) => {
    // console.log("request: ", request);
    handler(request, response, config);
  });

  server.on("error", (err) => {
    const { code, port } = err;
    if (code === "EADDRINUSE") {
      console.log(chalk.red(`address already in use [:::${port}]`));
      console.log(chalk.green(`Restart server on [:::${port + 1}]`));
      startEndpoint(port + 1, entry);
      return;
    }
    process.exit(1);
  });

  server.listen(port, () => {
    console.log(chalk.green(`Open http://localhost:${port}`));
  });
};

startEndpoint(args["--port"] || 3000, args);

扩展

rewrite 和 redirect 的区别?

  • rewrite: 重写,是指服务器在接收到客户端的请求后,返回的是别的文件内容。举个例子,浏览器 A 向服务器请求了一个资源 indexA.html,服务器接收到 indexA.html 请求后,拿 indexB.html 作为实际的响应内容返回给浏览器 A,整个过程对于 A 来说是无感知的。
  • redirect: 重定向,浏览器 A 向服务器请求一个 index.html,服务器告诉浏览器 A “资源不在当前请求路径,需要去通过另外一个地址请求”。浏览器接收到新地址后,重新请求。整个过程中,浏览器需要请求两次。

到此这篇关于基于 Node 实现简易 serve(静态资源服务器)的文章就介绍到这了,更多相关node实现静态资源服务器内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • node静态服务器实现静态读取文件或文件夹

    现在我们已经大致了解了node 的基本工作原理,现在来实现一个系统的功能 读取文件或者文件夹 采坑记录 中文输出乱码问题 res.statusCode = 200 res.setHeader('Content-Type', 'text/plain') res.end('啊啊和嘎哈啊') 输出中出现中文乱码 附解决方案 ~ res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' }) 或 res.writeHead(200,

  • 深入理解nodejs搭建静态服务器(实现命令行)

    静态服务器 使用node搭建一个可在任何目录下通过命令启动的一个简单http静态服务器 完整代码链接 安装:npm install yg-server -g 启动:yg-server 可通过以上命令安装,启动,来看一下最终的效果 TODO 创建一个静态服务器 通过yargs来创建命令行工具 处理缓存 处理压缩 初始化 创建目录:mkdir static-server 进入到该目录:cd static-server 初始化项目:npm init 构建文件夹目录结构: 初始化静态服务器 首先在src

  • Nodejs实现的一个静态服务器实例

    参考cnodejs.org上面的静态服务器例子,写了下面的一个nodejs静态服务器例子,里面包含cache,压缩,贴代码如下: 复制代码 代码如下: /**  * 静态文件服务器测试例子  * User: xuwm  * Date: 13-5-17  * Time: 上午8:38  * To change this template use File | Settings | File Templates.  */ var port=3333; var http = require("http

  • Node.js静态文件服务器改进版

    首先还是先感谢github,感谢github上提供此段源码的作者.跟昨晚的来比今天的静态文件服务器有点点复杂些,可以学到很多新的东西. 仔细会发现这次的代码多了一个fs.stat函数和ReadStream对象的pipe函数,stat这个函数是用来获取文件信息.第一个参数是传入文件路径,第二个则是回调函数,回调函数的第二个参数stats的属性为文件的基本信息.pipe函数用于将这个可读流和destination目标可写流连接起来,传入这个流中的数据将会写入到destination流中.通过在必要时

  • 基于 Node 实现简易 serve静态资源服务器的示例详解

    目录 前言 基础示例 简易 serve 实现 arg - 命令行参数读取 chalk - 控制台信息输出 源码 扩展 rewrite 和 redirect 的区别? 前言 静态资源服务器(HTTP 服务器)可以将静态文件(如 js.css.图片)等通过 HTTP 协议展现给客户端.本文介绍如何基于 Node 实现一个简易的静态资源服务器(类似于 serve). 基础示例 const fs = require("node:fs"); const fsp = require("n

  • Linux使用Node.js建立访问静态网页的服务实例详解

    Linux使用Node.js建立访问静态网页的服务实例详解 一.安装node.js运行所需要的环境,:http://www.jb51.net/article/79536.htm 二.创建node目录(/node/www),并在目录下创建node.js服务文件server.js var http = require('http'); var fs = require('fs');//引入文件读取模块 var documentRoot = '/node/www';//需要访问的文件的存放目录 var

  • SpringBoot web静态资源映射实现步骤详解

    目录 静态资源映射规则 自定义静态资源映射规则 静态资源映射规则 “/**” 访问当前项目任何资源,全部找静态资源的文件夹进行映射 静态资源的文件夹包括: "classpath:/META-INF/resources/","classpath:/resources/","classpath:/static/", "classpath:/public/" 静态资源路径下的文件,可以通过地址栏直接访问. 例如:我们在在static

  • 静态pod 创建使用示例详解

    目录 一.系统环境 二.前言 三.静态pod 3.1 何为静态pod 3.2 创建静态pod 3.2.1 使用--pod-manifest-path指定静态pod目录 3.2.2 静态pod默认目录/etc/kubernetes/manifests 一.系统环境 服务器版本 docker软件版本 Kubernetes(k8s)集群版本 CPU架构 CentOS Linux release 7.4.1708 (Core) Docker version 20.10.12 v1.21.9 x86_64

  • PHP基于phpqrcode类生成二维码的方法示例详解

    HP QR Code是一个PHP二维码生成类库,利用它可以轻松生成二维码,官网提供了下载和多个演示demo,查看地址: http://phpqrcode.sourceforge.net/ 下载官网提供的类库后,只需要使用phpqrcode.php就可以生成二维码了,当然您的PHP环境必须开启支持GD2. phpqrcode.php提供了一个关键的png()方法,其中 参数$text表示生成二位的的信息文本: 参数$outfile表示是否输出二维码图片 文件,默认否: 参数$level表示容错率,

  • Promise静态四兄弟实现示例详解

    目录 前言 Promise.all 基础学习 Iterator 接口参数 思路分析 源码实现 Promise.allSettled 基础学习 思路分析 源码实现 Promise.race 基础学习 思路分析 源码实现 Promise.any 基础学习 思路分析 源码实现 前言 恰逢 Promise 也有四个很像的静态三兄弟(Promise.all.Promise.allSettled.Promise.race.Promise.any),它们接受的参数类型相同,但各自逻辑处理不同,它们具体会有什么

  • Golang实现简单http服务器的示例详解

    目录 一.基本描述 二 .具体方法 2.1 连接的建立 2.2 http请求解析 2.3 http请求处理 2.4 http请求响应 三.完整示例 一.基本描述 完成一个http请求的处理和响应,主要有以下几个步骤: 监听端口 建立连接 解析http请求 处理请求 返回http响应 完成上面几个步骤,便能够实现一个简单的http服务器,完成对基本的http请求的处理 二 .具体方法 2.1 连接的建立 go中net包下有提供Listen和Accept两个方法,可以完成连接的建立,可以简单看下示例

  • 基于 angular material theming 机制修改 mat-toolbar 的背景色(示例详解)

    最近在学习 angular,记录一下昨天的进展,解决的问题是通过 theme 的配置修改 mat-toolbar 的背景色,避免对色彩的硬编码. 首先通过 mat-toolbar (以下统一称为 toolbar)的实现源代码 _toolbar-theme.scss 得知背景色来自 theme 中 background palette 的 app-bar. background: theming.get-color-from-palette($background, app-bar); 于是通过下

  • 手写Node静态资源服务器的实现方法

    想写静态资源服务器,首先我们需要知道如何创建一个http服务器,它的原理是什么 http服务器是继承自tcp服务器 http协议是应用层协议,是基于TCP的 http的原理是对请求和响应进行了包装,当客户端连接上来之后先触发connection事件,然后可以多次发送请求,每次请求都会触发request事件 let server = http.createServer(); let url = require('url'); server.on('connection', function (so

  • Node.js动手撸一个静态资源服务器的方法

    简介 本文介绍了一个简单的静态资源服务器的实例项目,希望能给Node.js初学者带来帮助.项目涉及到http.fs.url.path.zlib.process.child_process等模块,涵盖大量常用api:还包括了基于http协议的缓存策略选取.gzip压缩优化等:最终我们会发布到npm上,做成一个可以全局安装.使用的小工具.麻雀虽小,五脏俱全,一想是不是还有点小激动?话不多说,放码过来. 文中源码地址在最后附录中. 可先行体验项目效果: 安装:npm i -g here11 任意文件夹

随机推荐