Skip to content

Express 概述(Day10 1/3) ​

本页对应 Day10_Node,共 7 段视频,约 1 小时 43 分。

学习目标 ​

  • 能够独立使用 Node.js http 模块创建并启动 HTTP 服务,在回调中读取请求 URL、请求方式、请求体,设置状态码、响应头并结束响应。
  • 能够从用途、请求体、安全性、数据长度限制四个维度准确说明 GET 与 POST 的区别,并能结合示例判断应选择哪种请求方式。
  • 能够基于 URL 路径与服务器静态资源目录的映射关系,使用 fs、path、url 模块实现静态文件托管,并处理 404、500、中文路径解码及 Content-Type/MIME 类型设置。
  • 能够完成 npm 项目初始化并安装 Express,使用 express() 创建 HTTP 服务并通过 listen 启动服务。
  • 能够使用 app.get、app.post 编写简单路由,根据请求路径和请求方式返回不同响应,并使用 res.send、res.sendFile 完成响应。
  • 能够对比原生 http 与 Express 在创建服务、路由处理和静态资源托管上的实现差异,并说明 Express 封装带来的简化。

知识点 ​

从 HTTP 服务三件事讲起 ​

为什么需要:后面用 Express 之前,必须先知道原生 HTTP 服务到底替我们做了什么。转写里把昨天内容总结为三部分:创建服务、启动服务、在请求回调里取请求数据并组织响应。

怎么想:创建服务用 http.createServer,它返回服务对象;启动服务调用 listen 指定端口;createServer 的回调会在收到客户端请求时执行,并自动拿到请求对象 req 和响应对象 res。取数据包括客户端 IP、请求方式、URL、请求体;响应则包括状态码、响应头、响应体。

怎么做:

js
const http = require('http');
const server = http.createServer((req, res) => {
  // req.url、req.method 等
  res.end('ok');
});
server.listen(8080, () => {
  console.log('HTTP server running on 8080');
});

易错点:res.end() 表示结束响应,不写浏览器会一直转圈;请求体本质是读取流,POST 请求要一点点取再拼接;GET 请求常见数据在 URL 查询字符串里。

GET 与 POST 的区别 ​

为什么需要:这是面试和开发都常见的问题,也决定表单、接口怎么传数据。

怎么想:一般 GET 用于向服务器请求数据,POST 用于向服务器提交数据;GET 请求报文一般没有请求体,POST 有请求体;GET 通过 URL 查询字符串传数据,完全可见,POST 放在请求体里默认不可见,所以一般认为 POST 更安全;GET 受 URL 长度限制,约 2K 到 4K,POST 理论上没有这个容量限制。

怎么做:表单 method 不写或写 get,会把输入项拼成查询字符串;写 post 才把数据放进请求体。服务端解析 GET 用 URL 的查询串,解析 POST 要读请求体流。

易错点:POST 只是“更安全”,不是绝对安全;用抓包工具仍可能看到请求体;GET 也能传少量数据,不要把它理解成完全不能传。

初步实现静态文件托管 ​

为什么需要:前端写的 HTML、CSS、图片、视频要能被浏览器请求到,后端就要提供静态文件服务。

怎么想:所谓“静态”是从服务器角度看的——服务器不执行 HTML 里的代码,只把文件内容搬运给浏览器。最直观方案是拿到 URL 的 pathname,用 switch case 判断不同路径,再读对应文件。

怎么做:用 url.parse(req.url) 拿 pathname,根据路径读 public 下的文件:

js
const url = require('url');
const fs = require('fs');
const path = require('path');

const pathname = url.parse(req.url).pathname;
switch (pathname) {
  case '/':
  case '/index.html':
    fs.readFile(path.resolve(__dirname, 'public/index.html'), (err, data) => {
      if (err) { res.statusCode = 500; return res.end('500'); }
      res.end(data);
    });
    break;
  default:
    res.statusCode = 404;
    res.setHeader('Content-Type', 'text/html; charset=utf-8');
    res.end('<h1>您访问的页面不存在</h1>');
}

