Rest api

理解和使用内容协商

我们的开发者在发送一个 REST API 请求的同时,根据应用场景,针对相同的资源,可能会期待不同的返回形式。

比如,我希望根据用户客户端语言,同一个资源的内容可以返回不同的语言。又比如,当我使用 Java 编程的时候,我希望得到 ATOM 格式的返回结果,而当我使用 JavaScript 编程的时候,我希望得到 Json 格式的返回结果。

因此,我们在设计 REST API 的时候,应该提供完备的内容协商能力。

使用 URL 参数进行内容协商

最容易想到的自然是通过 URL 参数进行控制,我们经常看到形如 / 航班号 /entry? format=JSON 这样的 URL。这种方式的优势就是简单灵活, 你可以通过任何 URL 参数来组合你的输出格式。

下面是一个来自 IBM developerWorks 的 API 样例,尝试请求该 API,你可以看到该集合是如何支持不同的输出格式请求的。

清单 3. IBM developerWorks 的文件服务标签云的 API
 REST API 请求,要求返回 XML 格式数据:
 GET  https://www.ibm.com/developerworks/mydeveloperworks
 /files/form/anonymous/api/tags/feed?format=xml
 &scope=document&pageSize=30&sK=cloud&sO=dsc 

 REST API 请求,要求返回 JSON 格式数据:
 GET  https://www.ibm.com/developerworks/mydeveloperworks
 /files/form/anonymous/api/tags/feed?format=json
 &scope=document&pageSize=30&sK=cloud&sO=dsc

使用 Accept 头进行内容协商

使用 URL 参数,简单灵活,但是也由此带来了设计上的随意和不标准。并且,过多的参数会导致 URL 的可读性变差,更有甚者,可能会导致 URL 过长,超出规范,API 请求无法执行。

更为标准的内容协商方式是使用 HTTP 头。我们通常使用 Accept 来设置我们接受的返回结果的内容格式,用 Accept-Charset 来设置字符集,用 Accept-Encoding 来设置数据传输格式,用 Accept-Language 来设置语言。

使用 URI 模式进行内容协商

还有一种模式,就是将协商设置直接作为 URI 的一部分,将不同的返回视为不同的资源,比如 / 航班号 /json 来返回 JSON 格式的结果,用 / 航班号 /atom 来返回 ATOM 格式的结果。

回页首

正确的使用 HTTP 响应代码

作为 API 的设计者,正确的将 API 执行结果和失败原因用清晰简洁的方式传达给客户程序是十分关键的一步。 我们确实可以在 HTTP 的相应内容中描述是否成功,如果出错是因为什么, 然而, 这就意味着用户需要进行内容解析,才知道执行结果和错误原因。因此,HTTP 响应代码可以保证客户端在第一时间用最高效的方式获知 API 运行结果,并采取相应动作。 下表列出了比较常用的响应代码。

表 1. 常用 HTTP 响应代码含义
HTTP 响应代码 代码含义
200 已创建,请求成功且服务器已创建了新的资源。
201 是否只显示处于警告状态的应用实例
301 重定向 , 请求的网页已被永久移动到新位置。服务器返回此响应时,会自动将请求者转到新位置。
302 重定向 , 请求的网页临时移动到新位置,但求者应继续使用原有位置来进行以后的请求。302 会自动将请求者转到不同的临时位置。
304 未修改,自从上次请求后,请求的网页未被修改过。服务器返回此响应时,不会返回网页内容。
400 错误请求 , 服务器不理解请求的语法。
401 未授权 , 请求要求进行身份验证。
403 已禁止 , 服务器拒绝请求。
404 未找到 , 服务器找不到请求的网页。
405 方法禁用 , 禁用请求中所指定的方法。
406 不接受 , 无法使用请求的内容特性来响应请求的网页。
408 请求超时 , 服务器等候请求时超时。
410 已删除 , 如果请求的资源已被永久删除,那么,服务器会返回此响应。
412 未满足前提条件 , 服务器未满足请求者在请求中设置的其中一个前提条件。
415 不支持的媒体类型 , 请求的格式不受请求页面的支持。
500 内部服务器错误。

回页首

使用 HTTP 头处理缓存和并发

缓存和并发处理,从来是大型软件系统设计中的重要组成部分。

使用 HTTP 头进行缓存处理

在 REST 的构架中,我们除了在与后台的数据交换中,需要有一个良好的缓存机制外,针对 REST API 请求都是在远端用 HTTP 发起这一特点,还需要为网络缓存进行更多考虑。通过减少 HTTP 响应内容,避免不必要的 HTTP 连接等方式,达到提高 REST API 使用效率的目的。

HTTP 头中,有多个字段可以用于缓存处理。比较常用的有缓存控制和条件请求。

缓存控制:

