Skip to main content
ClaudeWave
Skill545 repo starsupdated 9d ago

backend/api-development

# Backend API Development This Claude Code skill provides a backend API development methodology covering RESTful and GraphQL design patterns, request validation, error handling, and security implementation. Use it when building server-side API endpoints to ensure consistent contract management, standardized response formats, multi-layer input validation, and proper HTTP status code mapping for errors. The skill includes specific schemas for pagination, type definitions for frontend sharing, and best practices for resource naming conventions and authentication requirements.

Install in Claude Code
Copy
git clone --depth 1 https://github.com/echoVic/boss-skill /tmp/backend-api-development && cp -r /tmp/backend-api-development/skill/skills/backend/api-development ~/.claude/skills/backend-api-development
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

# 后端 API 开发方法论

## API 契约管理

### 契约来源

实现 API 前,**必须**阅读 `architecture.md` §5(API 设计),获取:
- API 规范(RESTful/GraphQL)
- 接口列表(方法、路径、描述、认证要求)
- 请求/响应格式约定
- 错误码规范

### 契约遵守原则

1. **严格实现**:API 端点的方法、路径、参数必须与 architecture.md §5 一致
2. **响应格式**:遵循统一的成功/错误响应结构
3. **偏差记录**:如需偏离契约,必须在输出报告中标注原因
4. **类型导出**:将请求/响应类型导出到共享文件,供前端引用

## RESTful API 设计

### 资源命名规范

| 操作 | HTTP 方法 | 路径 | 说明 |
|------|-----------|------|------|
| 列表 | GET | `/api/users` | 获取用户列表 |
| 详情 | GET | `/api/users/:id` | 获取单个用户 |
| 创建 | POST | `/api/users` | 创建新用户 |
| 更新 | PUT/PATCH | `/api/users/:id` | 更新用户 |
| 删除 | DELETE | `/api/users/:id` | 删除用户 |

### 统一响应格式

**成功响应**:
```json
{
  "success": true,
  "data": { ... },
  "message": "Operation successful"
}
```

**错误响应**:
```json
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid input data",
    "details": [
      { "field": "email", "message": "Invalid email format" }
    ]
  }
}
```

### 分页规范

**请求参数**:
```
GET /api/users?page=1&pageSize=20&sortBy=createdAt&order=desc
```

**响应格式**:
```json
{
  "success": true,
  "data": {
    "items": [...],
    "pagination": {
      "page": 1,
      "pageSize": 20,
      "total": 100,
      "totalPages": 5
    }
  }
}
```

## 请求验证

### 输入验证层级

1. **路由层**:验证路径参数和查询参数
2. **中间件层**:验证请求体格式和必填字段
3. **Service 层**:验证业务规则

### 验证示例

```typescript
// 使用验证库(如 Zod、Joi、class-validator)
import { z } from 'zod';

const CreateUserSchema = z.object({
  name: z.string().min(1).max(100),
  email: z.string().email(),
  age: z.number().int().min(0).max(150).optional(),
});

// 在路由处理器中验证
app.post('/api/users', async (req, res) => {
  try {
    const validatedData = CreateUserSchema.parse(req.body);
    const user = await userService.create(validatedData);
    res.json({ success: true, data: user });
  } catch (error) {
    if (error instanceof z.ZodError) {
      res.status(400).json({
        success: false,
        error: {
          code: 'VALIDATION_ERROR',
          message: 'Invalid input data',
          details: error.errors,
        },
      });
    }
  }
});
```

### 常见验证规则

- **必填字段**:确保关键字段存在
- **类型检查**:字符串、数字、布尔值、日期
- **格式验证**:邮箱、URL、手机号、UUID
- **范围限制**:最小/最大长度、数值范围
- **业务规则**:唯一性、外键存在性

## 错误处理

### 错误分类

