mcpField
A
api-design

api-design

github.com/travisjneuman开发107167 次安装今天更新
代码仓库

关于 api-design

api-design 是面向开发者的 API 设计参考技能,涵盖 REST 及其他 API 的可维护性实践。内容从资源命名延伸到安全、协议和交付模式。

主要功能

  1. 01REST 资源与方法规范
  2. 02状态码与响应格式
  3. 03分页、筛选、排序和版本管理
  4. 04OpenAPI、gRPC 与 tRPC 指南
  5. 05身份验证、限流与安全
  6. 06Webhook 签名、重试与幂等性

适用场景

  1. 01规划新 REST API 的端点
  2. 02选择分页与版本管理模式
  3. 03整理身份验证和安全要求
  4. 04设计可靠的 Webhook 投递

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/travisjneuman/.claude --skill api-design

安装后在 Claude Code 中输入/api-design确认已加载。

详细介绍

API 设计指南

设计对开发者友好且易于维护的 API 的最佳实践。

REST API 原则

资源命名

使用名词,而非动词:

✓ GET /users
✓ GET /users/123
✓ GET /users/123/orders

✗ GET /getUsers
✗ GET /fetchUserById
✗ POST /createNewOrder

使用复数名词:

✓ /users
✓ /orders
✓ /products

✗ /user
✗ /order

层级关系:

/users/{userId}/orders           # User's orders
/users/{userId}/orders/{orderId} # Specific order

HTTP 方法
方法用途幂等请求正文
GET获取资源是否
POST创建资源否是
PUT完全替换资源是是
PATCH部分更新资源否是
DELETE移除资源是否

状态码

成功(2xx):

  • 200 OK - 请求成功
  • 201 Created - 资源已创建(返回 Location 标头)
  • 204 No Content - 请求成功,但无响应正文

客户端错误(4xx):

  • 400 Bad Request - 请求格式错误
  • 401 Unauthorized - 需要身份验证
  • 403 Forbidden - 无权限
  • 404 Not Found - 资源不存在
  • 409 Conflict - 状态冲突
  • 422 Unprocessable Entity - 验证失败
  • 429 Too Many Requests - 请求频率受限

服务端错误(5xx):

  • 500 Internal Server Error - 意外错误
  • 503 Service Unavailable - 服务暂时不可用

响应格式

成功响应:

{
  "data": {
    "id": "123",
    "name": "John Doe",
    "email": "[email protected]"
  }
}

集合响应:

{
  "data": [
    { "id": "1", "name": "Item 1" },
    { "id": "2", "name": "Item 2" }
  ],
  "meta": {
    "page": 1,
    "perPage": 20,
    "total": 100,
    "totalPages": 5
  },
  "links": {
    "self": "/items?page=1",
    "next": "/items?page=2",
    "prev": null
  }
}

错误响应:

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Validation failed",
    "details": [
      {
        "field": "email",
        "code": "INVALID_FORMAT",
        "message": "Must be a valid email address"
      }
    ]
  }
}

分页

基于偏移量(实现简单,但处理大型数据集时较慢):

GET /users?page=2&perPage=20
GET /users?offset=40&limit=20

基于游标(效率高,推荐使用):

GET /users?cursor=eyJpZCI6MTIzfQ&limit=20

响应中包含下一个游标:

{
  "data": [...],
  "meta": {
    "nextCursor": "eyJpZCI6MTQzfQ",
    "hasMore": true
  }
}

筛选、排序和字段

筛选:

GET /users?status=active
GET /users?created_after=2024-01-01
GET /users?role=admin,moderator

排序:

GET /users?sort=name
GET /users?sort=-created_at         # Descending
GET /users?sort=status,-created_at  # Multiple fields

字段选择:

GET /users?fields=id,name,email
GET /users?include=orders,profile

版本控制

URL 路径(推荐):

/api/v1/users
/api/v2/users

标头:

Accept: application/vnd.api+json;version=2

OpenAPI 规范

openapi: 3.0.3
info:
  title: My API
  version: 1.0.0
  description: API for managing users

servers:
  - url: https://api.example.com/v1

paths:
  /users:
    get:
      summary: List users
      tags: [Users]
      parameters:
        - name: page
          in: query
          schema:
            type: integer
            default: 1
      responses:
        "200":
          description: List of users
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/User"

components:
  schemas:
    User:
      type: object
      required: [id, email]
      properties:
        id:
          type: string
        email:
          type: string
          format: email
        name:
          type: string

身份验证

API 密钥(简单,适用于服务间通信):

