前言
前面我们说了,如果API的设计更规范更合理,在很大程度上能够提高联调的效率,降低沟通成本。那么什么是好的API设计?这里我们不得不提到REST API。
关于REST API的书籍很多,但是完整完善实践丰富的设计指导并不多见,我们有幸看到了微软团队的作品——Microsoft REST API Guidelines,因此才有了此篇内容。
由于公众号文章内容字数有限,因此我们将翻译稿拆分并分享出来,并且给出英文对照。翻译的不对之处,请多多指教。
上篇内容:
7.4.1 POST
POST operations SHOULD support the Location response header to specify the location of any created resource that was not explicitly named, via the Location header.
POST 操作应该支持响应头部信息输出位置URL,通过响应头部信息中的Location信息明确已创建资源的URL位置。
PS:大概意思是,创建一个资源时,响应头部信息应输出新资源的路径URL。
As an example, imagine a service that allows creation of hosted servers, which will be named by the service:
例如,一个服务允许创建并命名托管服务器:
POST http://api.contoso.com/account1/servers
The response would be something like:
响应将会是这个样子:
-
201 Created
-
Location:http://api.contoso.com/account1/servers/server321
Where "server321" is the service-allocated server name.
“server321” 是服务创建的托管服务器的名称。
Services MAY also return the full metadata for the created item in the response.
服务也可以在响应中返回创建项的完整元数据。
7.4.2 PATCH
PATCH has been standardized by IETF as the method to be used for updating an existing object incrementally (see [RFC 5789][rfc-5789]).
PATCH 已经被 IETF 标准化,用来对已存在对象(已知资源)进行局部更新。(参考 [RFC 5789][rfc-5789])。
PS:PATCH方法是对PUT的补充,用来对已知资源进行局部更新。
Microsoft REST API Guidelines compliant APIs SHOULD support PATCH.
符合 Microsoft REST API 指南的 API 应该支持 PATCH 方法。
7.4.3 Creating resources via PATCH (UPSERT semantics) 通过 PATCH 创建资源(UPSERT 定义)
Services that allow callers to specify key values on create SHOULD support UPSERT semantics, and those that do MUST support creating resources using PATCH.
允许调用者在创建资源时指定 key 的服务应该支持 UPSERT ,支持此方法的服务也必须支持通过 PATCH 创建资源。
PS:UPSERT即更新插入,通过PATCH方法,允许指定Key来创建资源,例如通过PATCH方法创建UserId为88的用户。
Demo:
curl https://yourInstance.salesforce.com/services/data/v20.0/sobjects/Account/customExtIdField__c/11999 -H "Authorization: Bearer token" -H "Content-Type: application/json" -d @newrecord.json -X PATCH
{
"Name" : "California Wheat Corporation",
"Type" : "New Customer"
}
成功响应:
{
"id" : "00190000001pPvHAAU",
"errors" : [ ],
"success" : true
}
错误响应:
{
"message" : "The requested resource does not exist",
"errorCode" : "NOT_FOUND"
}
Because PUT is defined as a complete replacement of the content, it is dangerous for clients to use PUT to modify data.
因为 PUT 被定义为完全替换原数据,所以客户端直接使用 PUT方法修改数据是非常危险的。
PS:警告:请不要暴露UpdateTime、UpdateBy等字段。。。
Clients that do not understand (and hence ignore) properties on a resource are not likely to provide them on a PUT when trying to update a resource, hence such properties could be inadvertently removed.
当对资源属性不了解的客户端试图通过 PUT 更新数据时,由于对属性不了解,很可能忽略了某些属性,进而导致这些属性被无意删除。
PS:比如常见的,客户端某些字段就是不填导致的业务流程Game Over。
Services MAY optionally support PUT to update existing resources, but if they do they MUST use replacement semantics (that is, after the PUT, the resource's properties MUST match what was provided in the request, including deleting any server properties that were not provided).
服务可以支持 PUT 更新现有资源,但必须是完整替换(也就是说,在 PUT 后,资源的所有属性必须与请求中提供的内容相匹配,包括删除所有未提供的服务端属性)。
Under UPSERT semantics, a PATCH call to a nonexistent resource is handled by the server as a "create," and a PATCH call to an existing resource is handled as an "update." To ensure that an update request is not treated as a create or vice-versa, the client MAY specify precondition HTTP headers in the request.
在使用 UPSERT 的情况下,对不存在资源 使用PATCH 方法时,服务端应进行创建,已存在时,服务端应进行更新处理。为了确保更新请求不被视为创建(反之亦然),客户端可以在请求中指定预先定义的 HTTP 请求头。
The service MUST NOT treat a PATCH request as an insert if it contains an If-Match header and MUST NOT treat a PATCH request as an update if it contains an If-None-Match header with a value of "*".
如果一个 PATCH 请求包含一个 If-Match 请求头,那么服务端绝不能把这个 PATCH 请求当做插入(新增)处理,并且如果它包含一个值为“*”的 If-None-Match 请求头,则不能将该 PATCH 请求当做更新处理。
If a service does not support UPSERT, then a PATCH call against a resource that does not exist MUST result in an HTTP "409 Conflict" error.
如果服务不支持 UPSERT,那么对不存在资源的 PATCH 调用必须返回HTTP状态码为 "409 Conflict"的错误。
7.4.4 Options and link headers
OPTIONS allows a client to retrieve information about a resource, at a minimum by returning the Allow header denoting the valid methods for this resource.
OPTIONS 允许客户端检索有关资源的信息,至少可以返回表示该资源的有效方法的允许的头部信息。
PS:当发起跨域请求时,浏览器会自动发起OPTIONS请求进行检查。
In addition, services SHOULD include a Link header (see [RFC 5988][rfc-5988]) to point to documentation for the resource in question:
此外, 服务应该包括 Link header (参考 [RFC 5988][rfc-5988]) 以指向有关的文档资源:
Link: <{help}>; rel="help"
Where {help} is the URL to a documentation resource.
其中 {help} 是文档资源的 URL.
PS:例如分页时,返回下一步、上一步链接信息。这方面,大家可以参阅Github的API,如下所示:
Link: <https://api.github.com/user/repos?page=3&per_page=100>; rel="next",
<https://api.github.com/user/repos?page=50&per_page=100>; rel="last"
For examples on use of OPTIONS, see [preflighting CORS cross-domain calls][cors-preflight].
有关使用 OPTIONS 的示例,请参考 [preflighting CORS cross-domain calls][cors-preflight]。
7.5. Standard request headers 标准请求头
The table of request headers below SHOULD be used by Microsoft REST API Guidelines services. Using these headers is not mandated, but if used they MUST be used consistently.
表的请求头应该遵循微软REST API服务规范。使用这些标头不是必须的,但是如果用到,那么它们必须使用一致。
All header values MUST follow the syntax rules set forth in the specification where the header field is defined. Many HTTP headers are defined in RFC7231, however a complete list of approved headers can be found in the IANA Header Registry."
所有头部值必须遵循在定义头部字段的规范中所阐述的语法规则(syntax rules )。在HTC721中定义了许多HTTP报头,但是在IANA报头注册表中可以找到完整的批准报头列表。
Header| Type |Description
头部 | 类型 | 描述
Authorization| String |Authorization header for the request
授权 | 字符 | 授权头部
Date |Date |Timestamp of the request, based on the client's clock, in RFC 5322 date and time format. The server SHOULD NOT make any assumptions about the accuracy of the client's clock. This header MAY be included in the request, but MUST be in this format when supplied. Greenwich Mean Time (GMT) MUST be used as the time zone reference for this header when it is provided. For example: Wed, 24 Aug 2016 18:41:30 GMT. Note that GMT is exactly equal to UTC (Coordinated Universal Time) for this purpose.
日期 | 日期类型 | 请求时间戳,在RFC 5322日期和时间格式中。服务器不应该信任客户端时间。该报头可以包含在请求中,但在提供时必须以这种格式。当提供该报头时,必须使用格林尼治平均时间(GMT)作为时区参考。例如:星期三,2016年8月24日18:41:30 GMT注意到GMT完全等于UTC(协调的通用时间)。
Accept| Content type |The requested content type for the response such as:
接收 | 内容类型 | 请求响应的请求内容类型,例如application/xml 、text/xml 、application/json 、text/javascript (for JSONP)
Per the HTTP guidelines, this is just a hint and responses MAY have a different content type, such as a blob fetch where a successful response will just be the blob stream as the payload. For services following OData, the preference order specified in OData SHOULD be followed.
根据HTTP指南,这只是一个提示,并且响应可能有不同的内容类型,例如获取一个对象,只有返回了对象流才算是成功的返回。如果服务是OData协议,应该遵循ODATA中指定的优先要求和顺序。
Accept-Encoding | Gzip, deflate | REST endpoints SHOULD support GZIP and DEFLATE encoding, when applicable. For very large resources, services MAY ignore