调试过程:访问首页后样式没了,打开 Network 发现浏览器解析 HTML 后还会继续请求 CSS、图片、视频等资源;每个资源都是新请求。若每个路径都写 case,文件一多就维护不了。

易错点:path.resolve 拼路径时,如果 pathname 以 / 开头,会被当成根目录,前面拼的 public 可能失效;此时可用 path.join,或去掉开头斜杠。

完整静态资源托管:拼接、解码与 MIME ​

为什么需要:不能为每个静态文件写一个 case。转写里的关键发现是:URL 路径和 public 目录结构可以对应起来,直接把 pathname 拼到静态目录后面即可。

怎么做:

js
const filename = path.join(__dirname, 'public', pathname);
fs.access(filename, (err) => {
  if (err) {
    res.statusCode = 404;
    return res.end('404 Not Found');
  }
  fs.readFile(filename, (err, data) => {
    if (err) {
      res.statusCode = 500;
      return res.end('500');
    }
    res.end(data);
  });
});

中文路径问题:浏览器会自动对中文路径编码,服务端按编码后的名字找不到文件,所以要用 decodeURI(filename) 解码。注意不要提前 res.end(),否则异步读文件还没回调,响应已结束。

MIME 类型:响应头应设置 Content-Type,告诉浏览器内容类型。转写中用 mimes.json 按扩展名取 MIME,取不到就给空,让浏览器自行识别。扩展名可用 pathname.lastIndexOf('.') 配合 slice 获取。

Express 介绍、安装与创建服务 ​

为什么需要:原生写路由、读文件、设置响应头较繁琐,Express 是 Node 的 Web 开发框架,封装了 HTTP 服务创建、请求响应处理和路由。

怎么做:先 npm init -y,再 npm i express。创建服务:

js
const express = require('express');
const app = express();
app.get('/', (req, res) => {
  res.send('欢迎访问本网站');
});
app.listen(8080, () => {
  console.log('HTTP server running on 8080');
});

易错点:Express 不再像原生 HTTP 那样统一写一个 createServer 回调,而是用路由方法匹配;res.send 会自动补 Content-Type,中文一般不再乱码。

Express 简单路由演示 ​

为什么需要:不同路径、不同请求方式要返回不同内容,这就是路由。

怎么做:app.get('/login', ...) 处理 GET 登录页,app.post('/login', ...) 处理 POST 提交;res.sendFile 可直接发送文件,内部处理读取失败等情况。路径仍建议用 path.resolve(__dirname, ...) 拼绝对路径。

js
app.get('/login', (req, res) => {
  res.sendFile(path.resolve(__dirname, 'public/login.html'));
});
app.post('/login', (req, res) => {
  res.send('<h2>表单提交成功</h2>');
});

易错点:只写 app.get 时,POST 到同一路径不会进入该回调;方法名对应请求方式,路径对应匹配规则。调试时先启动服务,再用浏览器 Network 看请求是否发出、命中哪个路由。

一、HTTP 服务:创建、启动、取请求与做响应 ​

为什么需要: 后端要能接收浏览器请求,并按照请求内容返回数据;不掌握 http 模块,就不知道请求报文、响应报文和路由判断的底层流程。
怎么想: 转写稿把 HTTP 服务总结为三部分:创建服务、启动服务、在回调里处理请求和响应。createServer 的回调会在接收到请求时执行,Node 会管理并发请求;请求对象用来取数据,响应对象用来组响应。
怎么做:

js
const http = require('http');
const server = http.createServer((req, res) => {
  // req:取请求数据;res:设置响应
});
server.listen(8080, () => console.log('HTTP server is running on 8080'));

