不是标准,是设计风格
REST(英文:Representational State Transfer,简称REST),通常应用在web应用程序中,提供一套满足特定的约束和原则的接口,用于客户端和服务器交互。REST并没有一个明确的标准,而更像是一种设计的风格。
来源于一篇论文
Roy Felding 在他论文 network based software architectures 中首次介绍了这些原则。
文章最后是论文下载链接(中文版)。80多页,概念很多,看起来有点无趣。哈哈。
意义深远
就像REST的作者所说的那样:
"本文研究计算机科学两大前沿----软件和网络----的交叉点。长期以来,软件研究主要关注软件设计的分类、设计方法的演化,很少客观地评估不同的设计选择对系统行为的影响。而相反地,网络研究主要关注系统之间通信行为的细节、如何改进特定通信机制的表现,常常忽视了一个事实,那就是改变应用程序的互动风格比改变互动协议,对整体表现有更大的影响。我这篇文章的写作目的,就是想在符合架构原理的前提下,理解和评估以网络为基础的应用软件的架构设计,得到一个功能强、性能好、适宜通信的架构。"
基于HTTP
因为大部分用于web应用,底层通讯肯定还是http协议。比如GET,POST那些。这些也是客户端唯一可以访问服务端的方式。
URI
HTTP协议中有个很重要的概念:URI(注意不是URL,二者区别请自行搜索学习)
URI,是uniform resource identifier,统一资源标识符,用来唯一的标识一个资源。在RESTful架构中,每个网址代表一种资源(resource)。
网上的一些例子,
ftp://ftp.is.co.za/rfc/rfc1808.txt (also a URL because of the protocol)
http://www.ietf.org/rfc/rfc2396.txt (also a URL because of the protocol)
ldap://[2001:db8::7]/c=GB?objectClass?one (also a URL because of the protocol)
mailto:John.Doe@example.com (also a URL because of the protocol)
news:comp.infosystems.www.servers.unix (also a URL because of the protocol)
tel:+1-816-555-1212
telnet://192.0.2.16:80/ (also a URL because of the protocol)
urn:oasis:names:specification:docbook:dtd:xml:4.1.2
从上面这个例子也可以看出,大部分REST API都是在某个域名之下,这也是实现REST API一个常用的方式。
知乎上的一个例子
比如在JDK中sun公司提供的简易HttpServer实现中
public void handle(final HttpExchange exchange)throws Exception
方法中,根据exchange对象可以拿到访问Http请求的URI对象,
ps:
http://127.0.0.1:8080/cmd_helloworld/?name=guowuxin
此时URI uri = exchange.getRequestURI();
通过uri可以拿到连接的各部分内容:
uri.getPath() --------------------> /cmd_helloworld 注意有斜杠
uri.getQuery()----------------------> name=guowuxin
作者:郭无心
链接:https://www.zhihu.com/question/21950864/answer/66779836
来源:知乎
著作权归作者所有,转载请联系作者获得授权。
应用实例
微博 API Error code
论文里对状态码有描述:
同样地,HTTP需要一个通用的规则来解释新的响应状态码,这样新的响应能够进行部 署而不会严重损害老的客户端。因此我们扩大了这个规则,规定每个状态码属于一个类别, 通过三位十进制数的第一位数字来表示:100-199表示消息中包含一个临时的信息响应, 200-299表示请求成功,300-399表示请求需要被重定向到另一个资源,400-499表示客户 端发生了一个不应该重复的错误,500-599表示服务器端遇到了一个错误,但是客户端稍后 可以得到一个更好的响应(或者通过某个其他服务器)。如果接收者不理解一个消息中的状 态码的特定语义,那么它们必须将该状态码按照与同一类别中状态码为x00时相同的方式来 处理。就像是方法名称的规则一样,这个可扩展性的规则在当前的架构上添加了一个需求, 这样架构就能够预见到未来的改变。改变因此能够被部署在一个现有架构之上,而无须害怕 出现不利的组件反应(adverse component reactions)。
Github API v3
比如我想获取一个github上的项目的详细信息,通过API可以拿到。
比如获取用户的基本信息,示例如下:
# GET /users/defunkt
curl https://api.github.com/users/defunkt
{
"login": "defunkt",
"id": 2,
"url": "https://api.github.com/users/defunkt",
"html_url": "https://github.com/defunkt",
...
}
另外有一点,Github API把版本号放在了URL的路径中,这个在很多参考资料中都不建议。一个很重要的原因是这样的设计,版本更新都会导致URL更新。不过这样设计的好处是方便直观,也有人推崇。
尽量使用JSON,避免使用XML
如果你做的项目多,会发现REST+JSON基本是个标准组合了。之所以没有用XML我觉得是JSON相对于XML更加简单,易读。作为开发者,我个人的经验是如果API响应的数据是JSON,我更容易发现里面的错误。
RESTful架构有一些典型的设计误区
最常见的一种设计错误,就是URI包含动词。因为"资源"表示一种实体,所以应该是名词,URI不应该有动词,动词应该放在HTTP协议中。举例来说,某个URI是/posts/show/1,其中show是动词,这个URI就设计错了,正确的写法应该是/posts/1,然后用GET方法表示show。
如果某些动作是HTTP动词表示不了的,你就应该把动作做成一种资源。比如网上汇款,从账户1向账户2汇款500元,错误的URI是:
POST /accounts/1/transfer/500/to/2
正确的写法是把动词transfer改成名词transaction,资源不能是动词,但是可以是一种服务:
POST /transaction HTTP/1.1
Host: 127.0.0.1
from=1&to=2&amount=500.00
另一个设计误区,就是在URI中加入版本号:
http://www.example.com/app/1.0/foo
http://www.example.com/app/1.1/foo
http://www.example.com/app/2.0/foo
因为不同的版本,可以理解成同一种资源的不同表现形式,所以应该采用同一个URI。版本号可以在HTTP请求头信息的Accept字段中进行区分(参见Versioning REST Services):
Accept: vnd.example-com.foo+json; version=1.0
Accept: vnd.example-com.foo+json; version=1.1
Accept: vnd.example-com.foo+json; version=2.0
一些好玩有用的资料
搜索API
APIs.io - the API search engine
ProgrammableWeb
Nytimes,使用这个API,开发者可以调用到几百万份结构化过的数据,从1981 年至今,纽约时报报道的事件,畅销书,甚至房地产等等
Nytimes
参考