ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

learnyounode 实战:用 http 模块与 fs.createReadStream 编写 HTTP 文件服务器(http-file-server)

learnyounode 实战:用 http 模块与 fs.createReadStream 编写 HTTP 文件服务器(http-file-server) 教程CLI【免费下载链接】learnyounodeLearn You The Node.js For Much Win! An intro to Node.js via a set of self-guided workshops.项目地址https://gitcode.com/gh_mirrors/le/learnyounode点击查看免费下载本指南围绕 learnyounode 的http_file_server练习展开核心目标是用 Node.js 内置http模块搭建一个 HTTP 服务器将同一个文本文件作为响应体返回给所有请求并要求通过fs.createReadStream()以流式方式完成文件传输。读完本文你将掌握http.createServer()、server.listen()、request/response双流对象以及src.pipe(dst)管道连接的完整用法并能通过 learnyounode 的自动验证流程确认实现的正确性。练习目标一个为所有请求返回同一文件的 HTTP 服务器这一关的任务与之前的 TCP 练习不同需要的是一个真正理解 HTTP 协议的服务器。具体要求来自 exercises/http_file_server/problem.fr.md英文原版见 exercises/http_file_server/problem.md编写一个 HTTP服务器对收到的每个请求都返回同一个文本文件的内容服务器监听第一个命令行参数指定的端口号第二个命令行参数给出要服务的文件完整路径实现时必须使用fs.createReadStream()方法将文件内容以流stream的形式灌入响应。所谓流式是指文件内容不是一次性读入内存再整体发送而是以数据块chunk的方式边读边发。这对于大文件场景能显著降低内存占用也正是本练习希望训练的核心技能。核心 API 剖析http 模块与请求/响应对象http.createServer()创建 HTTP 服务器与net模块的通用 TCP 服务器不同http模块提供的http.createServer()创建的是能够讲 HTTP 协议的服务器。其回调函数在服务器每次收到连接时被调用一次签名如下function callback (request, response) { /* ... */ }两个参数分别代表requestHTTP 请求对象用于获取请求属性例如请求头headers、查询字符串query-string等response响应对象用于向客户端返回数据既包括响应头也包括响应体body。典型的 Node HTTP 服务器骨架如下const http require(http) const server http.createServer(function (req, res) { // 请求处理逻辑…… }) server.listen(8000)http.createServer()返回服务器实例调用server.listen(portNumber)后服务器才开始在指定端口上监听。关键点request 和 response 都是 Node 流文档特别强调request和response本身都是 Node 的流stream对象。这意味着你可以直接使用流式抽象来收发数据——request是可读流可以读取请求体response是可写流可以向客户端写入响应内容。这一特性正是本练习能用pipe把文件流接到响应流的底层基础。关于http模块更完整的离线文档练习指向仓库内自带的 docs-nodejs/http.html。fs.createReadStream 与管道连接把文件流接到响应流fs核心模块提供了一系列面向文件的流式 API。本练习要求使用fs.createReadStream()创建代表命令行参数所给文件的可读流然后通过src.pipe(dst)将src流读出的数据连接到dst流上持续写入。这样一来就可以把文件系统流和 HTTP 响应流直接对接实现零手工处理的流式文件传输。用管道pipe替代读取完整文件 → 写入响应的最大价值在于背压backpressure处理当写入端客户端消费速度跟不上读取端磁盘时pipe会自动暂停源流避免内存被无限积压。这是手写data/write事件容易遗漏的细节。参考实现官方 solution 逐行解读仓库提供的官方答案位于 exercises/http_file_server/solution/solution.js全文如下use strict const http require(http) const fs require(fs) const server http.createServer(function (req, res) { res.writeHead(200, { content-type: text/plain }) fs.createReadStream(process.argv[3]).pipe(res) }) server.listen(Number(process.argv[2]))逐行要点res.writeHead(200, { content-type: text/plain })先写响应状态码与响应头。200表示成功content-type声明返回的是纯文本让客户端知道如何解析。fs.createReadStream(process.argv[3])process.argv中argv[0]是 node 可执行文件、argv[1]是脚本路径因此argv[2]是端口号、argv[3]才是第二个命令行参数——文件路径。.pipe(res)把文件可读流直接接入response可写流文件数据以块为单位自动发送。server.listen(Number(process.argv[2]))用数字类型的端口监听Number()显式转换避免字符串端口带来的隐患。该实现与练习要求完全对应没有引入任何第三方依赖只用了http和fs两个核心模块。自动验证机制练习是如何检查你的代码的了解验证逻辑能帮你写出真正符合要求的代码。验证器实现在 exercises/http_file_server/exercise.js 中验证流程由多个阶段组成1. 准备测试文件与端口const rndtxt require(boganipsum)({ paragraphs: 1, sentenceMax: 1 }) \n const testFile path.join(os.tmpdir(), _learnyounode_ process.pid .txt)addSetup阶段会在系统临时目录生成一个随机的测试文本文件并通过this.submissionPort rndport()分配一个随机端口。端口生成逻辑见 lib/rndport.jsmodule.exports function rndport () { return 1024 Math.floor(Math.random() * 64511) }即端口范围在 1024 到 65535 之间随机选取避开常见特权端口。随后端口号和测试文件路径被unshift进submissionArgs确保你的程序收到的是端口 文件路径两个参数。2. 延迟探测服务器query()函数在addProcessor中被延迟 500ms 调用目的是等待你的服务器启动完成。探测使用hyperquest.get(http://localhost: port)发起真实 HTTP 请求并把响应流req.pipe(stream)导入 stdout 流用于比对req.pipe(stream) setTimeout(function () { stream.unpipe(req) stream.end() }, 5000)如果连接失败例如端口未监听验证器会通过exercise.emit(fail, ...)报告fail.connection错误如果 5 秒后响应仍未结束则强制断开。这也提示我们服务器必须在收到参数后尽快启动监听否则会被判为连接失败。3. 强制校验必须使用 createReadStream这是本练习最关键的约束。addVerifyProcessor检查程序执行期间实际调用的 fs 方法const badCalls Object.keys(exercise.wrapData.fsCalls).filter(function (m) { exercise.emit(fail, exercise.__(fail.no_createReadStream, { method: fs. m () })) return !(/createReadStream/).test(m) }) callback(null, badCalls.length 0)它通过 exercises/my_first_io/wrap.js 预先注入的包装器wrapFsCalls会拦截所有fs方法调用并记录到ctx.fsCalls统计你的主程序到底调用了哪些fs.*方法。任何非createReadStream的 fs 调用都会导致验证失败——这正是仓库中invalid_02.js测试用例所演示的反例require(fs).readFileSync(process.argv[3]) require(http).createServer(function (req, res) { res.writeHead(200, content-type: text/plain) res.end(require(fs).readFileSync(process.argv[3], utf8)) }).listen(process.argv[2] | 0)这段代码用readFileSync一次性读取文件再用res.end()返回功能上也能工作但因为违反了必须用fs.createReadStream()的硬性要求会被判为不通过。对应的通过用例 test/http_file_server/valid_01.js 则使用了fs.createReadStream(process.argv[3]).pipe(res)符合全部要求。可复现的完整解法与运行验证在仓库根目录新建一个文件例如http-file-server.js写入完整解法use strict const http require(http) const fs require(fs) const server http.createServer(function (req, res) { res.writeHead(200, { content-type: text/plain }) fs.createReadStream(process.argv[3]).pipe(res) }) server.listen(Number(process.argv[2]))本地手动测试准备一个文本文件test.txt然后在终端运行$ node http-file-server.js 8000 test.txt服务器启动后用浏览器访问http://localhost:8000/或在另一终端执行$ curl http://localhost:8000/无论请求什么路径都会收到test.txt的完整内容。交给 learnyounode 验证$ learnyounode verify http-file-server.js验证器会启动你的程序发起真实 HTTP 请求将你的响应与官方 solution 的响应做 stdout 比对同时确认你确实使用了fs.createReadStream()。常见踩坑与排查清单端口/文件参数顺序搞反argv[2]是端口argv[3]是文件路径官方 solution 中用Number()转换端口防止字符串端口的隐式行为问题。误用readFileSync/readFile功能正确但违反练习硬性约束addVerifyProcessor会直接判失败参见 test/http_file_server/invalid_02.js。服务器未在 500ms 内启动验证器会报告fail.connection请确认server.listen()是同步执行且在程序顶层调用不要在异步回调里延迟启动。忘记设置响应头虽然本练习的 stdout 比对并不强制content-typeexercise.js 中有TODO: introduce verification of content-type:text/plain and statusCode200的注释说明未来版本可能加入该项校验但设置res.writeHead(200, { content-type: text/plain })是符合 HTTP 语义的规范做法。延伸从本练习看 Node 流的通用模式本练习是 Node 流式编程的最小示范其核心模式——fs.createReadStream(...).pipe(res)——可以推广到任意可读流 → 可写流的组合管道转发、文件复制、日志收集、代理转发等场景都基于同一套pipe抽象。理解了request/response即流这一点后续遇到http_collect用concat-stream收集请求体、juggling_async管理并发 HTTP 请求等练习时会更加得心应手。赞分享教程CLI【免费下载链接】learnyounodeLearn You The Node.js For Much Win! An intro to Node.js via a set of self-guided workshops.项目地址https://gitcode.com/gh_mirrors/le/learnyounode点击查看免费下载相关推荐learnyounode 实战用 Node.js http 模块与 fs.createReadStream 构建 HTTP 文件服务器HTTP FILE SERVERlearnyounode 实战用 Node.js http 模块与 fs.createReadStream 构建 HTTP 文件服务器HTTP FILE S教程CLIlearnyounode 实战使用 http 模块与 fs.createReadStream 编写 HTTP 文件服务器learnyounode 实战使用 http 模块与 fs.createReadStream 编写 HTTP 文件服务器 本篇文章以 learnyounode教程CLIlearnyounode「HTTP FILE SERVER」实战用 http 模块与 fs.createReadStream() 构建流式文件服务器learnyounode「HTTP FILE SERVER」实战用 http 模块与 fs.createReadStream 构建流式文件服务器 导读 本篇以教程CLI上一篇MCP Toolbox 中的 looker-get-project-directories 工具快速探索 LookML 项目目录结构下一篇cookiecutter-django 部署实战Heroku 环境配置、环境变量与生产发布全流程指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表