从请求中可取客户端 IP、请求方式 method、URL、请求体;URL 后的查询字符串可用 url 模块解析。POST 请求体本质是读取流,要监听 data 和 end 拼接。响应可设置 statusCode、statusMessage、setHeader,用 write 写响应体,最后必须 end。
易错点: listen 的回调是“启动成功”执行,不是“收到请求”执行;不写 res.end() 浏览器会一直转圈;状态码不要乱写,要按规范;请求体是流,不能当成普通字符串直接取。

二、GET 与 POST 的区别 ​

为什么需要: 这是常见面试题,也决定数据放在 URL 还是请求体里。
怎么想: 转写稿总结四点:GET 一般用于从服务器获取数据,POST 一般用于向服务器提交数据;GET 请求报文一般没有请求体,POST 一般有请求体;GET 通过 URL 查询字符串传数据,默认可见,POST 放请求体里,默认不可见,所以一般认为更安全;GET 传数据受 URL 长度限制,约 2K 到 4K,POST 理论上没有容量限制。
怎么做: 已学手段里,GET 可直接在地址栏写查询字符串,表单 method 不写或写 GET 也会拼查询字符串;POST 可用表单 method="post" 提交,服务端从请求体流里取数据。
易错点: POST 不是绝对安全,只是默认不可见,抓包仍可能看到;GET 也能提交少量数据;POST 理论无限制但受底层 HTTP/TCP 等限制;不要只会背四点,要理解“一般用于”的规范含义。

三、静态资源托管:从 switch-case 到路径拼接 ​

为什么需要: 浏览器请求 HTML 时会继续请求 CSS、JS、图片、视频和 favicon,若只给几个路径写 switch-case,请求一多就维护不了。
怎么想: 转写稿的调试过程很关键:最初用 switch-case 判断 /index.html、/learn.html、/videos.html,但浏览器解析 HTML 后会再发 CSS、JS、图片请求,全部 404。后来发现 URL 中的路径可以和 public 目录结构对应,直接把 pathname 拼到 public 后面即可。
怎么做:

js
const pathname = decodeURI(url.parse(req.url).pathname);
const filePath = path.join(__dirname, 'public', pathname);

fs.access(filePath, (err) => {
  if (err) {
    res.statusCode = 404;
    res.setHeader('Content-Type', 'text/html; charset=utf-8');
    return res.end('您访问的页面不存在');
  }
  fs.readFile(filePath, (err, data) => {
    if (err) {
      res.statusCode = 500;
      return res.end('服务器发生未知错误');
    }
    res.end(data);
  });
});

易错点: 转写稿踩过 path.resolve(__dirname, 'public', pathname) 的坑:pathname 以 / 开头时会被当成根目录,前面拼的全废;应改用 path.join。异步 readFile 没执行完不能在外层 end,否则响应提前结束。中文路径浏览器会自动编码,服务端要 decodeURI。文件不存在返回 404,读取失败返回 500。

四、MIME 类型与中文路径 ​

为什么需要: 响应头 Content-Type 要告诉浏览器返回的是什么类型;不设置时浏览器可能自动识别,但 favicon 等文件可能识别不了而被下载。
怎么想: 转写稿用 mimes.json 保存“扩展名 → MIME 类型”的对应关系,根据文件扩展名取 MIME;扩展名可从最后一个点后截取,找不到时给空字符串,让浏览器自行处理。
怎么做:

js
const mimes = require('./mimes.json');
const ext = path.extname(pathname).slice(1);
res.setHeader('Content-Type', mimes[ext] || '');

易错点: path.extname 带点,mimes 的键通常不带点,要 slice(1);找不到 MIME 不要设成 undefined;中文路径要解码;浏览器会自动请求 /favicon.ico,这是正常现象。

五、Express:封装后的 HTTP 服务与路由 ​

