别再用Express了!用Node.js原生HTTP模块装逼的正确姿势

你以为HTTP只是浏览器和服务器的"悄悄话"?其实它是互联网七层模型的顶流!今天就让我们用Node.js,带你从底层TCP"搬砖",一路笑到高阶Web服务上线!🤪


一、互联网七层模型:程序员的"葫芦娃"大冒险

  1. 物理层:网线插好了没?
  2. 数据链路层:小区门禁卡,没它进不去。
  3. 网络层:IP协议,帮你找家门。
  4. 传输层:TCP协议,快递小哥送货上门。
  5. 会话层:敲门打招呼。
  6. 表示层:翻译官,编码解码。
  7. 应用层:HTTP协议,终于能聊天了!

二、用net模块手搓HTTP:体验"原始人"造轮子

代码逐行讲解:tcp-server.js

js 复制代码
const net = require('net') // 引入Node.js原生net模块,负责TCP通信
const server = net.createServer(socket => { // 创建TCP服务器,回调参数是每个客户端连接的socket
  socket.on('data', data => { // 监听客户端发来的数据
    // 判断是否是浏览器的GET请求(只处理根路径)
    if (/^GET \/ HTTP/.test(data.toString())) {
      // 拼接HTTP响应报文,注意:\r\n是协议硬性要求!
      socket.write(
        'HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\n\r\n<h1>你好,TCP原生HTTP!</h1>'
      )
    }
  })
})
server.listen(8080) // 监听8080端口
运行效果

自定义的标头

技术拆解:
  • 直接用TCP监听端口,自己拼HTTP响应报文,体验协议本质。
  • 重点:HTTP响应头和内容之间必须有两个\r\n分隔,否则浏览器直接罢工。
  • 缺点:只能处理最简单的请求,复杂场景下维护地狱。
反面案例:
  • 响应头多一个空格,页面直接404。
  • 换行用\n而不是\r\n,浏览器罢工。

三、http模块登场:优雅的Web服务"自动贩卖机"

代码逐行讲解:http-simple.js

js 复制代码
const http = require('http') // 引入http模块
http.createServer((req, res) => { // 创建HTTP服务器
  // 判断请求头Accept字段,内容协商
  if (req.headers.accept && req.headers.accept.includes('application/json')) {
    res.writeHead(200, {'Content-Type': 'application/json; charset=utf-8'}) // 返回JSON
    res.end(JSON.stringify({msg: '你好,JSON!'}))
  } else {
    res.writeHead(200, {'Content-Type': 'text/html; charset=utf-8'}) // 返回HTML
    res.end('<h1>你好,HTTP模块!</h1>')
  }
}).listen(8080) // 监听8080端口
运行效果

请求头内容为: (所以页面会展示

你好,HTTP模块

)

技术拆解:
  • 自动解析请求,封装响应,开发效率飞升。
  • 内容协商:根据Accept头返回不同格式,前端后端都开心。
  • 细节:一定要加charset=utf-8,否则中文会乱码。

四、静态文件服务:打造属于你的"迷你百度云"

代码逐行讲解:http-static.js(核心片段)

js 复制代码
const http = require('http')
const path = require('path')
const fs = require('fs')
(async () => {
  const mimeModule = await import('mime'); // 动态导入ESM模块
  const server = http.createServer((req, res) => {
    let filePath = path.resolve(__dirname, path.join('www', req.url)) // 解析请求路径,防止目录遍历
    if (fs.existsSync(filePath)) { // 判断文件是否存在
      const stats = fs.statSync(filePath)
      if (stats.isDirectory()) { // 如果是目录,默认返回index.html
        filePath = path.join(filePath, 'index.html')
      }
      const content = fs.readFileSync(filePath) // 读取文件内容
      const { ext } = path.parse(filePath) // 获取文件扩展名
      const contentType = mimeModule.default.getType(ext) || 'text/plain' // 获取MIME类型
      res.writeHead(200, {'Content-Type': contentType}) // 设置响应头
      res.end(content) // 返回文件内容
    } else {
      res.writeHead(404, {'Content-Type': 'text/html; charset=utf-8'}) // 404处理
      res.end('<h1>404 not found</h1>')
    }
  })
  server.listen(8080, () => {
    console.log('server is running at http://127.0.0.1:8080')
  })
})()
运行效果截图:
  • 文件原内容为一个 html 代码页面 能成功识别出文件类型进行相应的解析上传

  • 成功图片文件根据图片文件类型进行识别上传
技术拆解:
  • 路径解析:用path.resolve和path.join防止../目录穿越攻击。
  • MIME类型识别:让图片、CSS、JS都能正常显示。
  • 404处理:用户体验up!
  • ESM模块兼容:用动态import解决require失效。
  • 文件读取:小文件用fs.readFileSync,大文件建议用fs.createReadStream(可扩展)。
反面案例:
  • 不判断目录,访问/返回一堆乱码。
  • 不识别MIME,图片直接变"黑块"。
  • 直接拼接路径,黑客轻松拿下服务器。

五、性能优化与进阶玩法

  • 大文件用fs.createReadStream,内存压力小。
  • 缓存控制:加Cache-Control头,减少重复请求。
  • 目录浏览:递归读取目录,生成文件列表。
  • HTTPS支持:让你的服务更安全。
  • 错误日志:用try/catch捕获异常,避免服务崩溃。

六、互动思考与彩蛋

  • 你能否扩展静态服务器,支持断点续传?
  • 为什么HTTP1.1要引入持久连接?
  • 试试把404页面换成表情包,体验极客幽默!

总结:Node.js HTTP模块不仅是Web开发的敲门砖,更是理解互联网协议的绝佳利器。别怕出错,边学边玩,码农的快乐就是这么简单!🎉

相关推荐
阿幸软件杂货间5 分钟前
【最新版】Edge浏览器(官方版)安装包_Edge浏览器(官方版)安装教程
前端·edge
RaidenLiu14 分钟前
Flutter 状态管理:Provider 入门与实战
前端·flutter
隔壁老王z18 分钟前
设计实现一个Web 终端:基于 Vue 3 和 Xterm.js 的实践
前端·iterm
中微子19 分钟前
简单介绍跨域资源共享(CORS)
前端
極光未晚23 分钟前
Vue 项目 webpack 打包体积分析:从 “盲猜优化” 到 “精准瘦身”
前端·vue.js·性能优化
刘小筛29 分钟前
Ant Design Vue (2x) 按钮(button)单击后离开,按钮状态无变化
前端
mogullzr32 分钟前
4.1.ByteOJ用户模块——登录注册功能(RSA + TimeStamp加密过)
前端·后端
鹏多多.33 分钟前
flutter-使用AnimatedDefaultTextStyle实现文本动画
android·前端·css·flutter·ios·html5·web
卑微前端在线挨打1 小时前
2025数字马力一面面经(社)
前端
OpenTiny社区2 小时前
一文解读“Performance面板”前端性能优化工具基础用法!
前端·性能优化·opentiny