Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

License

NotificationsYou must be signed in to change notification settings

bolasblack/http-api-guide

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

74 Commits
 
 
 
 
 
 
 
 

Repository files navigation

文档主要目的是为大家在设计接口时提供建议,给大家参考 HTTP 或者其他协议/指南已经设计过的内容

只是建议,不是必须遵从的要求

大家有什么问题想法或者建议欢迎创建 Issue 或者提交 Pull Request

  • README.md 主要是简单介绍和列出对设计可能会有帮助的资料,少放一些私货
  • SUPPLEMENT.md 有一些更细节的接口设计方面的我自己的想法,全是私货

目录

HTTP 协议

HTTP/1.1

2014 年 6 月的时候 IETF 已经正式的废弃了RFC 2616 ,将它拆分为六个单独的协议说明,并重点对原来语义模糊的部分进行了解释:

相关资料:

HTTP/2

HTTP 协议的 2.0 版本还没有正式发布,但目前已经基本稳定下来了。

2.0 版本的设计目标是尽量在使用层面上保持与 1.1 版本的兼容,所以,虽然数据交换的格式发生了变化,但语义基本全部被保留下来了

因此,作为使用者而言,我们并不需要为了支持 2.0 而大幅修改代码。

URL

URL 的设计都需要遵守RFC 3986 的的规范。

URL 的长度,在 HTTP/1.1: Message Syntax and Routing(RFC 7230) 的3.1.1 小节中有说明,本身不限制长度。但是在实践中,服务器和客户端本身会施加限制*,因此需要根据自己的场景和需求做对应的调整

强烈建议 API 部署 SSL 证书,这样接口传递的数据的安全性才能获得一定的保障。

空字段

接口遵循“输入宽容,输出严格”原则,输出的数据结构中空字段的值一律为null

国际化

语言标签

RFC 5646 (BCP 47) 规定的语言标签的格式如下:

language-script-region-variant-extension-privateuse
  1. language:这部分使用的是 ISO 639-1, ISO 639-2, ISO 639-3, ISO 639-5 中定义的语言代码,必填
    • 这个部分由primary-extlang 两个部分构成
    • primary 部分使用 ISO 639-1, ISO 639-2, ISO 639-3, ISO 639-5 中定义的语言代码,优先使用 ISO 639-1 中定义的条目,比如汉语zh
    • extlang 部分是在某些历史性的兼容性的原因,在需要非常细致地区别primary 语言的时候使用,使用 ISO 639-3 中定义的三个字母的代码,比如普通话cmn
    • 虽然language 可以只写extlang 省略primary 部分,但出于兼容性的考虑,还是建议加上primary 部分
  2. script: 这部分使用的是ISO 15924 (Wikipedia) 中定义的语言代码,比如简体汉字是zh-Hans ,繁体汉字是zh-Hant
  3. region: 这部分使用的是 ISO 3166-1 (Wikipedia) 中定义的地理区域代码,比如zh-Hans-CN 就是中国大陆使用的简体中文。
  4. variant: 用来表示extlang 的定义里没有包含的方言,具体的使用方法可以参考RFC 5646
  5. extension: 用来为自己的应用做一些语言上的额外的扩展,具体的使用方法可以参考RFC 5646
  6. privateuse: 用来表示私有协议中约定的一些语言上的区别,具体的使用方法可以参考RFC 5646

其中只有language 部分是必须的,其他部分都是可选的;不过为了便于编写程序,建议设计接口时约定语言标签的结构,比如统一使用language-script-region 的形式(zh-Hans-CN,zh-Hant-HK 等等)。

语言标签是大小写不敏感的,但按照惯例,建议script 部分首字母大写,region 部分全部大写,其余部分全部小写。

有一点需要注意,任何合法的标签都必须经过 IANA 的认证,已通过认证的标签可以在这个网页查到。此外,网上还有一个非官方的标签搜索引擎

相关资料:

时区

客户端请求服务器时,如果对时间有特殊要求(如某段时间每天的统计信息),则可以参考IETF 相关草案 增加请求头Timezone

Timezone: 2016-11-06 23:55:52+08:00;;Asia/Shanghai