为什么需要: 原生 http 写路径判断、静态托管、中文解码、MIME 很繁琐;Express 是第三方 Web 框架,封装了创建服务、拆请求、组响应和路由。
怎么想: 先 npm init -y 生成 package.json,再 npm i express。express() 返回值就是服务对象,用 app.get('/')、app.post('/login') 按“请求方式 + 路径”匹配;res.send 会自动加 Content-Type,中文不乱码;res.sendFile 内置读取文件,失败会自动处理。
怎么做:

js
const express = require('express');
const path = require('path');
const app = express();

app.get('/', (req, res) => res.send('欢迎访问本网站'));
app.get('/login', (req, res) => {
  res.sendFile(path.resolve(__dirname, 'public/login.html'));
});
app.post('/login', (req, res) => res.send('<h2>表单提交成功</h2>'));

app.listen(8080, () => console.log('HTTP server is running on 8080'));

易错点: 先初始化项目再安装;app.get('/') 只处理根路径,不是所有路径;POST 要写 app.post,否则 GET 路由接不到;sendFile 的路径最好用 path.resolve(__dirname, ...),避免受命令行位置影响;res.send 与 res.end 类似,但前者会自动补响应头。

从原生 HTTP 服务复习切入:Express 到底解决什么问题 ​

为什么需要:上一节用 Node 内置 http 模块写服务,虽然能跑,但步骤多、判断多。创建服务要 http.createServer,启动要 server.listen;请求对象里要取 IP、method、URL、请求体;响应对象里要设状态码、响应头、响应体;路径不同要 switch(pathname),请求方式不同还要再判断。静态资源托管更麻烦:要拼路径、判断文件是否存在、读文件、处理中文路径编码、设置 MIME 类型。代码一多,业务逻辑还没写,底层处理已经占满篇幅。

怎么想:Express 是 Node.js 平台上一个快速、极简的 Web 开发框架,属于第三方模块。它把“创建 HTTP 服务、拆解请求报文、组织响应报文、路由分发、静态资源托管”等操作做了封装。学它不是为了否定原生 HTTP,而是先理解底层流程,再用封装提高开发效率。转写稿里说得很直白:过去二十行代码,用 Express 可能五六行就完成。

怎么做:先初始化项目,再安装 Express。因为它是第三方包,需要 package.json 管理依赖。

bash
npm init -y
npm install express

易错点:包名不能用中文;安装前最好先 npm init -y 生成 package.json,虽然安装时也会自动生成,但信息不完整;Express 属于产品依赖,不是开发依赖。

用 Express 创建 HTTP 服务 ​

为什么需要:原生写法要导入 http 模块,再调 createServer,还要在回调函数里统一处理所有请求。Express 把创建服务这一步简化了。

怎么想:express 模块导出的是一个函数,直接调用就能得到服务对象,通常命名为 app。启动服务仍然用 listen,端口号和回调函数与原生类似。

怎么做:

js
const express = require('express');
const app = express();

app.listen(8080, () => {
  console.log('HTTP server is running on 8080');
});

易错点:这段代码启动后访问 http://localhost:8080 会显示 Cannot GET /,因为 Express 没有像原生 createServer 那样统一写一个请求回调,而是用“路由”处理请求。没有匹配的路由,就不会返回业务内容。另外,listen 不要误写成 lason 之类的同音错误。

简单路由:用方法名区分请求方式 ​

为什么需要:原生写法里,路径不同要判断 pathname,请求方式不同还要判断 method,典型就是 switch case。Express 把“请求方式 + 路径”直接做成方法,代码更直观。

怎么想:app.get(path, callback) 表示只处理 GET 请求;app.post(path, callback) 表示只处理 POST 请求。路径匹配后执行回调,回调仍然能拿到 req 和 res。响应时可以用 res.send,它比原生 res.end 多做了自动设置 Content-Type 的工作,所以直接写中文也不容易乱码。

怎么做:

js
const express = require('express');
const path = require('path');
const app = express();

app.get('/', (req, res) => {
  res.send('欢迎访问本网站');
});

