凌峰创科服务平台

Node.js 如何搭建 HTTP 服务器?

最简单的 HTTP 服务器

Node.js 内置了 http 模块,我们可以用它来创建一个最基本的服务器,这个服务器会监听一个端口,并对每个请求返回 "Hello, World!"。

Node.js 如何搭建 HTTP 服务器?-图1
(图片来源网络,侵删)

代码 (server.js):

// 1. 导入 Node.js 内置的 'http' 模块
const http = require('http');
// 2. 定义服务器将要监听的端口号
const port = 3000;
// 3. 创建服务器
// createServer 方法接收一个回调函数,这个函数会在每次有请求进入时被调用
// 回调函数有两个参数:request (req) 和 response (res)
const server = http.createServer((req, res) => {
  // 4. 设置响应头
  // HTTP 状态码: 200 (表示成功)类型: text/plain (纯文本)
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  // 5. 发送响应体并结束响应
  res.end('Hello, World!\n');
});
// 6. 启动服务器,让它监听指定的端口
server.listen(port, () => {
  // 7. 当服务器成功启动后,这个回调函数会被执行
  console.log(`Server is running and listening on http://localhost:${port}`);
});

如何运行:

  1. 将以上代码保存为 server.js
  2. 打开终端或命令行。
  3. 运行命令:node server.js
  4. 你会看到终端输出:Server is running and listening on http://localhost:3000
  5. 打开浏览器,访问 http://localhost:3000,你将看到 "Hello, World!"。

代码深入解析

代码片段 说明
const http = require('http'); require 是 Node.js 的函数,用于引入模块。http 是 Node.js 核心模块,无需额外安装。
http.createServer((req, res) => { ... }); 这是核心方法,它创建了一个新的服务器实例,并接收一个请求监听器(回调函数),每当有新的 HTTP 请求到达时,这个回调函数就会被执行。
req (Request 对象) 代表客户端发来的 HTTP 请求,它包含了请求的所有信息,
- req.method: 请求方法,如 'GET', 'POST'。
- req.url: 请求的 URL 路径,如 /about
- req.headers: 请求头对象,包含如 'User-Agent', 'Accept' 等信息。
res (Response 对象) 代表服务器将要发送给客户端的 HTTP 响应,我们通过这个对象来构建和发送响应。
- res.writeHead(statusCode, [statusMessage], [headers]): 发送一个响应头。statusCode 是 HTTP 状态码(如 200, 404, 500)。headers 是一个对象,包含响应头信息,如 Content-Type
- res.end([data], [encoding]): 结束响应,如果提供了 data,它会和之前通过 write()writeHead() 写入的内容一起发送,这是发送响应的最后一个步骤。
server.listen(port, callback); 让服务器开始在指定的 port 上监听客户端的连接,当服务器成功启动并准备好接收连接时,callback 函数会被执行。

处理不同的路由和请求方法

一个真实的服务器需要根据不同的 URL 和请求方法返回不同的内容,我们可以通过检查 req.methodreq.url 来实现。

代码 (router.js):

Node.js 如何搭建 HTTP 服务器?-图2
(图片来源网络,侵删)
const http = require('http');
const port = 3000;
const server = http.createServer((req, res) => {
  // 获取请求方法和路径
  const method = req.method;
  const url = req.url;
  // 设置响应头为 HTML,这样浏览器可以正确渲染
  res.setHeader('Content-Type', 'text/html');
  if (method === 'GET' && url === '/') {
    // 首页
    res.writeHead(200);
    res.end('<h1>Welcome to the Home Page!</h1>');
  } else if (method === 'GET' && url === '/about') {
    // 关于页面
    res.writeHead(200);
    res.end('<h1>About Us</h1><p>This is a simple Node.js server.</p>');
  } else if (method === 'POST' && url === '/submit-data') {
    // 处理 POST 请求
    let body = '';
    req.on('data', chunk => {
      body += chunk.toString(); // 将数据块拼接成字符串
    });
    req.on('end', () => {
      res.writeHead(200);
      res.end(`<h1>Received POST data:</h1><p>${body}</p>`);
    });
  } else {
    // 404 Not Found
    res.writeHead(404);
    res.end('<h1>404 Not Found</h1><p>The page you are looking for does not exist.</p>');
  }
});
server.listen(port, () => {
  console.log(`Server is running on http://localhost:${port}`);
});