具体格式说明:

Timezone: RFC3339 约定的时间格式;POSIX 1003.1 约定的时区字符串;tz datebase 里的时区名称

客户端最好提供所有字段,如果没有办法提供,则应该使用空字符串

如果客户端请求时没有指定相应的时区,则服务端默认使用最后一次已知时区或者UTC 时间返回相应数据。

PS 考虑到存在夏时制这种东西,所以不推荐客户端在请求时使用 Offset 。

相关资料:

时间格式

时间格式遵循ISO 8601(Wikipedia) 建议的格式:

  • 日期2014-07-09
  • 时间14:31:22+0800
  • 具体时间2007-11-06T16:34:41Z
  • 持续时间P1Y3M5DT6H7M30S (表示在一年三个月五天六小时七分三十秒内)
  • 时间区间2007-03-01T13:00:00Z/2008-05-11T15:30:00Z2007-03-01T13:00:00Z/P1Y2M10DT2H30MP1Y2M10DT2H30M/2008-05-11T15:30:00Z
  • 重复时间R3/2004-05-06T13:00:00+08/P0Y6M5DT3H0M0S (表示从2004年5月6日北京时间下午1点起,在半年零5天3小时内,重复3次)

相关资料:

货币名称

货币名称可以参考 ISO 4217(Wikipedia) 中的约定,标准为货币名称规定了三个字母的货币代码,其中的前两个字母是 ISO 3166-1(Wikipedia) 中定义的双字母国家代码,第三个字母通常是货币的首字母。在货币上使用这些代码消除了货币名称(比如 dollar )或符号(比如 $ )的歧义。

相关资料:

  • 《RESTful Web Services Cookbook 中文版》 3.9 节《如何在表述中使用可移植的数据格式》

请求方法

  • 如果请求头中存在X-HTTP-Method-Override 或参数中存在_method(拥有更高权重),且值为GET,POST,PUT,DELETE,PATCH,OPTIONS,HEAD 之一,则视作相应的请求方式进行处理
  • GET,DELETE,HEAD 方法,参数风格为标准的GET 风格的参数,如url?a=1&b=2
  • POST,PUT,PATCH,OPTIONS 方法
    • 默认情况下请求实体会被视作标准 json 字符串进行处理,当然,依旧推荐设置头信息的Content-Typeapplication/json
    • 在一些特殊接口中(会在文档中说明),可能允许Content-Typeapplication/x-www-form-urlencoded 或者multipart/form-data ,此时请求实体会被视作标准POST 风格的参数进行处理

关于方法语义的说明:

  • OPTIONS 用于获取资源支持的所有 HTTP 方法
  • HEAD 用于只获取请求某个资源返回的头信息
  • GET 用于从服务器获取某个资源的信息
    • 完成请求后返回状态码200 OK
    • 完成请求后需要返回被请求的资源详细信息
  • POST 用于创建新资源
    • 创建完成后返回状态码201 Created
    • 完成请求后需要返回被创建的资源详细信息
  • PUT 用于完整的替换资源或者创建指定身份的资源,比如创建 id 为 123 的某个资源
    • 如果是创建了资源,则返回201 Created
    • 如果是替换了资源,则返回200 OK
    • 完成请求后需要返回被修改的资源详细信息
  • PATCH 用于局部更新资源
    • 完成请求后返回状态码200 OK
    • 完成请求后需要返回被修改的资源详细信息
  • DELETE 用于删除某个资源
    • 完成请求后返回状态码204 No Content

相关资料:

状态码

请求成功

  • 200OK : 请求执行成功并返回相应数据,如GET 成功
  • 201Created : 对象创建成功并返回相应资源数据,如POST 成功;创建完成后响应头中应该携带头标Location ,指向新建资源的地址
  • 202Accepted : 接受请求,但无法立即完成创建行为,比如其中涉及到一个需要花费若干小时才能完成的任务。返回的实体中应该包含当前状态的信息,以及指向处理状态监视器或状态预测的指针,以便客户端能够获取最新状态。
  • 204No Content : 请求执行成功,不返回相应资源数据,如PATCHDELETE 成功

重定向