| 错误类型 | HTTP 状态码 | 错误码 | 说明 |
|----------|-------------|--------|------|
| 验证错误 | 400 | VALIDATION_ERROR | 输入数据不合法 |
| 认证错误 | 401 | UNAUTHORIZED | 未登录或 Token 无效 |
| 权限错误 | 403 | FORBIDDEN | 无权限访问资源 |
| 资源不存在 | 404 | NOT_FOUND | 请求的资源不存在 |
| 冲突错误 | 409 | CONFLICT | 资源冲突(如重复创建) |
| 服务器错误 | 500 | INTERNAL_ERROR | 服务器内部错误 |

### 统一错误处理中间件

```typescript
// errorHandler.ts
export function errorHandler(err: Error, req: Request, res: Response, next: NextFunction) {
  console.error(err);
  
  if (err instanceof ValidationError) {
    return res.status(400).json({
      success: false,
      error: {
        code: 'VALIDATION_ERROR',
        message: err.message,
        details: err.details,
      },
    });
  }
  
  if (err instanceof NotFoundError) {
    return res.status(404).json({
      success: false,
      error: {
        code: 'NOT_FOUND',
        message: err.message,
      },
    });
  }
  
  // 默认 500 错误
  res.status(500).json({
    success: false,
    error: {
      code: 'INTERNAL_ERROR',
      message: 'An unexpected error occurred',
    },
  });
}
```

## 安全实现

### 认证(Authentication)

**JWT Token 示例**:
```typescript
import jwt from 'jsonwebtoken';

// 生成 Token
export function generateToken(userId: string): string {
  return jwt.sign({ userId }, process.env.JWT_SECRET!, {
    expiresIn: '7d',
  });
}

// 验证 Token 中间件
export function authMiddleware(req: Request, res: Response, next: NextFunction) {
  const token = req.headers.authorization?.replace('Bearer ', '');
  
  if (!token) {
    return res.status(401).json({
      success: false,
      error: { code: 'UNAUTHORIZED', message: 'No token provided' },
    });
  }
  
  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET!);
    req.user = decoded;
    next();
  } catch (error) {
    res.status(401).json({
      success: false,
      error: { code: 'UNAUTHORIZED', message: 'Invalid token' },
    });
  }
}
```

### 授权(Authorization)

**基于角色的访问控制(RBAC)**:
```typescript
export function requireRole(...roles: string[]) {
  return (req: Request, res: Response, next: NextFunction) => {
    if (!req.user || !roles.includes(req.user.role)) {
      return res.status(403).json({
        success: false,
        error: { code: 'FORBIDDEN', message: 'Insufficient permissions' },
      });
    }
    next();
  };
}

// 使用
app.delete('/api/users/:id', authMiddleware, requireRole('admin'), deleteUser);
```

### 输入消毒

- **SQL 注入防护**:使用参数化查询或 ORM
- **XSS 防护**:转义用户输入,使用 Content Security Policy
- **CSRF 防护**:使用 CSRF Token
- **文件上传**:验证文件类型和大小

### 速率限制

```typescript
import rateLimit from 'express-rate-limit';

const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 分钟
  max: 100, // 最多 100 个请求
  message: 'Too many requests, please try again later',
});

app.use('/api/', limiter);
```

## 分层架构

### Controller 层

职责:处理 HTTP 请求和响应
```typescript
// controllers/userController.ts
export class UserController {
  async getUser(req: Request, res: Response) {
    try {
      const user = await userService.getById(req.params.id);
      res.json({ success: true, data: user });
    } catch (error) {
      next(error);
    }
  }
  
  async createUser(req: Request, res: Response) {
    const validatedData = CreateUserSchema.parse(req.body);
    const user = await userService.create(validatedData);
    res.status(201).json({ success: true, data: user });
  }
}
```

### Service 层

职责:业务逻辑封装
```typescript
// services/userService.ts
export class UserService {
  async getById(id: string): Promise<User> {
    const user = await userRepository.findById(id);
    if (!user) {
      throw new NotFoundError('User not found');
    }
    return user;
  }
  
  async create(data: CreateUserDto): Promise<User> {
    // 检查邮箱唯一性
    const existing = await userRepository.findByEmail(da