缓存控制通常是需要客户端,缓存服务器 / 代理服务器与业务服务器一起发生作用。

HTTP 头中有“Cache-control”字段来控制如何使用缓存,常见的取值有 private、no-cache、max-age、must-revalidate 等。比如当你给返回的数据内容设置 max-age=600,那么当用户隔了 30 秒再次请求的时候,就不会导致重新请求后台数据。

另外,也可以通过“Expires”字段来指定内容过期时间,在此时间前的请求都不会导致后台程序重新请求数据。

下图展示了 max-age 是如何工作的。

图 2. 缓存控制工作方式的简单范例


条件请求与电子标签:

很多时候,数据内容可能会几个小时甚至几天都不会发生变动,这个时候根据请求时间间隔来控制缓存,就不能满足系统的需求了。通过支持条件请求与电子标签,可以帮助我们来解决这个问题。

当用户请求数据内容时,系统在返回数据的同时,在 HTTP 头中,将返回根据服务器内容的最后修改时间 Last-Modified,或者根据服务器内容生成电子标签 ETag。 当用户再次请求数据时,就可以在 HTTP 请求中使用 If-Modified-Since 或者 If-None-Match 头信息,把上次请求得到的时间戳或者电子标签传给服务器。当收到一个有条件请求的 HTTP 头的 REST 请求的时候,我们的程序需要将收到的时间戳或者电子标签与当前内容作比较,就可以很容易的知道用户请求的数据内容在这段时间是否发生过修改,并根据比较结果返回给用户最新内容,或者用
HTTP 响应码 304 告知用户,内容没有变化。

下面是一个来自 IBM developerWorks 的 API 样例,尝试请求该 API,你可以看到该 API 会在 HTTP 头中返回电子标签和缓存处理信息。

清单 4. IBM developerWorks 的带有电子标签的文件服务 API
 REST API 请求:
 GET  https://www.ibm.com/developerworks/mydeveloperworks
 /form/anonymous/api/communitylibrary
 /7e2e8015-bf72-43b6-bacd-36565b67febc/document
 /ddc0ef4e-224e-449c-bb2c-f919fafb17d2
 /entry?acls=true&includeRecommendation=true
 &includeTags=false&includeLibraryInfo=true&format=xml

使用 HTTP 头进行并发处理

上文我们提到了使用条件请求控制缓存,其实我们还可以使用条件请求进行并发处理。

比如当用户 Alice 和 Bob 通过 REST 获取了一篇文档。Bob 阅读文档之后,通过 PUT 来修改文档;而此前几分钟,Alice 刚刚修改了这篇文档,于是 Bob 就在毫不知情的情况下不慎覆盖了 Alice 的修改。

通过在写操作中支持条件请求,我们可以更好的处理并发修改。用户在发出修改请求的同时,在 HTTP 请求中使用 If-Not-Modified-Since 或者 If-Match 头信息,把获取数据时得到的时间戳或者电子标签传给服务器;我们的程序通过与服务器当前内容的比较,就可以知道,这个修改请求是否是针对当前内容提出的。当服务器发现内容已经被其他用户修改过了,就不会执行修改请求,并返回 HTTP 响应码 412(未满足前提条件)给用户。

下图展示了使用条件请求和电子标签进行并发处理是如何工作的

图 3. 支持条件请求时的并发处理简单范例

回页首

更好的使用数据冗余和链接元素

在 ATOM 文档中,我们用各种数据元素来传递信息。其中有一类元素叫做链接,可以用于开发者的进一步访问。通常,我们会提供编辑当前资源的链接,访问当前资源的链接,等等。通过更加灵活的使用这类链接元素,以及提供必要的数据冗余,我们可以大大简化开发者的编程逻辑,提高 REST API 的使用效率


回页首

更多的需要注意的细节与技巧

除了以上提到的方面,还有大量的细节与技巧,可以帮助我们更好的设计 REST API:

批量更新:

当用户需要更新多个资源的时候,你打算让开发者一次次的发送 HTTP 请求逐个更新吗?你可以考虑在设计 API 的时候允许客户同时创建或者更新多个资源。

REST 安全:

除了使用固有的 HTTP 基本验证,你还可以考虑通过支持表单验证,LTPA 验证,Open ID 验证等方式,来满足更多的企业安全要求。

文档服务:

是否由于 API 持续更新,使得客户端连接不同版本服务的时候疲于奔命?尝试着把你的 API 定义规范成 XML 文档,这样客户端很容易理解当前服务可以提供哪些功能,以及如何使用这些功能。

你还可以通过阅读其他文档得到更多这方面的指导,本文无法将所有的细节与技巧一一穷尽。

时间: 2024-09-18 18:02:16

Rest api的相关文章

大神们!!百度地图api中标签信息的抓取啊。前js后C#。

