☰
agentic-awesome-skills 中的 REST API 设计最佳实践:从 URL 规范到生产级 FastAPI 落地
2026/10/21 2:53:38 网站建设 项目流程
  • AI 技能
  • AI 插件
  • 人工智能

【免费下载链接】agentic-awesome-skills

AAS Core is the local, agent-first control plane for complete catalog discovery, agent-owned selection, stack validation, and planning, backed by 2,600+ agentic skills. Includes CLI, local MCP, catalog, plugins, and Workbench.

项目地址:https://gitcode.com/GitHub_Trending/an/agentic-awesome-skills
点击查看免费下载

本指南以 agentic-awesome-skills 仓库内 api-design-principles 技能包的 REST Best Practices 参考文档为骨架,系统梳理 REST API 设计的核心规范,并结合作者随包提供的 rest-api-template.py 与 api-design-checklist.md,给出可复制、可运行的生产级实现。读完本文,你将掌握资源命名、HTTP 语义、分页/过滤、版本化、限流、错误格式、缓存、幂等性、CORS、OpenAPI 文档与健康检查等一整套 REST 设计方法,并能在 FastAPI 中直接落地。

该技能包在仓库的 skills_index.json 中被登记为分类backend、风险等级safe、来源community,插件目标同时支持 codex 与 claude 两类 Agent(参见 skills_index.json),说明它属于面向开发者的通用 API 设计方法论,而非特定框架绑定,正文中的代码示例采用 FastAPI 仅作为演示载体。

一、URL 结构:资源命名与层级设计

1.1 资源命名:名词复数,杜绝动词

REST 将"资源"建模为名词,HTTP 方法表达操作语义,因此 URL 中不应出现动词。原文档给出了清晰的对照:

# Good - Plural nouns GET /api/users GET /api/orders GET /api/products # Bad - Verbs or mixed conventions GET /api/getUser GET /api/user (inconsistent singular) POST /api/createOrder

配套的 api-design-checklist.md 在"Pre-Implementation Review → Resource Design"一节进一步固化了这条检查项:Resources are nouns, not verbs、Plural names for collections、Consistent naming across all endpoints,并建议把资源层级控制在 2 层以内(Clear resource hierarchy (avoid deep nesting >2 levels))。

1.2 嵌套资源:浅层优先

子资源通过嵌套表达从属关系,但嵌套过深会让 URL 冗长、路由复杂且难以维护:

# Shallow nesting (preferred) GET /api/users/{id}/orders GET /api/orders/{id} # Deep nesting (avoid) GET /api/users/{id}/orders/{orderId}/items/{itemId}/reviews # Better: GET /api/order-items/{id}/reviews

设计要点:当子资源本身需要被独立寻址时(如order-item可以直接通过 ID 访问),应把它提升为顶层资源,用"提升实体"的方式打断过深的层级,而不是无限嵌套下去。

二、HTTP 方法与状态码语义

原文档对每个 HTTP 方法给出了完整的请求-响应映射,这也是 REST 契约中最重要的部分。

2.1 GET —— 检索资源(安全、幂等)

GET /api/users → 200 OK (with list) GET /api/users/{id} → 200 OK or 404 Not Found GET /api/users?page=2 → 200 OK (paginated)

GET 必须是无副作用的;集合请求应支持分页(见第四节)。模板中的列表端点list_users正是按此模式实现,见 rest-api-template.py。

2.2 POST —— 创建资源

POST /api/users Body: {"name": "John", "email": "john@example.com"} → 201 Created Location: /api/users/123 Body: {"id": "123", "name": "John", ...} POST /api/users (validation error) → 422 Unprocessable Entity Body: {"errors": [...]}

要点:

  • 创建成功返回201 Created,并在响应头Location中给出新资源的定位;
  • 校验失败返回422 Unprocessable Entity而不是笼统的 400,因为请求语法本身合法,只是语义/业务校验不通过(如邮箱格式非法)。

模板中的create_user端点用status_code=status.HTTP_201_CREATED显式声明创建语义,并用 Pydantic 的EmailStr类型在请求进入业务逻辑前完成字段级校验,见 rest-api-template.py。

2.3 PUT —— 整体替换(幂等)

