在使用HATEOAS设计RESTful Web服务时,将链接显示为完整URL(“http://server:port/application/customers/1234”)与仅显示路径(“/ application / customers / 1234”)的优缺点是什么? ?
答案 0 :(得分:67)
当人们说“相对uri”时,存在一种微妙的概念歧义。
按RFC3986's definition,通用uri包含:
URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
hier-part = "//" authority path-abempty
/ path-absolute
/ path-rootless
/ path-empty
foo://example.com:8042/over/there?name=ferret#nose
\_/ \______________/\_________/ \_________/ \__/
| | | | |
scheme authority path query fragment
棘手的是,当省略方案和权限时,“路径”部分本身可以是绝对路径(以“/”开头)或“无根”相对路径。例子:
"http://example.com:8042/over/there?name=ferret"
所以,如果问题是“服务器是否应该在restful响应中产生相对路径”,答案是“否”和detail reason is available here。 我认为大多数人(包括我)反对“相对uri”实际上反对“相对路径”。
实际上,大多数服务器端MVC框架都可以轻松生成相对uri的绝对路径,例如“/ absolute / path / to / the / controller”,问题变成“是否服务器实现应该在scheme:// hostname:port前面加上绝对路径的前缀“。就像OP的问题一样。我对这个不太确定。
一方面,我仍然认为服务器返回完整的uri是建议的。但是,服务器应never hardcode the hostname:port thing inside source code like this(否则我宁愿使用绝对路径回退到相对uri)。解决方案是服务器端始终从HTTP请求的“主机”标头获取该前缀。不确定这是否适用于所有情况。
另一方面,客户端连接"http://example.com:8042"
和绝对路径似乎不是很麻烦。毕竟,客户端在向服务器发送请求时已经知道了该方案和域名吗?
总而言之,我会说,建议使用绝对uri,可能使用绝对路径回退到相对uri,从不使用相对路径。
答案 1 :(得分:12)
这取决于谁在编写客户端代码。如果您正在编写客户端和服务器,那么它没有太大区别。您将要么在客户端或服务器上构建URL的痛苦。
但是,如果您正在构建服务器而您希望其他人编写客户端代码,那么如果您提供完整的URI,他们会更加喜欢您。解析相对URI可能有点棘手。首先,如何解决它们取决于返回的媒体类型。 Html具有基本标记,Xml可以在每个嵌套元素中包含xml:base标记,Atom提要可以在提要中具有基础,并且内容中具有不同的基础。如果您没有向客户端提供有关基本URI的明确信息,那么他们必须从请求URI获取基本URI,或者从Content-Location标头获取基本URI!并留意那个尾随的斜线。通过忽略最后一个斜杠右侧的所有字符来确定基URI。这意味着在解析相对URI时,尾随斜杠现在非常重要。
唯一需要提及的另一个问题是文档大小。如果要返回一个大项目列表,其中每个项目可能有多个链接,则使用绝对URL可以在您不压缩实体时向实体添加大量字节。这是一个性能问题,您需要根据具体情况决定它是否具有重要意义。
答案 2 :(得分:11)
唯一真正的区别似乎是,如果客户端使用绝对URI而不必从相对版本构造它们,那么它对客户来说更容易。当然,这种差异足以让我做出绝对版本。
答案 3 :(得分:7)
随着您的应用程序扩展,您可能希望进行负载平衡,故障转移等。如果您返回绝对URI,那么您的客户端应用程序将遵循您不断发展的服务器配置。
答案 4 :(得分:4)
使用RayLou's trichotomy我的组织选择了偏好(2)。主要原因是避免XSS(跨站点脚本)攻击。问题是,如果攻击者可以将自己的URL根注入到从服务器返回的响应中,则后续用户请求(例如带有用户名和密码的身份验证请求)可以转发给攻击者自己的服务器*。
有些人提出了能够将请求重定向到其他服务器以实现负载平衡的问题,但是(虽然这不是我的专业领域)我会打赌有更好的方法来启用负载平衡而无需显式重定向客户到不同的主机。
*请告诉我这条推理是否存在任何缺陷。当然,目标不是防止所有攻击,而是防止至少一种攻击途径。
答案 5 :(得分:3)
您应该始终使用完整的网址。它充当资源的唯一标识符,因为URL都必须是唯一的。
我还认为你应该保持一致。由于Location HTTP标头需要基于HTTP规范的完整URL,因此在创建新资源时,会在Location头中将完整URL发送回客户端。您可以在Location头中提供完整的URL,然后在响应正文中的链接中提供相对URI,这很奇怪。
答案 6 :(得分:2)
使用绝对URI的一个缺点是api无法代理。
收回......不是真的。您应该查找包含域名的完整URL。
答案 7 :(得分:1)
大型API结果中的一个重要考虑因素是重复包含完整URI的额外网络开销。信不信由你,gzip并没有完全解决这个问题(不知道为什么)。当结果中包含数百个链接时,我们对完整URI所占用的空间感到震惊。
答案 8 :(得分:1)
关于优缺点,我看到要传输的字节数有所减少,但代价是客户端需要为(绝对)路径进行额外的处理。如果您不顾一切地保存每个字节,即使尝试将内容编码为gzip,正确使用缓存头,使用etags和客户端上的条件请求之后,最终还是有必要这样做的,但是我希望这样做的回报会更高是你的努力。
关于弊端,我发现无法控制将来如何在资源之间引导客户端流(负载平衡,A / B测试等),我认为这是一个不好的做法管理网络API。对于客户端,您提供的URL基本上不再是不透明的(请参见Tim Berners-Lee Axioms of Web Architecture on URI opacity)。最后,您有责任让客户满意他们对您的API的创造性用法,即使仅仅是关于您的URL空间的结构。如果您需要允许进行明确定义的URL修改,请考虑使用URI templates中使用的Hypertext Application Language。