重定向的新地址都需要在响应头Location 中返回

  • 301Moved Permanently : 被请求的资源已永久移动到新位置
  • 302Found : 请求的资源现在临时从不同的 URI 响应请求
  • 303See Other : 对应当前请求的响应可以在另一个 URI 上被找到,客户端应该使用GET 方法进行请求。比如在创建已经被创建的资源时,可以返回303
  • 307Temporary Redirect : 对应当前请求的响应可以在另一个 URI 上被找到,客户端应该保持原有的请求方法进行请求

条件请求

  • 304Not Modified : 资源自从上次请求后没有再次发生变化,主要使用场景在于实现数据缓存
  • 409Conflict : 请求操作和资源的当前状态存在冲突。主要使用场景在于实现并发控制
  • 412Precondition Failed : 服务器在验证在请求的头字段中给出先决条件时,没能满足其中的一个或多个。主要使用场景在于实现并发控制

客户端错误

  • 400Bad Request : 请求体包含语法错误
  • 401Unauthorized : 需要验证用户身份,如果服务器就算是身份验证后也不允许客户访问资源,应该响应403 Forbidden 。如果请求里有Authorization 头,那么必须返回一个WWW-Authenticate
  • 403Forbidden : 服务器拒绝执行
  • 404Not Found : 找不到目标资源
  • 405Method Not Allowed : 不允许执行目标方法,响应中应该带有Allow 头,内容为对该资源有效的 HTTP 方法
  • 406Not Acceptable : 服务器不支持客户端请求的内容格式,但响应里会包含服务端能够给出的格式的数据,并在Content-Type 中声明格式名称
  • 410Gone : 被请求的资源已被删除,只有在确定了这种情况是永久性的时候才可以使用,否则建议使用404 Not Found
  • 413Payload Too Large :POST 或者PUT 请求的消息实体过大
  • 415Unsupported Media Type : 服务器不支持请求中提交的数据的格式
  • 422Unprocessable Entity : 请求格式正确,但是由于含有语义错误,无法响应
  • 428Precondition Required : 要求先决条件,如果想要请求能成功必须满足一些预设的条件

服务端错误

  • 500Internal Server Error : 服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理。
  • 501Not Implemented : 服务器不支持当前请求所需要的某个功能。
  • 502Bad Gateway : 作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应。
  • 503Service Unavailable : 由于临时的服务器维护或者过载,服务器当前无法处理请求。这个状况是临时的,并且将在一段时间以后恢复。如果能够预计延迟时间,那么响应中可以包含一个Retry-After 头用以标明这个延迟时间(内容可以为数字,单位为秒;或者是一个HTTP 协议指定的时间格式)。如果没有给出这个Retry-After 信息,那么客户端应当以处理 500 响应的方式处理它。

501405 的区别是:405 是表示服务端不允许客户端这么做,501 是表示客户端或许可以这么做,但服务端还没有实现这个功能

相关资料:

身份验证

部分接口需要通过某种身份验证方式才能请求成功(这些接口应该在文档中标注出来),合适的身份验证解决方案目前有两种:

超文本驱动和资源发现

REST 服务的要求之一就是超文本驱动,客户端不再需要将某些接口的 URI 硬编码在代码中,唯一需要存储的只是 API 的 HOST 地址,能够非常有效的降低客户端与服务端之间的耦合,服务端对 URI 的任何改动都不会影响到客户端的稳定。

目前有几种方案试图实现这个效果:

目前所知的方案都实现了发现资源的功能,服务端同时需要实现OPTIONS 方法,并在响应中携带Allow 头来告知客户端当前拥有的操作权限。

数据缓存

大部分接口应该在响应头中携带Last-Modified,ETag,Vary,Date 信息,客户端可以在随后请求这些资源的时候,在请求头中使用If-Modified-Since,If-None-Match 等请求头来确认资源是否经过修改。

如果资源没有进行过修改,那么就可以响应304 Not Modified 并且不在响应实体中返回任何内容。

