教程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 第 8 个练习HTTP 文件服务器对应文档 exercises/http_file_server/problem.zh-cn.md展开讲解如何用 Node.js 核心模块http编写一个每次请求都返回同一文本文件的 HTTP 服务器并强制要求使用fs.createReadStream()以流stream的方式把文件内容管道pipe进响应。读完本文你将掌握http.createServer()的请求-响应模型、request/response的流本质、src.pipe(dst)的流式传输写法以及 learnyounode 的自动校验机制是如何验证你是否真的用了流式 API 的。练习目标参数驱动、流式响应的文件服务器这道题的目标非常聚焦编写一个名为http-file-server.js的脚本实现一个 HTTP 文件服务器把每次收到的请求都响应为同一个文本文件的内容。它与前面基于net模块的 time_server 练习形成对照——本练习要求的是HTTP 服务器而不是通用 TCP 服务器。程序通过两个命令行参数接收配置参数位置含义用法第一个参数process.argv[2]服务器要监听的端口号传给server.listen(portNumber)第二个参数process.argv[3]要返回给客户端的文本文件路径传给fs.createReadStream()原文档特别强调在这一题中你必须使用fs.createReadStream()方法以 stream 的形式作出请求响应。这句话不是建议而是校验的硬性门槛——仓库的验证器会检查你的程序是否只调用了createReadStream这一文件读取 API详见下文验证机制一节。为什么用 http 而不是 net原文档明确指出因为需要创建的是 HTTP 服务而不是普通 TCP 服务所以应使用 Node 核心模块http。它与net模块的关系非常密切net模块提供net.createServer()创建的是基于 TCP 的裸连接服务器适合自定义二进制协议或字节流传输这正是上一题 time_server 的场景http模块提供http.createServer()内部同样建立在 TCP 之上但它额外实现了 HTTP 协议解析能识别请求行、请求头header、查询字符串query-string并能向客户端写出响应头和响应体。因此对返回文件内容给浏览器/客户端这种场景http是正确选择。官方模块文档详见仓库内下载好的 docs-nodejs/http.html。http.createServer 的回调模型http.createServer()接收一个回调函数作为参数服务器每次收到连接/请求时都会调用一次。回调签名固定为function callback (request, response) { /* ... */ }两个参数的含义request代表本次 HTTP 请求的对象用来获取请求的属性例如请求头header和查询字符串query-stringresponse代表本次请求对应的响应对象用来向客户端发送数据既包括响应头headers也包括响应主体body。http.createServer()还会返回一个服务器实例你需要调用server.listen(portNumber)去监听特定端口。一个典型的 Node HTTP 服务器骨架如下来自原文档提示const http require(http) const server http.createServer(function (req, res) { // 处理请求的逻辑... }) server.listen(8000)request 与 response 都是 Node 流这是本练习的核心认知原文档特别强调request和response也都是 Node stream。这意味着你可以用流式处理streaming所抽象的那些方法来实现数据的发送和接收这正是本练习把fs文件流与http响应流对接的底层依据——pipe()方法要求两端都是流而response恰好是可写流Writable可以直接作为pipe的目标。核心写法fs.createReadStream().pipe(res)fs核心模块含有针对文件的流式 API。fs.createReadStream()会为指定的文件创建一个可读流Readable该方法返回的流对象支持src.pipe(dst)语法把数据从src流传输到dst流。用这种形式可以轻松地把一个文件系统的 stream 和一个 HTTP 响应的 stream 连接起来。官方给出的最小接线写法是fs.createReadStream(process.argv[3]).pipe(res)这一行的执行逻辑Node 从磁盘以 chunk数据块形式读取文件每读到一块就立即写入resHTTP 响应全程不需要把整个文件读入内存也不需要手动调用res.end()——当文件流读完并结束end事件时pipe会自动结束响应流客户端收到完整响应体。完整可运行的参考实现仓库的官方解法位于 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]).pipe(res)把第二个参数指定的文件以流的方式灌入响应这是题目强制的核心写法server.listen(Number(process.argv[2]))监听第一个参数给定的端口。注意这里用Number()把字符串参数转成数字因为listen()对端口参数的类型有严格要求。启动方式原文档对应的验证命令{appname}即 learnyounode 命令$ learnyounode verify http-file-server.js也可以先手动运行再测试$ node http-file-server.js 8000 /path/to/file.txt然后用浏览器或curl访问http://localhost:8000查看返回的文件内容。验证机制如何保证你真的用了 createReadStream这道题不允许用把整个文件读进内存再res.end()的笨办法验证逻辑位于 exercises/http_file_server/exercise.js。从源码结构可以还原出完整的校验链路运行期对比练习使用workshopper-exercise/execute以spawn()并行启动你的提交脚本和官方解法测试时通过hyperquest向http://localhost:port发起请求把两者的 stdout 交给comparestdout对比同时设置了longCompareOutput true以应对长行输出见 exercise.js随机端口与临时文件addSetup阶段通过 lib/rndport.js1024 Math.floor(Math.random() * 64511)为提交脚本和解法分别分配端口并在系统临时目录os.tmpdir()写入一个随机生成的测试文本文件把端口和文件路径以命令行参数的形式unshift进子进程参数见 exercise.js核心约束检查addVerifyProcessor阶段通过wrappedexec包装子进程的全局环境收集运行期所有被调用的fs.*()方法记录exercise.wrapData.fsCalls逐一过滤——只要出现任何不是createReadStream的文件读取方法调用就触发fail.no_createReadStream错误并判定失败见 exercise.js。这意味着如果你用fs.readFileSync()或fs.readFile()来实现即使 HTTP 行为完全正确客户端照样能拿到文件内容验证也必然失败。仓库的无效样例正好印证了这一点test/http_file_server/invalid_01.js空文件没有任何服务器实现test/http_file_server/invalid_02.jsreadFileSync读取后res.end()返回功能正确但违背流式要求属于行为对、方法错的典型反例test/http_file_server/invalid_03.js参数取错把端口号当成文件路径且同样使用readFileSync双重错误test/http_file_server/valid_01.js与官方解法一致的流式实现是合法通过的参考。从这些测试用例可以推断learnyounode 的练习设计不仅检验服务器能不能跑通还强制学员养成正确的流式 I/O 思维——这也是本练习放在 Node 入门系列中间位置的用意所在。练习在课程体系中的位置与延伸从仓库的 exercises 目录结构看本练习是网络与流主题链上承前启后的一环前置http_collect如何收集 HTTP 响应数据对照本练习的流式不缓存、time_server基于net的 TCP 服务器与本练习的http服务器形成模块对照后置http_uppercaserer把请求体转大写返回练习 request 这一可读流的读取与回写、http_json_api_server用url模块解析路径并按 JSON 响应。理解了request/response皆为流的本质后续练习中读取请求流 → 变换 → 写回响应流的思路就会水到渠成。更深入的http模块细节可查阅仓库自带的 docs-nodejs/http.html流式文件 API 可查阅 docs-nodejs/fs.html 与 docs-nodejs/stream.html。小结本题的全部要点可以浓缩为三行代码用http.createServer()建 HTTP 服务器用server.listen()绑定第一个参数指定的端口用fs.createReadStream(process.argv[3]).pipe(res)把文件流接入响应流。其背后是两条重要的 Node 心智模型HTTP 响应对象本身就是可写流以及pipe()是连接任意可读流与可写流的标准接插件。通过 learnyounode 的自动化校验文件读取方法白名单 随机端口对比测试这个练习把流式思维从口头概念落实成了可自动验证的硬性代码规范。赞分享教程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点击查看免费下载相关推荐Plano 全链路追踪实战基于 OpenTelemetry 与 W3C Trace Context 的 AI Agent 可观测性指南Plano 全链路追踪实战基于 OpenTelemetry 与 W3C Trace Context 的 AI Agent 可观测性指南 本文以 Plano 的教程CLIlearnyounode 实战用 Node http 模块与 fs.createReadStream 构建 HTTP 文件服务器learnyounode 实战用 Node http 模块与 fs.createReadStream 构建 HTTP 文件服务器 本文基于 learnyoun教程CLIGameDevMind 游戏数据库选型与优化从关系型到 NoSQL 缓存的完整实践指南GameDevMind 游戏数据库选型与优化从关系型到 NoSQL 缓存的完整实践指南 游戏服务器的数据层既要支撑账号、支付、统计等强一致性业务又要服务排行教程CLI上一篇终极macOS清理方案Pearcleaner让磁盘空间翻倍的简单技巧下一篇从源码到应用python-mss开发者贡献指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?