1. 在软件与外部环境之间的许多交汇点上,版本控制基本上处于混乱状态 1.1. 不应该为了更新自身系统的API,而让服务消费者被迫与你同时发布新版本 1.2. 多数服务新版本的发布应该具有兼容性 2. 分层的“约定”栈 2.1. 连接握手和持续时间 2.2. 请求组帧 2.3. 内容编码 2.4. 消息语法 2.5. 消息语义 2.6. 鉴权和身份验证 3. 对请求要协变 3.1. covariant request 4. 对响应要逆变 4.1. contravariant response 5. 即 5.1. 可以比以往提出的要求更少 5.2. 可以比以往接受的可选信息更多 5.3. 可以比以往返回的响应更多 5.4. 可以类比必填参数和可选参数 6. 安全的变更 6.1. 在参数上强制执行以前所需约束的子集 6.2. 返回以前可返回值的超集 6.3. 接受以前可以接受的参数的超集 6.4. 要求必须填写以前必填参数的一个子集 7. 生成式测试技术 8. 破坏API的变更 8.1. 减少API破坏性变更影响的第一个先决条件是在请求和回复消息格式中添加一个版本号字段 8.2. 为URL添加版本辨别字段,可以用前缀形式或查询参数来实现 8.2.1. 同一实体的不同表示看起来像是不同的资源,而这在REST世界中是禁忌 8.3. 使用PUT和POST上的Content-Type标头指示正在发送的版本 8.3.1. 可以为版本定义一个媒体类型application/vnd.lendzit.loan-request.v1和一个新的媒体类型application/vnd.lendzit.loan-request.v2 8.3.2. 优点 8.3.2.1. 在数据库中存储的所有URL都可以继续工作,客户端无须更改路由就可升级 8.3.3. 缺点 8.3.3.1. 单单凭借URL已经不够区分版本了,像application/json和text/xml这样的通用媒体类型根本提供不了任何帮助 8.3.3.2. 客户端必须事先知道存在这种特殊的媒体类型,以及所有允许的媒体类型 8.3.3.3. 一些框架虽然支持基于媒体类型的路由,但配置起来会有难度 8.4. 仅针对PUT和POST,在请求正文中添加一个字段来指示预期版本 8.4.1. 优点是不需要路由,易于实施 8.4.2. 缺点是无法涵盖所需要的所有场景 8.5. 使用特定于应用程序的自定义标头指示所需的版本 8.5.1. 可以定义一个类似api-version的标头 8.5.2. 优点是具有完全的灵活性,并且与媒体类型和URL正交 8.5.3. 缺点 8.5.3.1. 要为特定框架编写路由处理器 8.5.3.2. 这个标头是另一个必须与服务消费者分享的秘密 8.6. 服务提供方都必须在一段时间内同时支持旧版本和新版本 8.7. 如果要在一些URL中添加版本信息,那么务必同时在所有路由中都添加这个版本 8.7.1. 即使这次变更只涉及一个路由,也不要强制用户记住哪些版本号对应哪些API 8.8. 只要不影响未来进行的变更,尽可能地减少代码重复 9. 处理其他系统的版本问题 9.1. 软件应该保持杞人忧天的状态 9.2. 虽然请求规范中添加了一些新字段,但并不意味着所有人都会遵守新规范 9.3. 请求端与响应端检查自己是否符合规范 9.4. 将测试分为不同的部分,有助于隔离通信中的故障,并能使代码更加稳健 9.4.1. 我们不会再对另一方的行为做出不合理的假设