📚 完整教程目录

前言:什么是API?

🤔 API的定义

API(应用程序编程接口)是两个软件系统之间的通信协议。它定义了请求和响应的格式,允许不同的应用相互通信。

API的重要性

常见API类型

💡 重点:好的API设计是系统成功的关键。

RESTful API设计

REST原则

API设计最佳实践

// 资源命名 GET /api/users # 获取所有用户 GET /api/users/1 # 获取用户1 POST /api/users # 创建用户 PUT /api/users/1 # 更新用户1 DELETE /api/users/1 # 删除用户1 // 查询参数 GET /api/users?page=1&limit=10&sort=created_at GET /api/users?filter[status]=active GET /api/users?search=alice // 子资源 GET /api/users/1/posts # 获取用户1的所有文章 POST /api/users/1/posts # 为用户1创建文章 GET /api/users/1/posts/5 # 获取用户1的文章5 // 响应格式 { "success": true, "data": { "id": 1, "username": "alice", "email": "alice@example.com" }, "meta": { "page": 1, "limit": 10, "total": 100 } } // 错误响应 { "success": false, "error": { "code": "VALIDATION_ERROR", "message": "Invalid email format", "details": { "email": "Email is invalid" } } }

HTTP状态码

分页实现

// 基于偏移的分页 GET /api/users?offset=0&limit=10 // 基于游标的分页(推荐) GET /api/users?cursor=abc123&limit=10 // 响应 { "data": [...], "pagination": { "cursor": "xyz789", "has_more": true, "limit": 10 } }

GraphQL详解

什么是GraphQL?

GraphQL是一个查询语言和运行时,允许客户端精确指定需要的数据。

GraphQL vs REST

特性 GraphQL REST
数据获取 精确获取需要的字段 固定的响应结构
多个资源 单个请求 多个请求
学习曲线 陡峭 平缓
缓存 复杂 简单

GraphQL基础

// Schema定义 type User { id: ID! username: String! email: String! posts: [Post!]! } type Post { id: ID! title: String! content: String! author: User! } type Query { user(id: ID!): User users(limit: Int, offset: Int): [User!]! post(id: ID!): Post } type Mutation { createUser(username: String!, email: String!): User! updateUser(id: ID!, username: String): User deleteUser(id: ID!): Boolean! } // 查询 query { user(id: "1") { id username email posts { id title } } } // 响应 { "data": { "user": { "id": "1", "username": "alice", "email": "alice@example.com", "posts": [ { "id": "1", "title": "First Post" } ] } } }

Apollo Server实现

const { ApolloServer, gql } = require('apollo-server'); const typeDefs = gql` type User { id: ID! username: String! email: String! } type Query { user(id: ID!): User users: [User!]! } type Mutation { createUser(username: String!, email: String!): User! } `; const resolvers = { Query: { user: (_, { id }) => { return { id, username: 'alice', email: 'alice@example.com' }; }, users: () => { return [ { id: '1', username: 'alice', email: 'alice@example.com' } ]; } }, Mutation: { createUser: (_, { username, email }) => { return { id: '2', username, email }; } } }; const server = new ApolloServer({ typeDefs, resolvers }); server.listen().then(({ url }) => { console.log(`Server ready at ${url}`); });

WebSocket实时通信

WebSocket vs HTTP

WebSocket服务器