说明:

  • 我们使用 if/else if/else 结构来匹配不同的 (method, url) 组合,这就是最简单的路由
  • 对于 POST 请求,请求体(request body)不是一次性接收到的,而是以数据块(chunks)的形式流式传输过来的,我们需要监听 reqdata 事件来收集数据块,并在 end 事件触发时(所有数据接收完毕)处理数据。
  • 对于不存在的路径,我们返回 404 Not Found 状态码。

从原生模块到框架

虽然用原生 http 模块可以构建服务器,但处理路由、中间件、静态文件等会变得非常繁琐和重复,社区诞生了许多优秀的 Web 框架,它们封装了底层细节,提供了更优雅、更强大的开发体验。

最流行的两个框架是 ExpressKoa

为什么使用框架?

  1. 路由管理:框架提供了清晰的路由定义方式(如 app.get(), app.post())。
  2. 中间件:框架的核心概念,允许你将请求处理函数模块化,可以处理日志、认证、解析请求体等。
  3. 模板引擎:轻松渲染动态 HTML 页面。
  4. 静态文件服务:轻松提供 CSS、JavaScript、图片等静态资源。
  5. 错误处理:提供统一的错误处理机制。

使用 Express 框架的例子

你需要安装 Express:

Node.js 如何搭建 HTTP 服务器?-图3
(图片来源网络,侵删)
npm init -y # 初始化一个 package.json 文件
npm install express

代码 (app.js):

// 1. 导入 express 框架
const express = require('express');
const app = express(); // 创建一个 Express 应用实例
const port = 3000;
// 2. 使用中间件来解析 JSON 格式的请求体
// 这样我们就可以在 POST 请求中通过 req.body 获取数据
app.use(express.json());
// 3. 定义路由
// GET 请求到根路径
app.get('/', (req, res) => {
  res.send('<h1>Welcome to the Express Home Page!</h1>');
});
// GET 请求到 /about 路径
app.get('/about', (req, res) => {
  res.send('<h1>About Us (Express)</h1>');
});
// POST 请求到 /api/users 路径
app.post('/api/users', (req, res) => {
  // 请求体已经被 express.json() 中间件解析好了
  const newUser = req.body;
  console.log('Received new user:', newUser);
  res.status(201).json({ message: 'User created successfully!', user: newUser });
});
// 4. 404 处理中间件
// 这个中间件应该放在所有路由的后面
app.use((req, res) => {
  res.status(404).send('<h1>404 - Page Not Found (Express)</h1>');
});
// 5. 启动服务器
app.listen(port, () => {
  console.log(`Express server is running on http://localhost:${port}`);
});

对比原生 http 和 Express:

  • 简洁性:Express 的路由定义 (app.get()) 比原生 if/else 判断清晰得多。
  • 中间件app.use(express.json()) 一行代码就解决了 POST 请求体解析的复杂问题。
  • 响应方法res.send(), res.json() 等方法简化了发送不同类型响应的过程。
  • 状态码res.status(201).json(...) 设置状态码和发送响应结合得非常方便。

特性 原生 http 模块 Express 框架
易用性 较低,需要手动处理所有细节 ,提供了丰富的 API 和抽象
路由 手动 if/else 判断 req.methodreq.url 声明式,如 app.get('/path', handler)
中间件 无内置支持,需自己实现 核心功能,用于模块化处理逻辑
请求/响应 手动调用 writeHeadend 链式调用,如 res.status(200).json({})
适用场景 学习 Node.js 底层原理、构建极简服务 绝大多数 Web 应用,如 API、网站

建议:

  • 初学者:从原生 http 模块开始,可以帮助你深刻理解 Node.js 的 I/O 模型(事件驱动、非阻塞)和 HTTP 协议的工作原理。
  • 实际开发:直接使用 ExpressKoa 这样的框架,它们能让你更专注于业务逻辑,而不是重复造轮子,大大提高开发效率。
分享:
扫描分享到社交APP
上一篇
下一篇