app.get('/login', (req, res) => {
  res.sendFile(path.resolve(__dirname, './public/login.html'));
});

app.post('/login', (req, res) => {
  res.send('<h2>表单提交成功</h2>');
});

app.listen(8080, () => {
  console.log('HTTP server is running on 8080');
});

易错点:GET 和 POST 要分别写路由,只写 app.get('/login') 时,表单以 POST 提交是匹配不到的;res.sendFile 虽然内置了文件读取,但路径建议用 path.resolve(__dirname, ...) 拼成绝对路径,避免命令行工作目录变化导致找不到文件;res.send 和 res.end 功能相似但不要混用错方法名。

从静态资源托管看 Express 的封装价值 ​

为什么需要:转写稿里花了很多篇幅实现静态资源托管:根据 URL 的 pathname 拼服务器文件路径,用 fs.access 判断文件是否存在,用 fs.readFile 读取内容,还要处理中文路径被浏览器自动编码的问题,最后根据扩展名设置 MIME 类型。真实开发中如果每个静态文件都写 case,文件一多就维护不下去。

怎么想:Express 对这些重复操作做了封装。虽然本节演示重点是创建服务和简单路由,但要知道:原生阶段我们是在理解“请求路径如何映射到服务器文件”“响应头如何告诉浏览器内容类型”;Express 则把这些能力变成更少的代码。先学原生再学框架,才不会“空中楼阁”。

怎么做:本节先掌握 Express 的安装、创建服务、app.get/app.post 路由和 res.send/res.sendFile 的基本用法。静态资源托管的完整封装可以后续展开。

易错点:不要因为 Express 简单就跳过原生 HTTP;路由路径要写清楚,/ 和 /login 是两个不同匹配;res.send 自动设置响应头是便利,但遇到特殊内容类型仍要理解 MIME 类型的意义。

课堂画面 ​

课堂画面 1

课堂画面 2

课堂画面 3

课堂画面 4

课堂画面 5

课堂画面 6

代码示例 ​

示例一:原生 HTTP 实现静态资源托管(含 MIME 类型、中文路径、404/500) ​

目录结构:public/(放 index.html、css、图片等)、mimes.json、01-静态资源托管.js

json
// mimes.json —— 扩展名 => MIME 类型(可自行增删)
{
  "html": "text/html",
  "css": "text/css",
  "js": "application/javascript",
  "png": "image/png",
  "jpg": "image/jpeg",
  "jpeg": "image/jpeg",
  "gif": "image/gif",
  "ico": "image/x-icon",
  "mp4": "video/mp4",
  "mp3": "audio/mpeg"
}
js
// 01-静态资源托管.js
const http = require('http');
const fs = require('fs');
const path = require('path');
const mimes = require('./mimes.json'); // 自定义模块:json 引入后直接就是对象

const server = http.createServer((req, res) => {
  // 1. 从 URL 中取路径名(忽略查询字符串等干扰因素)
  const { pathname } = new URL(req.url, 'http://localhost');

  // 2. 浏览器会对中文路径自动编码,服务端需要解码,否则找不到文件
  const filePath = decodeURI(pathname);

  // 3. 拼接静态资源在服务器上的绝对路径(用 join,别用 resolve)
  const fileName = path.join(__dirname, 'public', filePath);

  // 4. 判断文件是否存在
  fs.access(fileName, (err) => {
    if (err) {
      res.statusCode = 404;
      res.setHeader('Content-Type', 'text/html;charset=utf-8');
      res.end('<h1>404 您访问的页面不存在</h1>');
      return;
    }

    // 5. 读取文件,读到的 data 是 Buffer,直接响应即可
    fs.readFile(fileName, (err, data) => {
      if (err) {
        res.statusCode = 500;
        res.setHeader('Content-Type', 'text/html;charset=utf-8');
        res.end('<h1>500 服务器发生未知错误</h1>');
        return;
      }

      // 6. 根据扩展名设置 Content-Type(MIME 类型)
      const index = fileName.lastIndexOf('.');
      const ext = fileName.slice(index + 1); // 不要前面的点
      const type = mimes[ext] || '';          // 查不到给空,让浏览器自己识别
      if (type) res.setHeader('Content-Type', type);

      res.end(data); // Buffer 直接给浏览器,效率更高
    });
  });
});

