Kodokon kodokon.com

你的第一个原生 HTTP 服务器

你将用 Node 的 http 模块创建一个 Web 服务器、响应请求,并返回 JSON。

10 分钟 · 3 题

在 Kodokon 中打开本课

Web 服务器是一个持续运行、等待请求的程序:请求就是客户端(浏览器、手机应用等等)发来的要求。对于每个请求,它都会返回一个响应。这段对话遵循 HTTP 协议,也就是 Web 的通用语言。Node 内置了一个开箱即用的 http 模块:无需安装任何东西。最后一个概念:端口,一个在机器上标识某个特定程序的数字,就像楼里的房间号。我们会用端口 3000;至于 localhost,它就是指你自己的机器。

JAVASCRIPT
import http from "node:http";

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader("Content-Type", "text/plain");
  res.end("Hello from my server!");
});

server.listen(3000, () => {
  console.log("Server at http://localhost:3000");
});
把这段代码保存到 server.js 里,然后运行 node server.js。

让我们把它拆解开来。http.createServer 接收一个在每次请求时都会被调用的函数,它有两个参数:req(进来的请求)和 res(正在构建的响应)。res.statusCode = 200 设置状态码,200 表示 "一切正常"。res.setHeader 添加一个头部,也就是关于响应的一小段元数据:这里指的是它的格式,即纯文本。res.end 发送响应并结束它。最后,server.listen(3000) 让服务器在端口 3000 上监听。在你的浏览器里打开 http://localhost:3000:你的文本就会出现。请注意,这个程序并不会把控制权交还回来:它在等待请求。用 Ctrl+C 停止它。

现代的服务器很少返回纯文本:它们会暴露一些用 JSON 来响应的 API,JSON 就是你已经认识的那种文本格式,任何语言都能理解。两处调整:Content-Type 头部变成 application/json,并且 JavaScript 对象要用 JSON.stringify 转换成文本。让我们借此机会根据 req.url(客户端所请求的路径)做出不同的反应:这正是路由的基础。

JAVASCRIPT
import http from "node:http";

const server = http.createServer((req, res) => {
  res.setHeader("Content-Type", "application/json");

  if (req.url === "/api/message") {
    const body = { message: "Hello!", ok: true };
    res.statusCode = 200;
    res.end(JSON.stringify(body));
    return;
  }

  res.statusCode = 404;
  res.end(JSON.stringify({ error: "Not found" }));
});

server.listen(3000, () => {
  console.log("http://localhost:3000/api/message");
});
一个已知的路由会用一个 JSON 对象响应 200;任何其他路径都会收到 404。

404 状态码表示 "未找到":所请求的路径不匹配任何已知的路由。请注意第一个响应之后的 return:它会阻止代码继续往下运行并发送第二个响应,否则那会导致一个错误。要测试的话,可以在浏览器里打开这个地址,或者使用 curl,这是一个发送 HTTP 请求并在终端里显示响应的命令行工具。

BASH
curl http://localhost:3000/api/message
在第二个终端里,当服务器正在运行时:JSON 响应就会出现。

知识检测

确认你已牢记本课的重点内容。

  1. server.listen(3000) 做了什么?
    • 它让服务器在端口 3000 上监听请求
    • 它向端口 3000 发送一个请求
    • 它把服务器限制为最多同时处理 3000 个请求
    • 它在 localhost:3000 上打开浏览器
  2. 你要发送哪个头部来表明响应是 JSON?
    • Accept: application/json
    • Content-Type: application/json
    • Format: json
  3. 为什么要在 res.end 之前把对象经过 JSON.stringify 处理?
    • 为了压缩响应并节省时间
    • 为了检查对象里不含错误
    • 因为 HTTP 响应承载的是文本,而不是 JavaScript 对象