我一直在讨论与我的一位同事一起做这件事的最佳方式
以下是一个示例场景:
我正在尝试获取ID为1234的Customer
的所有订单。
考虑以下终点:
/ customer / orders
使用GET请求,使用以下标头:
授权:基本QWxhZGRpbjpvcGVuIHNlc2FtZQ ==
使用Authorization
标头,我们的身份验证机制会为ID为1234的客户识别此请求,我们的服务会返回所需的订单。
他试图说服我这是正确的,因为登录客户,只会请求他们的订单(在这种情况下,属于客户1234的订单) - 所以传递ID URL是不必要的。 但是......对我来说,这不是RESTful(我可能错了)
在我看来,它应该是这样的:。
/ customer / 1234 / orders
使用标题(例如)
授权:基本QWxhZGRpbjpvcGVuIHNlc2FtZQ ==
使用Authorization标头,我们验证用户是否有权检索这些订单......如果是,则返回它们,否则返回401
我的问题是,哪种方法首选?
我当然可以看到第一种方式带来的好处,但是为了保持我们的api RESTful,我心里说第二种方式......
答案 0 :(得分:14)
资源标识是一个关键的REST约束。您的订单和我的订单不是同一个资源,因此他们应该(不是必须)有不同的标识符。
你应该给他们一个唯一标识符(即/ customers / 1234 / orders)的实际原因是因为支持HTTP缓存会容易得多。 HTTP缓存中介主要使用URI作为缓存键。通过使用vary头,可以使用其他头文件(如auth)作为缓存密钥的一部分,但是,对这种机制的支持不太可靠/普遍。
即使今天您还没有计划使用HTTP缓存,最好还是安全地玩,并确保您的URI设计为在将来需要时使用此功能。
在进行客户端URI构建时,不必在URI中包含客户ID有一些好处。但是,RESTful系统应该通过在返回的表示中嵌入这些URI来为客户端提供URI。客户端不需要构建这些URI,因此客户端使用带有id的URI作为使用不带Id的URI的ZERO额外工作。如果您准备吞下超媒体药丸,那么不包括ID就没有优势。
答案 1 :(得分:10)
我认为只有在您允许客户检索其他客户的订单数据时才需要第二个实施(包括客户ID)。换句话说,如果客户4321将能够看到客户1234的订单历史记录,那么发送它是绝对必要的。
我的猜测是他们无法做到这一点。这意味着如果您包含该信息,您可能会忽略它而无论如何都支持授权码。
如果是这种情况,我说甚至不发送它。
如果它让你感觉更好,LinkedIn的REST API会反映出这种行为。如果省略id,任何用户都可以请求任何其他用户 BUT 的个人资料,假设当前用户正在请求他们自己的个人资料。 Read more here
所有这一切,只要它对你有意义并且你记录它你就应该没问题。
答案 2 :(得分:5)
两者都不是RESTful。 URI的语义应该与RESTful应用程序中的客户端无关。
REST是一种基于Web本身的架构风格。想一想。当您转到Stack Overflow时,您唯一关注的URI是stackoverflow.com
。登录后,您将被重定向到主页,并且主页的URI无关紧要。现在我在我的菜单栏上有一个链接到我的主页,你有一个相同的链接进入你的主页,我们点击它时我们不关心URI是什么,对吧?在我们的主页上,我们看到问题和答案,我们也不关心他们的URI,只关注他们的标题和描述。
现在,让我们扭转它。 REST是网络的架构风格,如果网络就像你认为REST一样,当你加入stackoverflow.com
时,而不是一个指向你主页的名字很好的链接,你会有一个文字说“你的ID是131809,请带URI模式/ users /(id),用这个数字替换id,将它粘贴到地址栏中,你就会到达你的主页”,你会想,“为什么那些白痴不要为此建立链接?“
这听起来很荒谬,但这就是大多数人认为REST的含义。 REST APIs must be hypertext driven.
这意味着,如果用户的订单应位于/customer/(customer_id)/orders
,或仅/customer/orders
或甚至/orders
并且依赖其凭据,则强制客户了解所有这些URI模式,您应该在API入口点给他一个根文档,考虑他的凭据,并为URI提供标准的标题和描述,就像任何网站登录时一样!
因此,假设您使用的是JSON,而您的API是myapi.com
。这应该是客户端知道的唯一URI。当他向该根文档发出GET
请求时,如果使用正确的Authorization标头,他应该获得一个JSON文档,如:
{"orders": "http://myapi.com/customer/123456/orders"}
显然,他不需要知道“订单”的价值是什么,只是它是一个有效的URI,将导致他到另一个包含他的订单集合的资源。 URI可以是任何东西,它的语义无关紧要。这可能是你朋友的建议:
{"orders": "http://myapi.com/orders"}
或其他任何可以随时更改的内容:
{"orders": "http://myapi.com/this/is/a/meaningless/uri"}
当然,您应该付出一些努力来获得清晰且有意义的URI,但这并不会使您的API更多或更少RESTful。在这个问题上,使您的API RESTful是您的客户获取URI的方式,如果您的客户正在阅读文档中的URI模式而不是将其作为其他资源中的链接,那么您的API就不是RESTful。就这么简单。
答案 3 :(得分:1)
如果你在其他地方使用/customer/[id]
模式中的id,那么仅仅因为你认为没有其他人会看到它们而省略它就会很奇怪而且不一致。
如果客户看到的唯一订单是他们自己的订单,为什么不使用/orders
?这样,至少可以避免这种不一致。
但是,我更希望明确添加id。如果将来有来自客户支持的人想要查看订单,则必须更改URL或仅为此目的创建新URL。我建议严格区分资源标识和访问权限。