问题描述 大神们!!百度地图api中标签信息的抓取啊.前js后C#. 是这样的,一个地图api的调用,我需要获取到百度地图api上的搜索出来的信息,可是获取不到啊啊啊... 解决方案 js版的百度地图还是其他版本的? js版本的,C#是运行于服务器端的,无法直接获取客户端的数据.js搜索后你自己即那个解码后的信息用ajax回发到服务器进行获取

使用Java API处理WebSphere MQ大消息

WebSphere MQ 中处理大消息的方法 使用过 WebSphere MQ 的读者都知道,WebSphere MQ 对处理的单条消息的大小是有限制的,目前支持的最大消息是100M,而且,随着消息大小的增大,WebSphere MQ 处理的性能也会随之下降.从最佳实践来说,WebSphere MQ 传输大小为几K的消息其效率是最高的.那如何使 WebSphere MQ 能高效的处理大消息呢? WebSphere MQ 提供了处理大消息的两种方法:消息分片和消息分组.下面我们来看在使用 Java

如何从k8s集群外的机器上调用k8s的API(可调用多个k8s的apiserver)

因为公司项目需要,k8s的集群管理由其它人负责,而我们的自动化部署平台需要从k8s集群外的机器上调用k8s主节点的apiserver提供的API. 由于集群是用kubeadm安装的,证书验证齐全,那么,调用API时,只能通过kubectl proxy的方式进行调用管理. 操作步骤如下:   一,在集群外的机器上安装好kubectl的rpm包. rpm -ivh kubectl-1.7.0-0.x86_64.rpm 二,将k8s上在安装过程中生成的config文件重命名,CP到操作用户的家目录的.

WKWebView API精讲(OC)

前言 鉴于LL同志对笔者说:"能不能写个OC版本的WKWebView的使用教程?",还积极打赏了30RMB,笔者又怎么好意思拒绝呢,于是才有了下文. 所有看到本篇文章的同志们,应该要感谢LL同志,更要向LL同志学习,积极打赏! WKWebView 看看WKWebView的头文件声明: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

使用osgi api启动osgi时,用java -jar命令运行报异常,用eclipse运行正常

问题描述 使用osgi api启动osgi时,用java -jar命令运行报异常,用eclipse运行正常 我使用osgi的api写了osgi框架的启动程序,然后使用java -jar 命令运行这个jar包报空指针异常,我在eclipse中运行一切正常,请问这是为什么呀

用 Flask 来写个轻博客 (32) — 使用 Flask-RESTful 来构建 RESTful API 之一

目录 目录 前文列表 扩展阅读 RESTful API REST 原则 无状态原则 面向资源 RESTful API 的优势 REST 约束 前文列表 用 Flask 来写个轻博客 (1) - 创建项目 用 Flask 来写个轻博客 (2) - Hello World! 用 Flask 来写个轻博客 (3) - (M)VC_连接 MySQL 和 SQLAlchemy 用 Flask 来写个轻博客 (4) - (M)VC_创建数据模型和表 用 Flask 来写个轻博客 (5) - (M)VC_SQ

Openstack API 类型 & REST 风格

目录 目录 Openstack 提供了三种操作方式 Web界面 CIL 指令行 RESTful API REST 风格 RESTFul风格的API设计 基于HTTP协议的RESTful API OpenStack中的RESTful API开发框架 Openstack 提供了三种操作方式 Web界面 也就是通过Dashboard(儀表板)来使用Openstack雲計算平台上的功能.通过Web界面使用 OpenStack Services 这种方式是通过 OpenStack Horizon Proj

api-开发是使用位置服务(android自带API),无法上传实时坐标,只能上传第一个点的坐标?

问题描述 开发是使用位置服务(android自带API),无法上传实时坐标,只能上传第一个点的坐标? 开发是使用位置服务(android自带API),无法上传实时坐标,只能上传第一个点的坐标?有大神知道这是为什么吗?急急急!!! 解决方案 http://blog.csdn.net/qiannuo/article/details/6791873

(转)SendMessage API

  原文:http://hi.baidu.com/ytmeng/blog/item/25f5de5157931a888c543001.html using System;using System.IO;using System.Threading;using System.Diagnostics;using System.Runtime.InteropServices; namespace XDF.GamePlugInCommon {     ///   <summary>         /

xml-携程api接口请求成功返回的String数据怎样拿来使用

问题描述 携程api接口请求成功返回的String数据怎样拿来使用 携程官网提供的java方法,配置好后,请求成功,返回的是xml形式的一串String类型的字符串,怎么才能拿来使用? 解决方案 用xml解析库,或者反序列化成对象后就可以用了. 解决方案二: 用xml解析库,或者反序列化成对象后就可以用了. 解决方案三: google java xml解析.http://bbs.csdn.net/topics/290027113 http://developer.51cto.com/art/20