server.listen(8080, () => {
  console.log('HTTP server is running on 8080');
});

关键行与易错点

  • path.join(__dirname, 'public', filePath):pathname 以 / 开头,若用 path.resolve,这个 / 会被当成根目录,把前面的 __dirname 和 public 全部丢掉,拼成 D:\index.html 这种错误路径。join 是机械拼接,不会跳根。
  • decodeURI(pathname):浏览器会对中文文件名自动编码(如 js高级.png),不解码就 fs.access 找不到,表现为图片 404。
  • fs.access 先判断存在性 → 不存在给 404;fs.readFile 失败给 500。顺序不能颠倒。
  • res.end() 必须写在异步回调里:fs.readFile 是异步的,如果在外面提前 res.end(),浏览器收到空响应,回调里再写就会报错。
  • 扩展名取值用 lastIndexOf('.'),取最后一个点;slice(index + 1) 顺带把点去掉,因为 mimes.json 的属性名没有点。
  • mimes[ext] 查不到是 undefined,如果直接 setHeader('Content-Type', undefined) 会报错,所以要 || '' 并加 if (type)。
  • 一个 HTML 页面里的 CSS、JS、图片,浏览器解析后会再发起多次请求,所以服务端必须按路径全部能响应,这也是要用“拼接路径”而不是 switch case 的原因。

示例二:Express 创建 HTTP 服务(send 自动加响应头) ​

js
// 02-express创建服务.js
const express = require('express'); // 第三方模块,需先 npm i express
const app = express();              // 调用 express() 得到服务对象

app.get('/', (req, res) => {
  // express 的 res.send 在 end 的基础上自动添加 Content-Type,中文不乱码
  res.send('欢迎访问本网站');
});

app.listen(8080, () => {
  console.log('HTTP server is running on 8080');
});

关键行与易错点

  • 使用前要先 npm init -y 生成 package.json,再 npm i express;express 是产品依赖。
  • 不需要再 require('http'),express() 返回值就是创建好的服务,app.listen() 启动。
  • 和原生 http.createServer 不同,这里没有统一接收请求的回调,请求由后面的“路由”分别处理;没写路由的路径默认返回 Cannot GET /xxx。
  • res.send() ≈ res.end() + 自动设置 Content-Type,所以写中文不会乱码;原生 res.end() 写中文必须自己 setHeader('Content-Type','text/html;charset=utf-8')。

示例三:Express 简单路由(get/post 区分 + sendFile) ​

public/login.html:

html
<form action="/login" method="post">
  用户名:<input type="text" name="username"><br>
  密码:<input type="password" name="password"><br>
  <button type="submit">登录</button>
</form>
js
// 03-简单路由演示.js
const express = require('express');
const path = require('path');
const app = express();

// GET / :响应首页
app.get('/', (req, res) => {
  res.send(`
    <h1>首页</h1>
    <a href="/login">登录</a>
  `);
});

// GET /login :把静态页面发给浏览器
app.get('/login', (req, res) => {
  // sendFile 内置 fs,读取失败会自动返回 404,不用自己判断
  res.sendFile(path.resolve(__dirname, 'public/login.html'));
});

// POST /login :同一个路径,用请求方式区分处理
app.post('/login', (req, res) => {
  res.send('<h2>表单提交成功</h2>');
});

app.listen(8080, () => {
  console.log('HTTP server is running on 8080');
});

