← Back to Index

Chapter 5: Network Programming

Building HTTP services and client communication

1. Native HTTP Server

Node.js's built-in http module can directly create HTTP servers without any third-party dependencies.

import http from "http";

interface ApiResponse {
    status: string;
    message: string;
    timestamp: number;
}

const server = http.createServer((req, res) => {
    const url = new URL(req.url ?? "/", `http://${req.headers.host}`);

    if (url.pathname === "/api/health" && req.method === "GET") {
        const body: ApiResponse = {
            status: "ok",
            message: "服务运行中",
            timestamp: Date.now(),
        };
        res.writeHead(200, { "Content-Type": "application/json" });
        res.end(JSON.stringify(body));
    } else {
        res.writeHead(404, { "Content-Type": "text/plain" });
        res.end("Not Found");
    }
});

server.listen(3000, () => {
    console.log("服务器已启动: http://localhost:3000");
});
🔄 Comparison with Java: The native HTTP server is similar to com.sun.net.httpserver.HttpServer but with a simpler API. Real projects typically use frameworks like Express, just as Java uses Spring Boot.

2. Express.js Basics

Express is Node.js's most popular web framework — minimal and flexible.

npm install express
npm install -D @types/express
import express, { Request, Response } from "express";

interface Todo {
    id: number;
    title: string;
    done: boolean;
}

const app = express();
app.use(express.json()); // 解析 JSON 请求体

const todos: Todo[] = [];
let nextId = 1;

// GET - 获取所有待办
app.get("/api/todos", (_req: Request, res: Response) => {
    res.json(todos);
});

// POST - 创建待办
app.post("/api/todos", (req: Request, res: Response) => {
    const todo: Todo = { id: nextId++, title: req.body.title, done: false };
    todos.push(todo);
    res.status(201).json(todo);
});

// PUT - 更新待办
app.put("/api/todos/:id", (req: Request, res: Response) => {
    const todo = todos.find((t) => t.id === Number(req.params.id));
    if (!todo) return res.status(404).json({ error: "未找到" });
    Object.assign(todo, req.body);
    res.json(todo);
});

// DELETE - 删除待办
app.delete("/api/todos/:id", (req: Request, res: Response) => {
    const idx = todos.findIndex((t) => t.id === Number(req.params.id));
    if (idx === -1) return res.status(404).json({ error: "未找到" });
    todos.splice(idx, 1);
    res.status(204).send();
});

app.listen(3000, () => console.log("Express 服务已启动"));

3. Express Middleware

Middleware is the core concept of Express — each request flows through the middleware chain in order, with each layer able to process, modify, or intercept the request.

import express, { Request, Response, NextFunction } from "express";

const app = express();

// 内置中间件
app.use(express.json());                    // 解析 JSON body
app.use(express.urlencoded({ extended: true })); // 解析表单
app.use(express.static("public"));          // 静态文件服务

// 自定义日志中间件
function logger(req: Request, _res: Response, next: NextFunction): void {
    console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
    next(); // 必须调用 next(),否则请求会挂起
}
app.use(logger);

// 错误处理中间件(4个参数)
function errorHandler(
    err: Error, _req: Request, res: Response, _next: NextFunction
): void {
    console.error("服务器错误:", err.message);
    res.status(500).json({ error: "内部服务器错误" });
}
app.use(errorHandler);
🔄 Comparison with Python Flask/Django: Express's middleware pattern is similar to Python WSGI/ASGI middleware. Express is lighter, similar to Flask's minimal style, rather than Django's full-stack framework.

Popular third-party middleware: cors (cross-origin), helmet (security headers), morgan (HTTP logging).

4. HTTP Client

Node.js 18+ has a built-in global fetch API, consistent with the browser side.

// GET 请求
interface User {
    id: number;
    name: string;
    email: string;
}

async function getUser(id: number): Promise<User> {
    const res = await fetch(`https://api.example.com/users/${id}`);
    if (!res.ok) throw new Error(`HTTP ${res.status}: ${res.statusText}`);
    return (await res.json()) as User;
}

// POST 请求
async function createUser(name: string, email: string): Promise<User> {
    const res = await fetch("https://api.example.com/users", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ name, email }),
    });
    if (!res.ok) throw new Error(`创建失败: ${res.status}`);
    return (await res.json()) as User;
}

For advanced features like interceptors, timeout control, and auto-retry, use axios:

npm install axios

5. WebSocket

WebSocket provides full-duplex communication, ideal for chat, real-time notifications, etc. The most commonly used library in Node.js is ws.

npm install ws
npm install -D @types/ws
import { WebSocketServer, WebSocket } from "ws";

const wss = new WebSocketServer({ port: 8080 });
const clients = new Set<WebSocket>();

wss.on("connection", (ws) => {
    clients.add(ws);
    console.log(`新连接,当前 ${clients.size} 个客户端`);

    ws.on("message", (data) => {
        const msg = data.toString();
        console.log("收到:", msg);
        // 广播给所有客户端
        for (const client of clients) {
            if (client !== ws && client.readyState === WebSocket.OPEN) {
                client.send(msg);
            }
        }
    });

    ws.on("close", () => {
        clients.delete(ws);
    });
});

console.log("WebSocket 服务器已启动: ws://localhost:8080");

📝 Chapter Summary

Native http is good for learning

Express or Fastify recommended for real projects

Express = Routing + Middleware

Understanding the middleware chain is key to mastering Express

fetch is the standard HTTP client

Built into Node 18+, choose axios for complex scenarios

WebSocket for real-time communication

ws library is lightweight and efficient for server-side bidirectional push