Rest API是一种非常常见的方法,可为客户端提供通过http/https通道与服务器进行通信的功能。本文档列出了一些指南,可以帮助您建立良好的rest 服务。
致力于这些实践可以在短短10天内帮助您建立良好的服务。
代表性状态转移(REST)是一种体系结构样式,用于指定约束(例如统一接口),如果将约束应用于统一的Web服务,该约束会引起期望的属性(例如性能,可伸缩性和可修改性),这些属性使服务能够在Web上最好地工作。在REST体系结构样式中,数据和功能被视为资源,并使用统一资源标识符(URI)(通常是Web上的链接)进行访问。通过使用一组简单的,定义明确的操作对资源进行操作。在这种情况下,通常将建立的通信通道视为无状态。
以下原则鼓励RESTful应用程序是简单的、轻量级的和快速的:
Rest 服务是轻量级的且易于使用。但是,设计良好的rest服务可以确保客户端与服务的无缝集成,并提供一种用于健壮的、可扩展的和安全的通信方式的机制。
下一节将介绍有助于构建良好的REST API的准则。
在构建REST服务时,正确获取服务名称很重要。尽管这似乎是一个简单的步骤,但是确保正确命名服务可确保客户可以轻松理解服务的功能。建立REST API的第一天开始时,请确保使用正确的术语。
类似的,REST服务使用标准的HTTP动词,如GET,POST,PUT和DELETE。按照准则使用这些内容可确保客户以正确的方式调用服务。
引用:
“网址是一个句子,资源是名词,而动作是动词”。
接下来的小节将详细介绍这些内容。
通过使用作为服务一部分访问的资源的名称来命名服务。
例如,如果服务返回一条静态数据信息,则应调用该服务:
\static\{id}
其中static是要访问的资源的类型,而{id}代表服务的实际ID。
不建议在服务名称中使用动词。
例如,getStatic或saveStatic不是访问静态数据服务的正确名称。
为了访问多个资源,可以使用多种形式的资源。
例如,/currencypairs/或/persons/
建议唯一使用动词的地方是当服务执行未直接链接到资源的动作时。
例如,/backup/当需要备份数据库时。
正确的HTTP动词(操作)对于构建服务很重要。
应遵循以下准则:
如果使用不正确,则不会通过HTTP进行验证。但是,使用正确的操作可以确保整个服务的一致性–无论是对于服务还是使用该服务的客户。
默认情况下,http 1.0和http 1.1均提供了一组响应代码,只要通过HTTP协议生成响应,该代码就会返回。这些是调用REST服务时返回的标准响应。但是,这些通常不足以为客户提供正确的响应。提供适当的消息以及响应是很有用的。
此外,在发生错误的情况下,记录错误的堆栈跟踪很重要,以确保在进行调查时可以对其进行调试/检查。此信息无需传递回客户端。但是,应将明确定义的错误消息作为响应返回给客户。
不需要与客户端共享的安全相关信息或关键数据是不需要记录回客户端的信息的特定情况。
注意:此处描述了标准的HTTP响应消息。
身份验证和授权在提供良好的rest服务中起着关键作用。有几种启用安全性的方法,本节仅介绍实现这些项目的一些方法。
验证调用资源是所有服务使用的标准过程。它可以通过多种方式完成。下面列出了一些常见的方法:
这些方法提供身份验证,但不能保证对服务器的所有其他请求都是安全的。结果,需要考虑某种形式的令牌机制作为身份验证的补充。
启用授权的一种简单方法是使委托人能够管理资源。将主体链接到资源将确保仅可访问资源返回给每个客户端。
一旦获得授权,甚至可以将主体信息添加到令牌中。
登录尝试成功时将生成令牌。然后,在对服务器的每个请求中,将这些令牌附加到标头。
为了在无状态环境中管理请求,JWT(json Web令牌)提供了一种智能且安全的令牌管理方法。
JWT令牌由三部分组成,包括标头,声明和签名,它们提供了实现每个请求验证的无状态方式。
JWT令牌确保令牌在不同用户、委托人之间的有效性,并通过声明管理过期时间。
身份验证和授权本身不足以在现实世界中提供安全性。嗅探器攻击,中间人攻击等多种风险威胁着rest服务。
虽然这些主题的详细讨论不在本文档的讨论范围内,但在此提及一些项目以供参考:
需要缓解这些威胁中的每一种,以使REST服务安全可靠,以应对任何类型的威胁。
Rest服务建议借助“子资源”访问资源。
例如,如果我们有一个名称为“cars” 的资源表示所有类型的汽车的列表,而另一个资源集为“drivers”,则要获取特定类型汽车的驾驶员列表,可以使用以下资源子资源组合:
/cars/{carname}/drivers/{drivername}/
这避免了拥有两种不同类型的服务的开销,同时确保了不同API集之间的关系得以维持。
使用HATEOS(作为应用程序状态引擎的超媒体),客户端应用程序可以通过超媒体直接与服务器进行交互。这样可确保REST客户端不需要预先了解与REST服务的接口。
一旦访问了第一个URL,就可以动态生成指向其他资源的链接。这样做的主要好处是,它允许服务器更改URI模式,并且对客户端没有影响。即使更改了到服务器的链接,客户端也不需要更改。
这与传统的WSDL系统不同,在传统的WSDL系统中,已知接口点,并且对这些接口的更改将暗示在客户端进行必要的更改。
访问资源的响应告诉我们下一步需要执行的操作。
在下面的示例中,布局资源提供对响应本身内的静态货币资源的访问。
随着业务功能的变化,预计REST API将发生变化。但是,随着新API的创建,旧客户端无法确保它们是最新的。REST API签名将破坏现有功能。结果,现有客户将难以跟上这些变化。
API版本控制可确保长期的客户承诺。
有几种解决版本控制的方法。下面列出了其中一些方法。
使用url和url参数中的版本进行uri版本控制是管理版本的更常用方法。
下面,我们将看两个用例,重点介绍每种方法的一些利弊。
用例1 –能够对特定资源分支进行版本控制。客户愿意升级和更改代码以调用这些特定分支。
REST本身不推荐uri中除了资源以外的任何东西,因此这种方法是对标准的偏离。
但是,这些是最常见的版本控制方法(Amazon,Google和Netflix使用它们!)
用例2 –能够以隐藏方式对特定资源分支进行版本控制。客户端可能并不总是希望指定版本。
接受和自定义标头都很难测试。客户需要意识到它们。
并非所有的防火墙都允许自定义标头。
为了使API可以将来使用,重要的是应该构建REST API以处理任何类型的数据格式。这些格式中的某些可能现在可用,而另一些可能仅在将来可用。
例如,content-type可以包含text/xml或application/json。
第一步,服务应该能够在content-type中提供的不同格式之间切换。
下一步,该服务还应该可扩展以支持将来可能使用的其他格式。
通过确保所有这些功能都已内置到服务中,可以确保该服务可以更快地适应格式更改。
该服务应固有地支持uri本身内的分页、过滤和排序。
这样可以与希望从该服务获得数据的客户端/用户界面实现更流畅的集成。
尽可能在服务器上进行过滤、分页和排序,然后将数据传递给客户端。这样做的好处是减少了通过网络发送的数据,从而提高了性能。
分页、排序和过滤也可以在客户端进行。这可能会减慢客户端的速度,因为所有这些都将处理大型数据集。
在多个客户端上,代理仅允许POST和GET方法。不支持PUT和DELETE。
结果,REST API将无法在这些客户端上运行。
为了提供此问题的解决方案,建议服务了解X-HTTP-METHOD-OVERRIDE标头选项。
服务器管道接收该值并将其转换为适当的REST方法。
缓存的主要目标是永远不会两次产生相同的响应。在REST服务中,这可以通过使服务器同时处理更多客户端来确保更好的性能。
缓存
请求中的缓存控制参数在响应中提供了几个参数。这些参数提供了有关缓存的可配置选项。
在所有HTTP方法中,GET最有可能的选择是缓存,这仅仅是因为它请求资源。POST和PUT不太可能进行缓存,因为这些在服务器端更新信息。
需要注意确保分别针对http 1.0和http 1.1启用了不同的缓存,因为这两个协议之间的某些参数有所不同。
为了提高性能,可以在以下四个位置进行缓存:
没有正确的文档,没有API是完整的。如果没有正确记录服务,则用户将很难知道每个服务的功能以及使用该功能所需的操作。
服务的消费者需要了解服务中的几个问题:
通常,可以将JAXRS分析器和ASCII doc等工具与标准javadoc一起使用,以创建类似swagger的文档。但是,这可能还不够,因为功能顾问/技术作家需要提供适当的功能文档,以使客户能够以正确的方式使用API。
牢记基本的基本原则,可以创建良好的REST服务。这不需要花费很多天的精力,并且如果从一开始就实施了这些实践,则服务可以在短短10天内包含许多良好实践。
最初构建一个良好的REST框架可以帮助客户端轻松地与服务器进行交互,并确保在使用这些服务方面的长期承诺。
在许多地方,API和服务可以互换使用。
REST代表Representational State Transfer -无论是否使用该缩写,它可以适当地以其完整形式代替。
在整个文档中都使用了Rest和REST。就本文档而言,它们的含义相同。