一位开发人员(现在左)已经确信,开发RESTful Web服务的正确方法是为您的服务创建自定义媒体类型。
例如application / vnd.acme.payroll.v1 + json
这样,您可以告诉客户端指定要使用的编码而不更改URI。
这种技术是好的吗?通常服务将版本嵌入到URL:
例如/acme/1.0/payroll /
我在执行客户端使用此方案时遇到了很多困难,尤其是因为DELETE似乎没有强制执行媒体类型
答案 0 :(得分:18)
您可以在RESTful服务中使用一些主要的信令机制:
rel
。Accept-Version
/ Api-Version
。每个都有不同的用途,我将概述在设计API时我们理解它们的方式。
为了表明给定资源上可能的操作,以及这些操作的语义,许多人使用自定义媒体类型。在我看来,这不太正确,rel
更准确。
自定义媒体类型应该告诉您有关数据的类型,例如它的格式或某些信息的体现或嵌入方式。拥有自定义媒体类型意味着您的API的消费者与该特定表示紧密耦合。然而,使用像application/json
这样更通用的东西说“这只是JSON数据。”
通常单独使用JSON对于RESTful服务是不够的,因为它没有内置链接或资源嵌入功能。这就是HAL(application/hal+json
)之类的内容。它是JSON的一种特殊化,它仍然是一种通用格式,而不是特定于应用程序的格式。但它足以覆盖JSON之上的链接和嵌入语义,这是连贯表达RESTful API所必需的。
rel
s)这将我们带到了rel
。对我来说,自定义rel是一种完美的方式,用于表示正在处理或链接的资源类型。例如,用户资源的自定义rel
可能为http://rel.myapi.com/user
,这有两个目的:
initialResource._links["http://rel.myapi.com/user"].href
找到用户链接。如果将rel
与标准或半标准媒体类型(如application/hal+json
)结合使用,您将获得遵循其媒体类型指定的统一格式的资源,并使用其定义的API特定语义rel
秒。这几乎可以让你在那里。
剩下的问题是版本控制。如何允许客户端协商不同版本的资源,同时不使旧URI失效?
我们的解决方案受Restify Node.js框架的启发,是两个自定义标头:Accept-Version
来自客户端,与服务器X-Api-Version
非常匹配(或Api-Version
在即将发布的Restify 2.0版本中,根据新的RFC 6648)。如果它们不匹配,则结果为400 Bad Request
。
我承认自定义媒体类型在这里是一个相当流行的解决方案。在我看来,根据上述考虑,它们在概念上并不合适,但如果你选择它们作为你的版本控制机制,你就不会做一些奇怪的事情。正如您所注意到的那样,当与GET
以外的方法一起使用时,它会出现一些语义问题。
要记住的一件事是,在真正的RESTful系统中,版本控制不应该是这样的问题。它应该只在一个非常具体的情况下:当资源的表示以向后不兼容的方式发生变化时,您仍然希望保持相同的rel
。因此,如果http://rel.myapi.com/friend
资源突然失去其username
字段并获得id
字段,那么这将符合资格。但是如果它突然获得nickname
字段,那么它不是后向不兼容的,因此不需要进行版本控制。如果“朋友”的概念在您的API中被完全替换为“连接”的概念,这实际上并不是向后兼容的,因为API消费者将不再找到{{ 1}}链接API中的任何位置,以便他们遵循。
答案 1 :(得分:3)
是的,这是一个不错的选择。它澄清了您将用于有效负载的编码,并允许双方协商不同版本的编码而不更改URI,正如您正确指出的那样。
是的,客户端不需要发送DELETE和实体主体。我相信它会被兼容的HTTP服务器忽略,因为在这种情况下没有传输有效载荷数据。客户端为URI发出DELETE,服务器返回一个响应代码,指示它是否成功。好又简单!如果服务器希望在DELETE之后返回一些数据,则可以自由地执行此操作,并且应该在响应时指定响应的媒体类型。