Microsoft API 设计标准
原文地址
:Microsoft API Guidelines >笔者有关于REST 系列文章 笔者之前翻译过一篇来自于PayPal 的RESTful API 标准,其是PayPal 内部遵循的RESTful 的接口规范,本文则是微软提出的API 风格指南,笔者认为二者各有优劣。微软的准则相对更加详细严谨,但是对于复杂资源请求,却没有PayPal 提及的多。本文目前仅包含第一部分的翻译,笔者日后为添加上第二部分。
微软云平台为开发者提供了基于
- 为
Microsoft 提供的所有REST 风格的Endpoints 都遵循一直的实践模式 - 尽可能与目前产业界中大规模使用的
REST/HTTP 的最佳实践相符合 - 保证所有使用
Microsoft 服务的应用开发者能够方便快捷地基于REST 接口进行访问 - 允许服务开发者能够基于之前的工作快速搭建新的接口
- 允许所有的非
Microsoft 合作者也能使用这些规范
在正式介绍本指南之前,推荐阅读如下一些参考资料
- RFC 2616 –
HTTP/1.1 的细节定义 - REST in Practice – 基于
REST 的实践指南 - REST on Wikipedia – 维基百科上关于
REST 的核心概念与思想的介绍
Taxonomy
作为
Errors: 错误
Errors,或者更准确地说,Service Errors,被定义为因为客户端将错误的数据传递给了服务端而导致服务端拒绝该请求。典型的譬如无效的认证状态、错误的参数、未知的版本4xx
系列的
Faults: 故障
Faults,或者说是5xx
系列的
Latency: 延迟
延迟,即是指某个
Time To Complete
提供慢操作的服务必须要追踪Time To Complete
这个测量标准。
Long Running API Faults
对于长期运行的
Client Guidence: 客户端指南
为了保证客户端能够较好地接入
Ignore Rule: 忽略原则
对于松耦合的客户单而言,在真实地获取到数据之前是不知道数据的确切结构的,如果服务端返回了一些并不是客户端所需要的数据,那么客户端应该安全地忽略这些意外的数据。另外在服务端迭代的过程中,可能有部分服务端会添加些额外的域,对于老的客户端而言可能并不需要这些域,从客户端的角度应该选择性地忽略这些域,而服务端必须要在文档中进行注明。
Variable Order Rule: 变量排序原则
客户端在处理服务端的返回数据时,一定不能依赖于返回的$orderBy
关键字来对返回的
Slient Fail Rule
如果客户端是使用服务端提供的一些可选功能,譬如可能发送一些自定义的头部请求项,那么客户端必须要能够在服务器可能无法提供这些可选功能的情况下依然正常工作。
REST Consistency Fundamentals
URL Structure
https://api.contoso.com/v1.0/people/jdoe@contoso.com/inbox
而与之相反的,一个可读性较差的
https://api.contoso.com/EWS/OData/Users('jdoe@microsoft.com')/Folders('AAMkADdiYzI1MjUzLTk4MjQtNDQ1Yy05YjJkLWNlMzMzYmIzNTY0MwAuAAAAAACzMsPHYH6HQoSwfdpDx-2bAQCXhUk6PC1dS7AERFluCgBfAAABo58UAAA=')
另一个常用的模式就是将某个
https://api.contoso.com/v1.0/items?url=https://resources.contoso.com/shoes/fancy
URL 长度
HTTP 协议本身不会对URL 长度有任何限制,服务端必须要能够处理任何有效的URL ,并且对于基于GET 的过长请求也要能够有效处理。当URL 过长导致服务端无法处理时,服务端应该返回414 号错误码。
注意,
Canonical Identifier: 标准的标识符
除了需要提供友好的
https://api.contoso.com/v1.0/people/7011042402/inbox
Supported Verbs: 支持的动词
客户端必须要以合适的
POST
POST http://api.contoso.com/account1/servers
响应值应该是如下这样
201 Created
Location: http://api.contoso.com/account1/servers/server321
利用PATCG 创建资源
允许客户端在创建资源的时候只指定部分键值数据的必须支持409 Conflict
OPTIONS and Link Headers
Link: {help}; rel="help"
Standard Request Headers: 标准请求头
所有遵循
Standard Response Headers
Response Header | Required | Description |
---|---|---|
Date | All responses | 请求的处理完成的时间,以 RFC 3339 格式 |
Content-Type | All responses | The content type |
Content-Encoding | All responses | |
Preference-Applied | When specified in request | Whether a preference indicated in the Prefer request header was applied |
ETag | 当请求的资源包含资源体时 | 包含当前资源的版本信息,与 |
Custom Headers: 自定义请求头
对于某些给定
RFC 3864 中暂定为临时的请求头格式- 请求头应该尽可能地符合使用场景
Specifying Headers as Query Parameters: 以查询参数方式提交自定义请求头
很多时候在进行
PII Parameters: 个人认证信息
鉴于通行的安全与隐私性保护原则,所有关于个人认证的信息不应该放置在
Response Formats: 响应格式
成功的平台总是相似的,它们往往会提供可读性较好并且一致的响应结果,从而使开发者能够尽可能地复用代码来进行响应处理。一般在基于
Client Specified Response Format
在application/json
,并且所有的服务端都应该支持application/json
GET https://api.contoso.com/v1.0/products/user
Accept: application/json
Error Condition Response
对于非成功的场景,开发者应该能够以相同的代码库来处理不同的error
,而值也是一个code
、message
,并且建议包含譬如target
、details
、innererror
这些信息。code
定义,推荐不要超过message
中的值应该是可读的错误的具体描述,主要是为了辅助开发者进行理解,注意,不可以将message
提供本地化服务,因为这样对于开发者变得非常不友好并且难以处理。target
中的值应该指向错误的具体的目标,譬如错误中的属性名。details
中的值必须是一个包含多个code
与message
信息,并且可能包含target
属性。details
中的信息会用于描述请求过程中发生的一些其他错误。innererror
键值对必须包含一个
{
"error": {
"code": "BadArgument",
"message": "Previous passwords may not be reused",
"target": "password",
"innererror": {
"code": "PasswordError",
"innererror": {
"code": "PasswordDoesNotMeetPolicy",
"minLength": "6",
"maxLength": "64",
"characterTypes": ["lowerCase","upperCase","number","symbol"],
"minDistinctCharacterTypes": "2",
"innererror": {
"code": "PasswordReuseNotAllowed"
}
}
}
}
}
上面例子中,基本的错误码为 “BadArgument,",但是服务端在innererror
中提供了更多详细的说明
{
"error": {
"code": "BadArgument",
"message": "Multiple errors in ContactInfo data",
"target": "ContactInfo",
"details": [
{
"code": "NullValue",
"target": "PhoneNumber",
"message": "Phone number must not be null"
},
{
"code": "NullValue",
"target": "LastName",
"message": "Last name must not be null"
},
{
"code": "MalformedValue",
"target": "Address",
"message": "Address is not valid"
}
]
}
}
上例中一次请求里发生了多个错误,这些错误以及信息都包含在了 “details.” 中。我们还推荐服务端在发生错误时添加一个
HTTP Status Codes:HTTP 状态码
我们应当使用标准的
Client Library Optional
开发者应该能够使用多种语言或者平台来进行客户端开发,譬如