Authorization: Api-Key YOUR_API_KEY

Bearer 令牌(JWT、OAuth):

Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

在 OpenAPI 中包含:

components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

security:
  - bearerAuth: []

速率限制

在响应中包含以下标头:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1640995200

超出限制时,返回 429 Too Many Requests。


安全检查清单

  • 仅使用 HTTPS
  • 对受保护的路由进行身份验证
  • 输入验证
  • 输出编码
  • 速率限制
  • CORS 配置
  • URL 中不包含敏感数据
  • 审计日志记录

gRPC 和 Protocol Buffers

Proto 定义
syntax = "proto3";
package user.v1;

service UserService {
  rpc GetUser(GetUserRequest) returns (User);
  rpc ListUsers(ListUsersRequest) returns (ListUsersResponse);
  rpc CreateUser(CreateUserRequest) returns (User);
  rpc StreamUpdates(StreamRequest) returns (stream UserUpdate);
}

message User {
  string id = 1;
  string name = 2;
  string email = 3;
  google.protobuf.Timestamp created_at = 4;
}

message GetUserRequest {
  string id = 1;
}

message ListUsersRequest {
  int32 page_size = 1;
  string page_token = 2;
}

message ListUsersResponse {
  repeated User users = 1;
  string next_page_token = 2;
}
何时使用 gRPC,何时使用 REST
因素gRPCREST
性能二进制,速度快JSON,易于阅读
流式传输双向通过 SSE/WebSocket 变通实现
类型安全Proto 生成类型OpenAPI + 代码生成
浏览器需要 gRPC-Web 代理原生支持
工具链Protoc、BufSwagger、Postman
适用场景服务间通信、流式传输公共 API、Web 客户端

面向 TypeScript 的 tRPC

// server/router.ts
import { router, publicProcedure, protectedProcedure } from './trpc';
import { z } from 'zod';

export const appRouter = router({
  user: router({
    get: publicProcedure
      .input(z.object({ id: z.string() }))
      .query(async ({ input }) => {
        return db.user.findUnique({ where: { id: input.id } });
      }),
    create: protectedProcedure
      .input(z.object({
        name: z.string().min(1),
        email: z.string().email(),
      }))
      .mutation(async ({ input, ctx }) => {
        return db.user.create({ data: { ...input, createdBy: ctx.userId } });
      }),
  }),
});

export type AppRouter = typeof appRouter;

// client.ts - Full type inference, no codegen
const user = trpc.user.get.useQuery({ id: '123' });
const createUser = trpc.user.create.useMutation();

对于客户端和服务端共享同一代码库的单体仓库全栈 TypeScript 应用,tRPC 是理想选择。


Webhook 设计模式

Webhook 负载
{
  "id": "evt_abc123",
  "type": "order.completed",
  "created_at": "2025-01-15T10:30:00Z",
  "data": {
    "order_id": "ord_456",
    "total": 99.99,
    "currency": "USD"
  }
}
签名验证
// Sign webhooks with HMAC-SHA256
import crypto from 'crypto';

function signWebhook(payload: string, secret: string): string {
  return crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
}

// Verify on receiving end
function verifyWebhook(payload: string, signature: string, secret: string): boolean {
  const expected = signWebhook(payload, secret);
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected),
  );
}
重试策略
Attempt 1: Immediately
Attempt 2: After 1 minute
Attempt 3: After 5 minutes
Attempt 4: After 30 minutes
Attempt 5: After 2 hours
Attempt 6: After 24 hours (final)

Failed webhooks: log, alert, manual retry UI
幂等性
// Include idempotency key in webhook
// Receivers should deduplicate based on event ID
async function handleWebhook(event: WebhookEvent) {
  // Check if already processed
  const existing = await db.processedEvents.findUnique({
    where: { eventId: event.id },
  });
  if (existing) return { status: 'already_processed' };

  // Process and record
  await db.$transaction([
    processEvent(event),
    db.processedEvents.create({ data: { eventId: event.id } }),
  ]);
}

API 版本控制策略

策略示例优点缺点
URL 路径/api/v1/users明确,易于路由URL 冗余
查询参数/api/users?version=1可选参数容易被忽略
标头Accept: application/vnd.api.v1URL 简洁隐蔽,较难测试
内容协商Accept: application/json;v=2基于标准实现复杂

建议: 为求简单,采用 URL 路径版本控制。仅在存在破坏性变更时升级主版本。在同一版本中使用增量式、非破坏性变更。

评论

支持 Markdown