PUT /api/users/{id} Body: {complete user object} → 200 OK (updated) → 404 Not Found (doesn't exist) # Must include ALL fields

PUT 要求客户端提交完整对象,服务端整体覆盖;重复提交同一 PUT 结果一致,因此天然幂等。

2.4 PATCH —— 部分更新

PATCH /api/users/{id} Body: {"name": "Jane"} (only changed fields) → 200 OK → 404 Not Found

PATCH 只携带发生变更的字段。模板中update_user的实现很好地演示了这一语义:用update.model_dump(exclude_unset=True)只取出客户端显式设置的字段,再逐项应用到既有对象上,避免把未传字段误置为空,见 rest-api-template.py。

2.5 DELETE —— 删除资源

DELETE /api/users/{id} → 204 No Content (deleted) → 404 Not Found → 409 Conflict (can't delete due to references)

删除成功返回204 No Content(无响应体);若资源被外键/引用约束而无法删除,应返回409 Conflict说明状态冲突。模板中delete_user先调用get_user校验资源存在再返回 204,见 rest-api-template.py。

2.6 状态码速查表

原文档给出的完整状态码指南如下,这也是 api-design-checklist.md "Status Codes" 检查清单的直接依据:

状态码语义
200 OK成功的 GET、PATCH、PUT
201 Created成功的 POST
204 No Content成功的 DELETE
400 Bad Request请求格式错误
401 Unauthorized需要认证
403 Forbidden已认证但权限不足
404 Not Found资源不存在
409 Conflict状态冲突(如邮箱重复)
422 Unprocessable Entity校验失败
429 Too Many Requests被限流
500 Internal Server Error服务端错误
503 Service Unavailable临时不可用

三、过滤、排序与搜索

集合端点通过查询参数承载过滤/排序/搜索能力,保持 URL 干净且语义明确:

# Filtering GET /api/users?status=active GET /api/users?role=admin&status=active # Sorting GET /api/users?sort=created_at GET /api/users?sort=-created_at (descending) GET /api/users?sort=name,created_at # Searching GET /api/users?search=john GET /api/users?q=john # Field selection (sparse fieldsets) GET /api/users?fields=id,name,email

实现约定:排序参数用字段名前缀-表示降序,逗号分隔多级排序;搜索参数search/q对应全文检索;fields允许客户端按需选择返回字段(sparse fieldsets),减少传输体积。

模板中list_users端点把status(枚举过滤)与search(关键词搜索)直接建模为可选查询参数,并用 FastAPI 的Query附加约束(page >= 1、page_size介于 1 与 100 之间),见 rest-api-template.py。

四、分页模式

4.1 基于偏移量(Offset-Based)分页

适合中小规模数据集,实现简单:

GET /api/users?page=2&page_size=20 Response: { "items": [...], "page": 2, "page_size": 20, "total": 150, "pages": 8 }

模板中通过PaginationParams(page默认 1、page_size默认 20、上限 100)与PaginatedResponse两个 Pydantic 模型固化了这套响应结构,页数计算采用向上取整(total + page_size - 1) // page_size,见 rest-api-template.py 与 rest-api-template.py。

4.2 基于游标(Cursor-Based)分页

适合大数据集与高频写入场景:游标编码了最后一条记录的位置,新数据插入不会导致页码漂移、重复或遗漏:

GET /api/users?limit=20&cursor=eyJpZCI6MTIzfQ Response: { "items": [...], "next_cursor": "eyJpZCI6MTQzfQ", "has_more": true }

4.3 Link Header 分页(纯 RESTful 风格)

把分页导航放入 HTTP 响应头,响应体只含数据本身:

GET /api/users?page=2 Response Headers: Link: <https://api.example.com/users?page=3>; rel="next", <https://api.example.com/users?page=1>; rel="prev", <https://api.example.com/users?page=1>; rel="first", <https://api.example.com/users?page=8>; rel="last"

选择哪种模式应在设计期定下来:api-design-checklist.md 的 Pagination 检查项要求所有集合端点均分页、明确默认页大小与上限、携带分页元数据,并"选择 cursor 或 offset 模式之一"。

五、版本化策略

版本化是 API 演进的护栏。原文档给出三种主流方案及其取舍:

URL 版本化(推荐)

/api/v1/users /api/v2/users Pros: Clear, easy to route Cons: Multiple URLs for same resource

Header 版本化

GET /api/users Accept: application/vnd.api+json; version=2 Pros: Clean URLs Cons: Less visible, harder to test

查询参数版本化

GET /api/users?version=2 Pros: Easy to test Cons: Optional parameter can be forgotten

原文档明确推荐 URL 版本化——它直观、易于路由与缓存区分。api-design-checklist.md 同时要求:定义版本化策略(URL/header/query 三选一)、所有端点包含版本、并书面化弃用(deprecation)政策。

六、限流(Rate Limiting)

6.1 限流响应头

标准限流头让客户端可以主动感知配额:

X-RateLimit-Limit: 1000 X-RateLimit-Remaining: 742 X-RateLimit-Reset: 1640000000 Response when limited: 429 Too Many Requests Retry-After: 3600

被限流时必须返回429,并附Retry-After指示客户端多久后重试。

6.2 滑动窗口实现模式

原文档给出了一个可直接运行的固定窗口/滑动窗口限流器:

from fastapi import HTTPException, Request from datetime import datetime, timedelta class RateLimiter: def __init__(self, calls: int, period: int): self.calls = calls self.period = period self.cache = {} def check(self, key: str) -> bool: now = datetime.now() if key not in self.cache: self.cache[key] = [] # Remove old requests self.cache[key] = [ ts for ts in self.cache[key] if now - ts < timedelta(seconds=self.period) ] if len(self.cache[key]) >= self.calls: return False self.cache[key].append(now) return True limiter = RateLimiter(calls=100, period=60) @app.get("/api/users") async def get_users(request: Request): if not limiter.check(request.client.host): raise HTTPException( status_code=429, headers={"Retry-After": "60"} ) return {"users": [...]}

该实现以客户端 IP(request.client.host)为限流键,在窗口内裁剪过期时间戳并计数。它演示了限流的完整形态;生产环境建议换用 Redis 等集中式存储以支持多实例部署。api-design-checklist.md 的 Rate Limiting 检查项包括:按端点/用户定义限额、返回限流头、超限返回 429、提供Retry-After。

七、认证与授权

Authorization: Bearer eyJhbGciOiJIUzI1NiIs... 401 Unauthorized - Missing/invalid token 403 Forbidden - Valid token, insufficient permissions
X-API-Key: your-api-key-here

两条核心区分原则:

  • 401 Unauthorized:认证缺失或令牌无效(你是谁?);
  • 403 Forbidden:令牌有效但权限不足(你能干什么?)。

两种常见机制:Bearer Token(JWT 等,承载身份与声明)与 API Key(常用于服务间调用/第三方集成,通过X-API-Key头传递)。api-design-checklist.md 的检查项要求在所有端点实施授权检查、正确区分 401/403、并处理令牌过期。

八、统一错误响应格式

8.1 错误响应结构

所有错误返回一致的 JSON 结构,客户端才能可靠解析:

{ "error": { "code": "VALIDATION_ERROR", "message": "Request validation failed", "details": [ { "field": "email", "message": "Invalid email format", "value": "not-an-email" } ], "timestamp": "2025-10-16T12:00:00Z", "path": "/api/users" } }

字段设计要点:

  • code:机器可读的错误码,便于客户端程序化处理;
  • message:人类可读的概括;
  • details:字段级错误明细(含字段名、原因、错误值);
  • timestamp/path:便于定位与排查。

模板通过 Pydantic 模型与全局异常处理器把这一格式固化为统一出口:ErrorDetail(field/message/code)与ErrorResponse(error/message/details),并在http_exception_handler中把任何HTTPException统一转换成该 JSON 形态,见 rest-api-template.py。404 场景在get_user中以detail={"message": "User not found", "details": {"id": user_id}}演示了带明细的错误构造,见 rest-api-template.py。

8.2 状态码选用指南

上文 2.6 节的状态码表就是错误语义的骨架。补充两点:409 Conflict适用于"状态冲突"(如注册重复邮箱);422专用于字段/业务校验失败。这两者与 400(语法错误)要区分开。

九、缓存策略

9.1 缓存头

# Client caching Cache-Control: public, max-age=3600 # No caching Cache-Control: no-cache, no-store, must-revalidate # Conditional requests ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4" If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4" → 304 Not Modified
  • Cache-Control:声明可缓存性与有效期;
  • ETag:资源内容的指纹;客户端带If-None-Match发起条件请求,服务端比对未变化时返回304 Not Modified(无响应体),显著节省带宽。

注意区分两类缓存:客户端/CDN 缓存(上述头)与服务端缓存(如对高频只读查询做内存/Redis 缓存)。api-design-checklist.md 的 Performance 检查项同时覆盖"缓存策略定义"与"缓存头正确设置"。

十、批量操作

当单次请求需要操作多条记录时,提供专用批量端点,避免客户端发 N 次请求:

POST /api/users/batch { "items": [ {"name": "User1", "email": "user1@example.com"}, {"name": "User2", "email": "user2@example.com"} ] } Response: { "results": [ {"id": "1", "status": "created"}, {"id": null, "status": "failed", "error": "Email already exists"} ] }

批量响应必须逐条报告成功/失败,而不是整体成功或整体失败,以便客户端精确定位失败项并重试。

十一、幂等性(Idempotency)

对容易因重试而重复执行的写操作(典型如创建订单),引入幂等键:

POST /api/orders Idempotency-Key: unique-key-123 If duplicate request: → 200 OK (return cached response)

客户端为一次业务操作生成唯一键;服务端收到重复键时直接返回首次处理的结果(通常缓存该响应),从而在网络重试、客户端重发等场景下保证业务结果不重复。POST(默认非幂等)+ 幂等键组合是支付、下单等场景的标准实践;PUT/DELETE 本身就幂等,通常无需幂等键。

十二、CORS 配置

跨域访问是浏览器端调用的必答题。模板给出了 FastAPI 的 CORS 中间件配置并附生产注意事项:

from fastapi.middleware.cors import CORSMiddleware app.add_middleware( CORSMiddleware, allow_origins=["https://example.com"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], )

rest-api-template.py 中提供了更保守的默认版:allow_origins=["*"]且allow_credentials=False,并明确注释了生产化要求——使用具体来源列表;如需携带 Cookie/认证头则开启allow_credentials=True但必须收紧allow_origins(通配符*与凭据不能同时安全使用)。同一文件还启用了TrustedHostMiddleware以防 HTTP Host 头攻击,见 rest-api-template.py。

十三、用 OpenAPI 驱动文档

FastAPI 从类型注解自动生成 OpenAPI/Swagger 文档,让文档与实现永不脱节:

from fastapi import FastAPI app = FastAPI( title="My API", description="API for managing users", version="1.0.0", docs_url="/docs", redoc_url="/redoc" ) @app.get( "/api/users/{user_id}", summary="Get user by ID", response_description="User details", tags=["Users"] ) async def get_user( user_id: str = Path(..., description="The user ID") ): """ Retrieve user by ID. Returns full user profile including: - Basic information - Contact details - Account status """ pass

文档化实践包括:summary/response_description描述端点意图,tags分组,Path(..., description=...)描述路径参数,docstring 说明响应内容。模板中app = FastAPI(title="API Template", version="1.0.0", docs_url="/api/docs")与各端点的tags=["Users"]正是这套实践,见 rest-api-template.py。api-design-checklist.md 的 Documentation 检查项要求:生成 OpenAPI/Swagger 规范、所有端点有文档、提供请求/响应示例、文档化错误响应与认证流程。

十四、健康与监控端点

运维可观测性的最低要求是健康检查:

@app.get("/health") async def health_check(): return { "status": "healthy", "version": "1.0.0", "timestamp": datetime.now().isoformat() } @app.get("/health/detailed") async def detailed_health(): return { "status": "healthy", "checks": { "database": await check_database(), "redis": await check_redis(), "external_api": await check_external_api() } }

设计约定:/health用于负载均衡/编排系统的存活探测(轻量、只报整体状态与版本时间戳);/health/detailed面向人工排查,逐项报告数据库、Redis、外部 API 等依赖的连通性。api-design-checklist.md 的 Monitoring 检查项也把"健康检查端点可用"列为必需。

十五、把这些规范落地为一次设计评审

原文档的规范与其配套清单形成了可执行的评审流程,建议在设计或评审 API 时按以下次序过一遍:

  1. 资源设计:名词复数、集合命名一致、层级 ≤ 2、CRUD 与 HTTP 方法正确映射;
  2. HTTP 语义:GET 安全幂等、POST 创建返回 201、PUT 整体替换、PATCH 部分更新、DELETE 返回 204;
  3. 状态码:严格按 2.6 节表格选用,尤其区分 400/401/403/404/409/422/429;
  4. 分页与过滤:集合端点全部分页、明确默认值与上限、携带分页元数据,选 offset 或 cursor 其一;
  5. 版本化:选定策略(推荐 URL 版本化)并书面化弃用政策;
  6. 错误格式:统一错误结构、字段级明细、错误码、时间戳;
  7. 认证授权:定义认证方式、全端点授权检查、正确区分 401/403;
  8. 限流:定义配额、返回限流头、429 + Retry-After;
  9. 文档与测试:OpenAPI 自动生成、错误场景与边界用例覆盖;
  10. 安全与性能:输入校验、SQL 注入/XSS 防护、CORS 收紧、HTTPS、查询优化与 N+1 预防、缓存与监控就绪。

以上每一条都可以在 api-design-checklist.md 中找到对应的勾选项(该清单还额外覆盖 GraphQL 专用检查项:Schema 优先、查询深度/复杂度限制、DataLoader 防 N+1、Relay 分页、持久化查询等),并可用 rest-api-template.py 作为骨架快速搭建符合规范的 FastAPI 服务——在仓库中执行uvicorn运行该模板(见文件尾部入口 rest-api-template.py)即可本地验证本文所述的分页、过滤、错误处理与文档生成行为。

  • AI 技能
  • AI 插件
  • 人工智能

【免费下载链接】agentic-awesome-skills

AAS Core is the local, agent-first control plane for complete catalog discovery, agent-owned selection, stack validation, and planning, backed by 2,600+ agentic skills. Includes CLI, local MCP, catalog, plugins, and Workbench.

项目地址:https://gitcode.com/GitHub_Trending/an/agentic-awesome-skills
点击查看免费下载
上一篇:探索未来3D打印新境界:Bambu Studio
下一篇:Enformer深度学习模型终极指南:从原理到实战的完整教程

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询