`

HTTP API Design Guide(HTTP API接口设计指南)

 
阅读更多

原文在这里:https://github.com/interagent/http-api-design

 

用我拙劣的英文水平翻译一下,也是练练~

HTTP API Design Guide(HTTP接口设计指南

Introduction(介绍)

This guide describes a set of HTTP+JSON API design practices, originally extracted from work on theHeroku Platform API.

本指南描述了一系列关于HTTP+JSON的接口设计实践,最初是由 Heroku(云平台)接口的工作演进而来。

This guide informs additions to that API and also guides new internal APIs at Heroku. We hope it’s also of interest to API designers outside of Heroku.

本指南充实了那部分API,并且也为Heroku新的内部API提供了指导,我们期待也能为Heroku外部的设计者提供便利。

Our goals here are consistency and focusing on business logic while avoiding design bikeshedding. We’re looking for a good, consistent, well-documented way to design APIs, not necessarily the only/ideal way.

我们的目标是避免无用的设计,持续专注于业务逻辑。我们试图寻找一个比较好的,具备一致性的、具有良好的文档记录的API设计,但不一定是唯一/最好的方法。

We assume you’re familiar with the basics of HTTP+JSON APIs and won’t cover all of the fundamentals of those in this guide.

我们假设你对HTTP+JSON的API有一定的基础,不希望在本指南中覆盖所有的基本概念。

We welcome contributions to this guide.

我们欢迎对本指南的贡献。

 

Contents(内容

 

Foundations(基础

Require TLS(强制要求TLS

Require TLS to access the API, without exception. It’s not worth trying to figure out or explain when it is OK to use TLS and when it’s not. Just require TLS for everything.

强制要求使用TLS来访问API,没有例外!解释或说明什么时候应该使用TLS是不值得的,任何时间都不合适,直接要求在任何情况下使用TLS。

Respond to non-TLS requests with 403 Forbidden. Redirects are discouraged since they allow sloppy/bad client behaviour without providing any clear gain. Clients that rely on redirects double up on server traffic and render TLS useless since sensitive data will already have been exposed during the first call.

对任何没有使用TLS的请求返回“403 Forbidden”。我们允许当收到一个草率的没有提供任何清晰收益的客户端请求时,重定向也是不可接受的,不断重定向的客户端请求会导致服务器端请求双倍增加,并且第一次调用可能就已经暴漏敏感数据时,使用TLS也是没有意义的。

Version with Accepts header(使用Accept Header传递版本

Version the API from the start. Use the Accepts header to communicate the version, along with a custom content type, e.g.:

从一开始就记录API的版本。使用Accepts头来通信版本,使用一个自定义的content type,例如:

Accept: application/vnd.heroku+json; version=3

Prefer not to have a default version, instead requiring clients to explicitly peg their usage to a specific version.

最好不要有一个默认版本,要求客户端用一个清晰地版本号来限制它们的使用。

Support caching with Etags(使用Etags支持缓存

Include an ETag header in all responses, identifying the specific version of the returned resource. The user should be able to check for staleness in their subsequent requests by supplying the value in theIf-None-Match header.

在所有请求中包含一个ETag头,用于识别返回资源的特定版本。使用者可以通过在后面的请求中通过 If-None-Match 头中的值来检查是否过期。

Trace requests with Request-Ids(使用Request Id来追踪请求)

Include a Request-Id header in each API response, populated with a UUID value. If both the server and client log these values, it will be helpful for tracing and debugging requests.

在每一个API响应中包含一个Request-Id头,包含个UUID值。如果服务器和客户端都记录了这些值,对追踪和调试请求时会非常有帮助。

Paginate with Ranges(使用Ranges来进行分页)

Paginate any responses that are liable to produce large amounts of data. Use Content-Range headers to convey pagination requests. Follow the example of the Heroku Platform API on Ranges for the details of request and response headers, status codes, limits, ordering, and page-walking.

分页响应倾向于用来产生大量数据,使用Content-Range头来传递分页请求。遵照Heroku Platform API onRanges的例子,可以看到详细过程,包括请求和响应头、状态码、限制、排序及页遍历。

Requests(请求

Return appropriate status codes(返回合适的状态码

Return appropriate HTTP status codes with each response. Successful responses should be coded according to this guide:

对每一个请求返回合适的HTT状态码,成功的响应码应遵照如下指南:

  • 200: Request succeeded for a GET calls, and for DELETE or PATCH calls that complete synchronously
  • 200:表示对一个GET请求、完成同步的DELETE/PATCH请求返回成功
  • 201: Request succeeded for a POST call that completes synchronously
  • 201:表示对一个完成同步的POST请求返回成功
  • 202: Request accepted for a POSTDELETE, or PATCH call that will be processed asynchronously
  • 202:表示对一个POST、DELETE或PATCH请求正在处理异步数据表示接受
  • 206: Request succeeded on GET, but only a partial response returned: see above on ranges
  • 206:表示对一个返回部分响应的GET请求返回成功,参考上面的“ranges”。

Pay attention to the use of authentication and authorization error codes:

注意对于授权和认证错误得返回码使用:

  • 401 Unauthorized: Request failed because user is not authenticated
  • 401 Unauthroized:由于用户未认证返回失败
  • 403 Forbidden: Request failed because user does not have authorization to access a specific resource
  • 403 Forbidden:由于用户为获得特定资源的访问权限返回失败

Return suitable codes to provide additional information when there are errors:

当发生错误时返回特定的状态吗来携带额外的信息:

  • 422 Unprocessable Entity: Your request was understood, but contained invalid parameters
  • 422 Unprocessable Entity:你的请求已经被理解,但包含非法参数。
  • 429 Too Many Requests: You have been rate-limited, retry later
  • 429 Too Many Requests:你被限速了,稍后重试
  • 500 Internal Server Error: Something went wrong on the server, check status site and/or report the issue
  • 500 Internal Server Error:服务器端发生错误,检查站点状态或报告错误

Refer to the HTTP response code spec for guidance on status codes for user error and server error cases.

参考HTTP response code spec参考对于用户错误和服务器端错误的状态码。

Provide full resources where available(提供所有可用的资源

Provide the full resource representation (i.e. the object with all attributes) whenever possible in the response. Always provide the full resource on 200 and 201 responses, including PUT/PATCH andDELETE requests, e.g.:

提供可能会用于响应的全部的资源展现(包含全部属性的对象等等)。始终在200和201响应中提供全部的资源,包括PUT/PATCH和DELETE请求,例如:

$ curl -X DELETE \  
  https://service.com/apps/1f9b/domains/0fd4

HTTP/1.1 200 OK
Content-Type: application/json;charset=utf-8
...
{
  "created_at": "2012-01-01T12:00:00Z",
  "hostname": "subdomain.example.com",
  "id": "01234567-89ab-cdef-0123-456789abcdef",
  "updated_at": "2012-01-01T12:00:00Z"
}

202 responses will not include the full resource representation, e.g.:

202响应不会包括所有的资源展现,例如:

$ curl -X DELETE \  
  https://service.com/apps/1f9b/dynos/05bd

HTTP/1.1 202 Accepted
Content-Type: application/json;charset=utf-8
...
{}

Accept serialized JSON in request bodies(在请求体中支持序列化的JSON数据)

Accept serialized JSON on PUT/PATCH/POST request bodies, either instead of or in addition to form-encoded data. This creates symmetry with JSON-serialized response bodies, e.g.:

在PUT/PATCH/POST请求体中支持序列化的JSON数据,代替或者作为表单式的数据的补充,这样可以相应的在响应中使用序列化的JSON数据,达到完美对称,例如:

$ curl -X POST https://service.com/apps \
    -H "Content-Type: application/json" \
    -d '{"name": "demoapp"}'

{
  "id": "01234567-89ab-cdef-0123-456789abcdef",
  "name": "demoapp",
  "owner": {
    "email": "username@example.com",
    "id": "01234567-89ab-cdef-0123-456789abcdef"
  },
  ...
}

Use consistent path formats(使用一致性路径格式

Resource names(资源名称

Use the plural version of a resource name unless the resource in question is a singleton within the system (for example, in most systems a given user would only ever have one account). This keeps it consistent in the way you refer to particular resources.

除非在系统之外的问题中的资源是一个个例(例如,在大多数系统中一个给定的用户希望只有一个账户),否则不要使用复数版本的路径名称,可以通过提及一个特殊资源的方式来保持一致性。

Actions(做法

Prefer endpoint layouts that don’t need any special actions for individual resources. In cases where special actions are needed, place them under a standard actions prefix, to clearly delineate them:

更倾向于终端层面对于独立的资源不需要任何特殊的做法,万一哪里需要特殊处理,将他们置于一个标准处理的前缀中,清晰地进行描述。

/resources/:resource/actions/:action

e.g.

/runs/{run_id}/actions/stop

Downcase paths and attributes(小写路径和属性

Use downcased and dash-separated path names, for alignment with hostnames, e.g:

使用小写和斜杠分割的路径名称,在主机名后面,例如:

service-api.com/users
service-api.com/app-setups

Downcase attributes as well, but use underscore separators so that attribute names can be typed without quotes in JavaScript, e.g.:

同样小写属性名,但使用下划线来分隔属性名,这样在js里可以省略引号,例如:

service_class: "first"

Support non-id dereferencing for convenience(支持非ID进行关联以方便使用

In some cases it may be inconvenient for end-users to provide IDs to identify a resource. For example, a user may think in terms of a Heroku app name, but that app may be identified by a UUID. In these cases you may want to accept both an id or name, e.g.:

对最终用户来说,在某些情况下使用ID来识别一个资源是不方便的,例如,一个用户记住了一个Heroku应用名,但是那个应用可能用一个UUID来识别,在这些情况下你需要同时接受ID和名称,例如:

$ curl https://service.com/apps/{app_id_or_name}
$ curl https://service.com/apps/97addcf0-c182
$ curl https://service.com/apps/www-prod

Do not accept only names to the exclusion of IDs.

不要只支持名称而不支持ID。

Minimize path nesting(最小化路径网

In data models with nested parent/child resource relationships, paths may become deeply nested, e.g.:

在数据模型中使用网状的父子资源关系,路径可能会比较深,例如:

/orgs/{org_id}/apps/{app_id}/dynos/{dyno_id}

Limit nesting depth by preferring to locate resources at the root path. Use nesting to indicate scoped collections. For example, for the case above where a dyno belongs to an app belongs to an org:

通过尽量使用根路径定位资源来限制最大深度,例如对于上述的例子当一个dynos属于一个app,app又属于一个org,使用网状来展示范围容器:

/orgs/{org_id}
/orgs/{org_id}/apps
/apps/{app_id}
/apps/{app_id}/dynos
/dynos/{dyno_id}

Responses(响应

Provide resource (UU)IDs(提供资源UUID)

Give each resource an id attribute by default. Use UUIDs unless you have a very good reason not to. Don’t use IDs that won’t be globally unique across instances of the service or other resources in the service, especially auto-incrementing IDs.

默认给每一个资源配备ID属性,除非你有一个更好的理由不去这么做。不使用Id,那么整个资源实例或者资源就不会有一个全局唯一的标示,尤其是使用自增ID。

Render UUIDs in downcased 8-4-4-4-12 format, e.g.:

使用小写格式来提交UUID,例如:

"id": "01234567-89ab-cdef-0123-456789abcdef"

Provide standard timestamps(提供标准时间戳

Provide created_at and updated_at timestamps for resources by default, e.g:

默认给所有资源提供created_at和updated_at时间戳,例如:

{
  ...
  "created_at": "2012-01-01T12:00:00Z",
  "updated_at": "2012-01-01T13:00:00Z",
  ...
}

These timestamps may not make sense for some resources, in which case they can be omitted.

这些时间戳可能对一些资源没有意义,某些情况下可能会被遗漏

Use UTC times formatted in ISO8601(使用UTC时间格式(ISO8601))

Accept and return times in UTC only. Render times in ISO8601 format, e.g.:

接受和返回UTC格式的时间,符合ISO8601标准,例如:

"finished_at": "2012-01-01T12:00:00Z"

Nest foreign key relations(构建外键关联

Serialize foreign key references with a nested object, e.g.:

使用一个链接对象序列化外键关联,例如:

{
  "name": "service-production",
  "owner": {
    "id": "5d8201b0..."
  },
  ...
}

Instead of e.g:

使用:

{
  "name": "service-production",
  "owner_id": "5d8201b0...",
  ...
}

This approach makes it possible to inline more information about the related resource without having to change the structure of the response or introduce more top-level response fields, e.g.:

这个方法在无需改变响应结构或者引入更多顶层属性的同时,使得关联资源响应能够内嵌更多的信息,例如:

{
  "name": "service-production",
  "owner": {
    "id": "5d8201b0...",
    "name": "Alice",
    "email": "alice@heroku.com"
  },
  ...
}

Generate structured errors(生成结构化错误

Generate consistent, structured response bodies on errors. Include a machine-readable error id, a human-readable error message, and optionally a url pointing the client to further information about the error and how to resolve it, e.g.:

生成一致的、结构化的响应错误,包含一个机器可读的错误ID,一个人可读的错误信息,以及可选的一个url,用于告诉客户端更多关于错误和如何解决它的信息,例如:

HTTP/1.1 429 Too Many Requests
{
  "id":      "rate_limit",
  "message": "Account reached its API rate limit.",
  "url":     "https://docs.service.com/rate-limits"
}

Document your error format and the possible error ids that clients may encounter.

用文档记录所有客户端可能遇到的错误格式及错误ID。

Show rate limit status(显示限速状态

Rate limit requests from clients to protect the health of the service and maintain high service quality for other clients. You can use a token bucket algorithm to quantify request limits.

Return the remaining number of request tokens with each request in the RateLimit-Remainingresponse header.

限制客户端访问能够保护服务的健康状态,同时保持对其他客户端的高服务可用性。你可以使用一个令牌桶算法来限制请求,对每一个请求使用RateLimit-Remaining响应头返回请求令牌的保有数量。

Keep JSON minified in all responses(在所有请求中最小化JSON数据

Extra whitespace adds needless response size to requests, and many clients for human consumption will automatically "prettify" JSON output. It is best to keep JSON responses minified e.g.:

额外的空格会导致在响应中不必要浪费,很多用于人类消费的客户端会“美化”JSON输出,所以最好在响应中最小化JSON数据,例如:

{"beta":false,"email":"alice@heroku.com","id":"01234567-89ab-cdef-0123-456789abcdef","last_login":"2012-01-01T12:00:00Z", "created_at":"2012-01-01T12:00:00Z","updated_at":"2012-01-01T12:00:00Z"}

Instead of e.g.:

代替下面的:

{
  "beta": false,
  "email": "alice@heroku.com",
  "id": "01234567-89ab-cdef-0123-456789abcdef",
  "last_login": "2012-01-01T12:00:00Z",
  "created_at": "2012-01-01T12:00:00Z",
  "updated_at": "2012-01-01T12:00:00Z"
}

You may consider optionally providing a way for clients to retreive more verbose response, either via a query parameter (e.g. ?pretty=true) or via an Accept header param (e.g. Accept: application/vnd.heroku+json; version=3; indent=4;).

你可能考虑选择提供给客户端一种获取更多响应的方式:通过一个查询参数(例如:?pretty=true)或者通过一个Accept头参数(例如Accept:application/vnd.heroku+json; version=3; indent=4)

Artifacts(人性化

Provide machine-readable JSON schema(提供机器可读的JSON策略

Provide a machine-readable schema to exactly specify your API. Use prmd to manage your schema, and ensure it validates with prmd verify.

提供一个机器可读的策略,用于精确地定义你的QPI,使用prmd来管理你的策略,并且确保他会使用prmd verify来进行验证。

Provide human-readable docs(提供可读文档

Provide human-readable documentation that client developers can use to understand your API.

If you create a schema with prmd as described above, you can easily generate Markdown docs for all endpoints with with prmd doc.

提供可读性文档,客户端开发者能够用于理解你的API,如果你创造了一个如上所述使用prmd的策略,你可以轻松地使用prmd doc为所有终端生成Markdown文档。

In addition to endpoint details, provide an API overview with information about:

对于终端的细节的补充,提供一个API总览,包含以下信息:

  • Authentication, including acquiring and using authentication tokens.
  • 认证,包括获取和使用认证token
  • API stability and versioning, including how to select the desired API version.
  • API稳定性和版本,包括如何选择所需的API版本
  • Common request and response headers.
  • 一般请求和响应头
  • Error serialization format.
  • 错误信息的序列化格式
  • Examples of using the API with clients in different languages.
  • 使用不同语言做客户端调用API的例子

Provide executable examples(提供可执行的例子

Provide executable examples that users can type directly into their terminals to see working API calls. To the greatest extent possible, these examples should be usable verbatim, to minimize the amount of work a user needs to do to try the API, e.g.:

提供可执行的例子,便于用户在查看API是否正常可用时直达目标。对于最大范围的可能性,这些例子能够按照所示一步步做下来就可以使用,尽量减少当用户尝试使用API时所付出的精力,例如:

$ export TOKEN=... # acquire from dashboard
$ curl -is https://$TOKEN@service.com/users

If you use prmd to generate Markdown docs, you will get examples for each endpoint for free.

如果你使用prmd生成Markdown文档,你需要为每一个终端都设置一个“轻松”的例子。

Describe stability(描述稳定性

Describe the stability of your API or its various endpoints according to its maturity and stability, e.g. with prototype/development/production flags.

描述你的API稳定性或者根据成熟度和稳定性描述终端变化,例如,使用原型/开发/生产 标签。

See the Heroku API compatibility policy for a possible stability and change management approach.

参考Heroku API compatibility policy用于一个可能的稳定性及变化管理方法。

Once your API is declared production-ready and stable, do not make backwards incompatible changes within that API version. If you need to make backwards-incompatible changes, create a new API with an incremented version number.

一旦你的API被声明是生产环境可用的及稳定的,不要做不符合这个版本的回滚或不兼容变更,如果你需要做这样的变更,创建一个新的API并且使用一个增加的版本号。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics