在使用HATEOAS设计RESTful Web服务时,将链接显示为完整的URL(“ http:// server:port / application / customers / 1234 ”)与仅显示路径(“ / application /客户/ 1234“)?
在使用HATEOAS设计RESTful Web服务时,将链接显示为完整的URL(“ http:// server:port / application / customers / 1234 ”)与仅显示路径(“ / application /客户/ 1234“)?
Answers:
当人们说“相对URI”时,存在一个概念上的含糊之处。
根据RFC3986的定义,通用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"
/over/there
here
or ./here
or ../here
oretc。因此,如果问题是“服务器是否应在平稳响应中生成相对路径”,则答案为“否”,并且详细原因在此处。我认为大多数反对“相对URI”的人(包括我)实际上都反对“相对路径”。
并且在实践中,大多数服务器端MVC框架都可以轻松生成带有绝对路径(例如)的相对URI,/absolute/path/to/the/controller
问题就变成了“服务器实现是否应scheme://hostname:port
在绝对路径之前加a”。像OP的问题一样。我对此不太确定。
一方面,我仍然认为建议服务器返回完整的uri。但是,服务器永远不要hostname:port
像这样在源代码中对事物进行硬编码(否则,我宁愿退回到具有绝对路径的相对uri)。解决方案是服务器端始终从HTTP请求的“主机”标头中获取该前缀。不知道这是否适用于所有情况。
另一方面,客户端将http://example.com:8042
和绝对路径连接起来似乎并不麻烦。毕竟,客户端在向服务器发送请求时已经知道该方案和域名了吗?
总而言之,我建议您使用绝对URI,最好使用绝对路径回退到相对URI,而不要使用相对路径。
这取决于谁在编写客户端代码。如果您正在编写客户端和服务器,则没有太大的区别。您将痛苦地在客户端或服务器上构建URL。
但是,如果您要构建服务器,并且希望其他人编写客户端代码,那么如果您提供完整的URI,他们会更爱您。解决相对URI可能会有些棘手。首先,您如何解决它们取决于返回的媒体类型。Html具有base标记,Xml在每个嵌套元素中都可以具有xml:base标签,Atom feed可以在feed中具有一个基础,而内容中可以具有一个不同的基础。如果您没有为客户提供有关基本URI的明确信息,那么他们必须从请求URI或从Content-Location标头中获取基本URI!并注意尾随的斜线。基本URI是通过忽略最后一个斜杠右侧的所有字符来确定的。这意味着在解析相对URI时,尾部的斜杠现在非常重要。
唯一需要提及的其他唯一问题是文档大小。如果您要返回大量项目,其中每个项目可能具有多个链接,则在不压缩实体的情况下,使用绝对URL可以为您的实体添加大量字节。这是一个性能问题,您需要根据具体情况决定是否重要。
随着应用程序的扩展,您可能希望进行负载平衡,故障转移等。如果返回绝对URI,则客户端应用程序将遵循不断发展的服务器配置。
/xxx/yyy...
),而不是定义为完全限定的URI(例如http://api.example.com/xxx/yyy...
)。
使用RayLou的三分法我的组织选择了偏爱(2)。主要原因是为了避免XSS(跨站点脚本)攻击。问题是,如果攻击者可以将自己的URL根注入到来自服务器的响应中,则随后的用户请求(例如具有用户名和密码的身份验证请求)可以转发到攻击者自己的服务器*。
有些人提出了能够将请求重定向到其他服务器以进行负载平衡的问题,但是(虽然这不是我的专业知识),我敢打赌,有更好的方法来启用负载平衡,而不必将客户端显式重定向到其他服务器。主机。
*请让我知道这种推理方法是否存在缺陷。当然,目标不是阻止所有攻击,而是至少阻止一种攻击途径。
您应该始终使用完整的URL。由于URL都必须唯一,因此它充当资源的唯一标识符。
我也认为您应该保持一致。由于Location HTTP标头期望基于HTTP规范的完整URL,因此在创建新资源时,完整URL将在Location标头中发送回客户端。您在Location标头中提供完整的URL,然后在响应正文中的链接中提供相对URI,这很奇怪。
Location
标头示例所提供的-绝对URI,其中不包含URI方案或服务器的网络位置。尽管链接和ID经常混杂在一起,但它们并不是同一件事-前者具有上下文,后者则没有。
使用绝对URI的一个缺点是无法代理api。
把它拿回来...不是真的。您应该使用完整的URL,包括域。
关于优点,我看到要传输的字节数有所减少,但代价是客户端需要为(绝对)路径进行额外的处理。如果您不顾一切地保存每个字节,即使尝试将内容编码为gzip,正确使用缓存头,使用etags和客户端上的条件请求之后,最终还是有必要这样做的,但我希望返回的结果会更高你的努力是其他的。
关于弊端,我发现无法控制将来如何在资源之间引导客户端流(负载平衡,A / B测试等),我认为这对于管理Web是一种不良做法API。对于客户端,您提供的URL基本上不再是不透明的(请参阅URI opacity上的Web体系结构的Tim Berners-Lee Axioms)。最后,您有责任让客户满意他们对您的API的创造性使用,即使仅仅是关于您的URL空间的结构。如果你曾经需要允许一个明确定义的URL修改,考虑使用URI模板中所使用的超文本应用程序语言。