关键行与易错点

  • app.get(路径, 回调) / app.post(路径, 回调):方法名即请求方式,路径相同、方式不同可以各写一份,等价于原生里判断 req.method + pathname,但代码量少得多。
  • 只写了 app.get('/login') 时,表单 method="post" 提交会匹配不上(表现为 404 / Cannot POST),必须补 app.post('/login')。
  • res.sendFile() 用绝对路径最稳,所以 path.resolve(__dirname, 'public/login.html');直接写相对路径会基于启动命令时所在的目录,换目录就找不到文件。
  • res.send() 里可以用模板字符串换行写 HTML,浏览器正常解析。
  • app.get('/') 只匹配根路径,写其他路径访问不到该处理函数。

常见错误 ​

  • 现象:访问静态页面时样式、图片全 404。
    原因:只处理了 HTML 路径,未按 URL 路径映射静态资源目录,或路径拼接错误。
    修法:统一用请求路径映射到静态目录,检查 path.join/sendFile 的实际路径。

  • 现象:静态资源路径拼成了盘符根目录,文件找不到。
    原因:用 path.resolve 拼接以 / 开头的 pathname,导致前面的目录被覆盖。
    修法:去掉开头的 /,或改用 path.join 拼接静态目录与请求路径。

  • 现象:中文文件名图片/资源请求 404。
    原因:浏览器对中文路径自动编码,服务端未解码。
    修法:对路径执行 decodeURI 后再拼接、查找文件。

  • 现象:响应提前结束,文件内容没返回,浏览器一直转圈或空响应。
    原因:异步读文件回调尚未执行就调用了 res.end()。
    修法:把 res.end()/res.send() 放到读取成功回调里,失败分支单独返回 404/500。

  • 现象:表单 POST 到登录路径无响应。
    原因:只写了 app.get('/login', ...),POST 请求不会进入该处理函数。
    修法:按请求方式注册路由,如 app.post('/login', ...),GET/POST 分开处理。

  • 现象:sendFile 报路径错误或文件读取失败。
    原因:传入相对路径,受启动命令所在目录影响。
    修法:用 path.resolve(__dirname, ...) 拼成绝对路径后再 sendFile。

练习 ​

  1. 用 Express 创建一个 HTTP 服务,分别实现 / 和 /login 两个 GET 路由,返回不同内容,并验证访问不存在路径时的表现。
  2. 写一个静态资源托管服务:请求路径与 public 目录结构对应,支持 HTML、CSS、图片;文件不存在返回 404。
  3. 准备一个中文文件名资源,复现编码导致的 404,再用解码方式修复,并记录请求路径变化。
  4. 实现 /login 的 GET 和 POST 两个路由:GET 返回登录表单,POST 返回“提交成功”,验证只写 GET 时 POST 是否无响应。
  5. 给静态资源响应补充 MIME 类型映射:至少覆盖 .html、.css、.png、.ico,并观察 favicon 请求是否正常。

原视频对照 ​

#视频时长
1http服务总结08:32
2get和post的区别07:22
3初步实现静态文件托管24:26
4实现静态资源托管服务43:43
5express介绍和安装07:44
6express演示-创建http服务05:12
7express演示-简单路由演示06:20

小结 ​

  • Express 适合在已理解原生 HTTP 请求/响应流程后使用,能显著减少样板代码。
  • 路由匹配同时看“请求方式 + 路径”,GET 与 POST 必须分别注册。
  • res.send 比原生 res.end 更适合常规响应,能自动处理部分响应头问题。
  • 静态资源托管的核心是 URL 路径与服务器目录结构的稳定映射。
  • 路径拼接优先考虑 path.join,并警惕绝对路径覆盖问题。
  • 中文路径问题要同时关注浏览器编码与服务端解码。
  • 异步文件读取中,响应结束时机必须放在回调成功分支内。
  • MIME 类型设置是静态资源服务的收尾工作,影响浏览器识别与展示行为。