无框架的 Node.js 服务器
本文提供了一个使用纯Node.js构建的简单静态文件服务器,无需使用任何框架。Node.js 的当前状态使得我们所需的大部分功能都由内置 API 提供,只需几行代码即可实现。
示例
使用 Node.js 构建的简单静态文件服务器
js
import * as fs from "node:fs";
import * as http from "node:http";
import * as path from "node:path";
const PORT = 8000;
const MIME_TYPES = {
default: "application/octet-stream",
html: "text/html; charset=UTF-8",
js: "application/javascript",
css: "text/css",
png: "image/png",
jpg: "image/jpg",
gif: "image/gif",
ico: "image/x-icon",
svg: "image/svg+xml",
};
const STATIC_PATH = path.join(process.cwd(), "./static");
const toBool = [() => true, () => false];
const prepareFile = async (url) => {
const paths = [STATIC_PATH, url];
if (url.endsWith("/")) paths.push("index.html");
const filePath = path.join(...paths);
const pathTraversal = !filePath.startsWith(STATIC_PATH);
const exists = await fs.promises.access(filePath).then(...toBool);
const found = !pathTraversal && exists;
const streamPath = found ? filePath : STATIC_PATH + "/404.html";
const ext = path.extname(streamPath).substring(1).toLowerCase();
const stream = fs.createReadStream(streamPath);
return { found, ext, stream };
};
http
.createServer(async (req, res) => {
const file = await prepareFile(req.url);
const statusCode = file.found ? 200 : 404;
const mimeType = MIME_TYPES[file.ext] || MIME_TYPES.default;
res.writeHead(statusCode, { "Content-Type": mimeType });
file.stream.pipe(res);
console.log(`${req.method} ${req.url} ${statusCode}`);
})
.listen(PORT);
console.log(`Server running at http://127.0.0.1:${PORT}/`);
分解
以下几行代码导入 Node.js 的内部模块。
js
import * as fs from "node:fs";
import * as http from "node:http";
import * as path from "node:path";
接下来,我们有一个用于创建服务器的函数。https.createServer
返回一个 Server
对象,我们可以通过监听 PORT
来启动它。
js
http
.createServer((req, res) => {
/* handle http requests */
})
.listen(PORT);
console.log(`Server running at http://127.0.0.1:${PORT}/`);
异步函数 prepareFile
返回以下结构:{ found: boolean, ext: string, stream: ReadableStream }
。如果可以提供文件服务(服务器进程具有访问权限且未发现路径遍历漏洞),我们将返回 HTTP 状态码 200
作为 statusCode
表示成功(否则返回 HTTP 404
)。请注意,其他状态码可以在 http.STATUS_CODES
中找到。对于 404
状态,我们将返回 '/404.html'
文件的内容。
将解析请求文件的扩展名并将其转换为小写。之后,我们将搜索 MIME_TYPES
集合以查找正确的MIME 类型。如果未找到匹配项,我们将使用 application/octet-stream
作为默认类型。
最后,如果没有错误,我们将发送请求的文件。file.stream
将包含一个 Readable
流,该流将被管道传输到 res
(Writable
流的实例)。
js
res.writeHead(statusCode, { "Content-Type": mimeType });
file.stream.pipe(res);