$ curl -i http://api.example.com/#{RESOURCE_URI}HTTP/1.1 200 OKCache-Control: public, max-age=60Date: Thu, 05 Jul 2012 15:31:30 GMTVary: Accept, AuthorizationETag:"644b5b0155e6404a9cc4bd9d8b1ae730"Last-Modified: Thu, 05 Jul 2012 15:31:30 GMTContent
$ curl -i http://api.example.com/#{RESOURCE_URI} -H"If-Modified-Since: Thu, 05 Jul 2012 15:31:30 GMT"HTTP/1.1 304 Not ModifiedCache-Control: public, max-age=60Date: Thu, 05 Jul 2012 15:31:45 GMTVary: Accept, AuthorizationLast-Modified: Thu, 05 Jul 2012 15:31:30 GMT
$ curl -i http://api.example.com/#{RESOURCE_URI} -H'If-None-Match: "644b5b0155e6404a9cc4bd9d8b1ae730"'HTTP/1.1 304 Not ModifiedCache-Control: public, max-age=60Date: Thu, 05 Jul 2012 15:31:55 GMTVary: Accept, AuthorizationETag:"644b5b0155e6404a9cc4bd9d8b1ae730"Last-Modified: Thu, 05 Jul 2012 15:31:30 GMT

相关资料:

并发控制

不严谨的实现,或者缺少并发控制的PUTPATCH 请求可能导致 “更新丢失”。这个时候可以使用Last-Modified 和/或ETag 头来实现条件请求,支持乐观并发控制。

下文只考虑使用PUTPATCH 方法更新资源的情况。

  • 客户端发起的请求如果没有包含If-Unmodified-Since 或者If-Match 头,那就返回状态码403 Forbidden ,在响应正文中解释为何返回该状态码
  • 客户端发起的请求提供的If-Unmodified-Since 或者If-Match 头与服务器记录的实际修改时间或ETag 值不匹配的时候,返回状态码412 Precondition Failed
  • 客户端发起的请求提供的If-Unmodified-Since 或者If-Match 头与服务器记录的实际修改时间或ETag 的历史值匹配,但资源已经被修改过的时候,返回状态码409 Conflict
  • 客户端发起的请求提供的条件符合实际值,那就更新资源,响应200 OK 或者204 No Content ,并且包含更新过的Last-Modified 和/或ETag 头,同时包含Content-Location 头,其值为更新后的资源 URI

相关资料:

跨域

CORS

接口支持“跨域资源共享”(Cross Origin Resource Sharing, CORS)这里这里这份中文资料有一些指导性的资料。

简单示例:

$ curl -i https://api.example.com -H"Origin: http://example.com"HTTP/1.1 302 Found
$ curl -i https://api.example.com -H"Origin: http://example.com"HTTP/1.1 302 FoundAccess-Control-Allow-Origin:*Access-Control-Expose-Headers: ETag, Link, X-Total-CountAccess-Control-Allow-Credentials:true

预检请求的响应示例:

$ curl -i https://api.example.com -H"Origin: http://example.com" -X OPTIONSHTTP/1.1 302 FoundAccess-Control-Allow-Origin:*Access-Control-Allow-Headers: Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-Requested-WithAccess-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETEAccess-Control-Expose-Headers: ETag, Link, X-Total-CountAccess-Control-Max-Age: 86400Access-Control-Allow-Credentials:true

JSON-P

如果在任何GET 请求中带有参数callback ,且值为非空字符串,那么接口将返回如下格式的数据

$ curl http://api.example.com/#{RESOURCE_URI}?callback=foo
foo({"meta":{"status":200,"X-Total-Count":542,"Link":[{"href":"http://api.example.com/#{RESOURCE_URI}?cursor=0&count=100","rel":"first"},{"href":"http://api.example.com/#{RESOURCE_URI}?cursor=90&count=100","rel":"prev"},{"href":"http://api.example.com/#{RESOURCE_URI}?cursor=120&count=100","rel":"next"},{"href":"http://api.example.com/#{RESOURCE_URI}?cursor=200&count=100","rel":"last"}]},"data":// data})

其他资料

其他接口设计指南

这里还有一些其他参考资料:

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors4

  •  
  •  
  •  
  •  

[8]ページ先頭

©2009-2025 Movatter.jp