const WebSocket = require('ws'); const http = require('http'); const server = http.createServer(); const wss = new WebSocket.Server({ server }); wss.on('connection', (ws) => { console.log('Client connected'); // 接收消息 ws.on('message', (message) => { console.log('Received:', message); // 广播给所有客户端 wss.clients.forEach((client) => { if (client.readyState === WebSocket.OPEN) { client.send(message); } }); }); // 处理断开连接 ws.on('close', () => { console.log('Client disconnected'); }); // 发送欢迎消息 ws.send('Welcome to the server'); }); server.listen(8080, () => { console.log('Server listening on port 8080'); });

WebSocket客户端

// 浏览器客户端 const ws = new WebSocket('ws://localhost:8080'); // 连接打开 ws.onopen = () => { console.log('Connected'); ws.send('Hello Server'); }; // 接收消息 ws.onmessage = (event) => { console.log('Message from server:', event.data); }; // 连接关闭 ws.onclose = () => { console.log('Disconnected'); }; // 错误处理 ws.onerror = (error) => { console.error('WebSocket error:', error); };

Socket.IO(更高级的选项)

const io = require('socket.io')(3000); io.on('connection', (socket) => { console.log('User connected:', socket.id); // 监听事件 socket.on('message', (data) => { console.log('Message:', data); // 广播给所有客户端 io.emit('message', data); }); // 监听断开连接 socket.on('disconnect', () => { console.log('User disconnected:', socket.id); }); });

API版本控制

版本控制策略

向后兼容性

// 添加新字段时保持兼容性 // v1响应 { "id": 1, "username": "alice", "email": "alice@example.com" } // v2响应(添加新字段) { "id": 1, "username": "alice", "email": "alice@example.com", "created_at": "2024-01-01T00:00:00Z", "updated_at": "2024-01-02T00:00:00Z" } // 弃用字段时使用Deprecation头 app.get('/api/v1/users/:id', (req, res) => { res.set('Deprecation', 'true'); res.set('Sunset', new Date(Date.now() + 30*24*60*60*1000).toUTCString()); res.json({ /* ... */ }); });

认证和授权

API密钥认证

// 请求头中传递API密钥 GET /api/users Authorization: Bearer sk_live_abc123xyz789 // 验证中间件 const authenticateApiKey = (req, res, next) => { const token = req.headers.authorization?.split(' ')[1]; if (!token) { return res.status(401).json({ error: 'No token' }); } // 验证token const user = verifyToken(token); if (!user) { return res.status(401).json({ error: 'Invalid token' }); } req.user = user; next(); }; app.use(authenticateApiKey);

OAuth 2.0

// 授权码流程 1. 用户点击"使用Google登录" 2. 重定向到Google授权页面 3. 用户授权后,Google重定向回应用,带上授权码 4. 应用使用授权码换取访问令牌 5. 使用访问令牌访问API // 实现示例 const passport = require('passport'); const GoogleStrategy = require('passport-google-oauth20').Strategy; passport.use(new GoogleStrategy({ clientID: process.env.GOOGLE_CLIENT_ID, clientSecret: process.env.GOOGLE_CLIENT_SECRET, callbackURL: '/auth/google/callback' }, (accessToken, refreshToken, profile, done) => { // 创建或更新用户 User.findOrCreate({ googleId: profile.id }, (err, user) => { return done(err, user); }); }));

权限控制

// 基于角色的访问控制(RBAC) const authorize = (roles) => { return (req, res, next) => { if (!req.user || !roles.includes(req.user.role)) { return res.status(403).json({ error: 'Forbidden' }); } next(); }; }; // 使用 app.delete('/api/users/:id', authenticate, authorize(['admin']), (req, res) => { // 删除用户 } );

速率限制和缓存

速率限制

const rateLimit = require('express-rate-limit'); // 创建限制器 const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15分钟 max: 100, // 限制100个请求 message: 'Too many requests' }); // 应用到所有请求 app.use(limiter); // 应用到特定路由 app.post('/api/login', rateLimit({ windowMs: 15 * 60 * 1000, max: 5 // 登录限制更严格 }), (req, res) => { // 登录逻辑 } );

缓存策略

// HTTP缓存头 app.get('/api/users/:id', (req, res) => { // 缓存1小时 res.set('Cache-Control', 'public, max-age=3600'); // 或者使用ETag进行条件请求 const etag = generateETag(user); res.set('ETag', etag); if (req.headers['if-none-match'] === etag) { return res.status(304).send(); } res.json(user); }); // 使用Redis缓存 const redis = require('redis'); const client = redis.createClient(); app.get('/api/users/:id', async (req, res) => { const cacheKey = `user:${req.params.id}`; // 检查缓存 const cached = await client.get(cacheKey); if (cached) { return res.json(JSON.parse(cached)); } // 从数据库获取 const user = await User.findById(req.params.id); // 缓存1小时 await client.setEx(cacheKey, 3600, JSON.stringify(user)); res.json(user); });

API文档

OpenAPI/Swagger

// swagger.yaml openapi: 3.0.0 info: title: My API version: 1.0.0 paths: /api/users: get: summary: 获取所有用户 parameters: - name: page in: query schema: type: integer responses: '200': description: 成功 content: application/json: schema: type: array items: $ref: '#/components/schemas/User' post: summary: 创建用户 requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UserInput' responses: '201': description: 创建成功 components: schemas: User: type: object properties: id: type: integer username: type: string email: type: string

使用Swagger UI

const swaggerUi = require('swagger-ui-express'); const swaggerDocument = require('./swagger.json'); app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));

API测试

使用Jest和Supertest

const request = require('supertest'); const app = require('../app'); describe('User API', () => { test('GET /api/users should return all users', async () => { const response = await request(app) .get('/api/users') .expect(200); expect(response.body).toBeInstanceOf(Array); }); test('POST /api/users should create a user', async () => { const response = await request(app) .post('/api/users') .send({ username: 'alice', email: 'alice@example.com' }) .expect(201); expect(response.body).toHaveProperty('id'); expect(response.body.username).toBe('alice'); }); test('GET /api/users/:id should return a user', async () => { const response = await request(app) .get('/api/users/1') .expect(200); expect(response.body).toHaveProperty('id'); }); });

使用Postman

实战项目:构建完整的API系统

项目需求

核心实现

// routes/users.js const express = require('express'); const router = express.Router(); const { authenticate, authorize } = require('../middleware/auth'); // 获取所有用户 router.get('/', async (req, res, next) => { try { const { page = 1, limit = 10 } = req.query; const skip = (page - 1) * limit; const users = await User.find() .skip(skip) .limit(limit); const total = await User.countDocuments(); res.json({ data: users, pagination: { page, limit, total } }); } catch (error) { next(error); } }); // 创建用户 router.post('/', async (req, res, next) => { try { const user = await User.create(req.body); res.status(201).json(user); } catch (error) { next(error); } }); // 更新用户 router.put('/:id', authenticate, authorize(['admin']), async (req, res, next) => { try { const user = await User.findByIdAndUpdate( req.params.id, req.body, { new: true } ); res.json(user); } catch (error) { next(error); } }); // 删除用户 router.delete('/:id', authenticate, authorize(['admin']), async (req, res, next) => { try { await User.findByIdAndDelete(req.params.id); res.json({ success: true }); } catch (error) { next(error); } }); module.exports = router;
✨ 实战总结:

通过这个项目,你学会了如何设计和实现一个完整的、生产级别的API系统。

🎉 API开发学习完成

现在你已经掌握了API开发的核心知识。

✅ 你现在可以:

🚀 下一步学习

  1. 学习API网关(Kong、AWS API Gateway)
  2. 学习API监控和分析
  3. 学习API安全最佳实践
  4. 学习微服务通信
💡 建议:

API设计的关键是考虑用户体验。设计简洁、易用的API,会让开发者更愿意使用你的服务。