URL中没有ID的RESTful API

URL中没有ID的RESTful API,rest,asp.net-web-api,restful-authentication,restful-url,restful-architecture,Rest,Asp.net Web Api,Restful Authentication,Restful Url,Restful Architecture,我一直在和我的一位同事讨论最好的方法 下面是一个示例场景: 我正在尝试获取ID为1234的客户的所有订单 考虑以下端点: /客户/订单 使用GET请求,具有以下标头: 授权:基本QWXHZGRPBJPCGVUIHNLC2FTZQ== 通过Authorization标题,我们的身份验证机制将此请求标识为ID为1234的客户,我们的服务将返回所需的订单 他试图说服我这是对的,因为一个登录的客户只会请求他们的订单(在本例中,订单属于客户1234)——因此在URL中传递ID是不必要的。 然而。。。。对我

我一直在和我的一位同事讨论最好的方法

下面是一个示例场景:

我正在尝试获取ID为1234的
客户的所有订单

考虑以下端点:

/客户/订单

使用GET请求,具有以下标头:

授权:基本QWXHZGRPBJPCGVUIHNLC2FTZQ==

通过
Authorization
标题,我们的身份验证机制将此请求标识为ID为1234的客户,我们的服务将返回所需的订单

他试图说服我这是对的,因为一个登录的客户只会请求他们的订单(在本例中,订单属于客户1234)——因此在URL中传递ID是不必要的。 然而。。。。对我来说,这并不平静(我可能错了)

在我看来,应该是这样的:

/客户/1234/订单

使用标题(作为示例)

授权:基本QWXHZGRPBJPCGVUIHNLC2FTZQ==

使用授权标头,我们验证用户是否有权检索这些订单。。。如果是,请退回,否则请退回401

我的问题是,哪种方法更可取


我当然可以看到第一种方法的好处,但为了保持api的RESTful,我的心说要使用第二种方法……

我认为只有当您要允许客户检索其他客户的订单数据时,才需要第二种实现(包括客户ID)。换句话说,如果客户4321将能够看到客户1234的订单历史记录,那么发送该记录是绝对必要的

我猜他们不会那么做的。这意味着,如果您包含该信息,您很可能会忽略它,而使用授权代码

如果是这样的话,我说甚至不要发送它

如果这能让你感觉更好,LinkedIn的RESTAPI会反映出这种行为。任何用户都可以请求任何其他用户的配置文件,但如果省略id,则假定当前用户正在请求自己的配置文件。


尽管如此,只要它对您有意义,并且您对它进行了记录,那么无论哪种方式,您都应该很好。

识别资源是一个关键的REST约束。您的订单和我的订单不是同一个资源,因此它们应该(不是必须)具有不同的标识符

您应该给他们一个唯一标识符(即/customers/1234/orders)的实际原因是,支持HTTP缓存会容易得多。HTTP缓存中介主要使用URI作为缓存密钥。通过使用vary报头,可以使用其他报头(如auth)作为缓存密钥的一部分,但是,对此类机制的支持不太可靠/广泛

即使今天您还没有使用HTTP缓存的计划,但最好谨慎行事,并确保您的URI设计为在将来需要时允许此功能


在进行客户端URI构造时,不必在URI中包含客户ID有一些好处。然而,RESTful系统应该通过将这些URI嵌入到返回的表示中来为客户端提供URI。客户端不需要构建这些URI,因此,客户端使用带有id的URI与使用不带id的URI一样没有额外的工作。如果您准备吞下超媒体药丸,那么不包含id没有任何好处。

两者都不是RESTful。URI的语义应该与RESTful应用程序中的客户端无关

REST是一种基于web本身的体系结构样式。想想看。当您转到Stack Overflow时,您唯一关心的URI是
stackoverflow.com
。登录后,您将被重定向到主页,主页的URI与此无关。现在,我的菜单栏上有一个指向我主页的链接,你有一个指向你主页的相同链接,我们不在乎单击它时URI是什么,对吗?在我们的主页上,我们看到问题和答案,我们也不关心他们的URI,只关心他们的标题和描述

现在,让我们把它倒过来。REST being是web的体系结构风格,如果web像您认为的REST一样,那么当您加入
stackoverflow.com
时,您会看到一条文字,上面写着“您的id是131809,请使用URI模式/users/(id)”,而不是一个指向主页的漂亮链接,用这个号码替换id,粘贴在地址栏上,你就会进入你的主页”,你会想,“为什么那些白痴不为这个链接?”

这听起来很可笑,但大多数人认为休息就是这样

这意味着,与其担心用户的订单是否应该位于
/customer/(customer_id)/orders
,或者仅仅是
/customer/orders
,甚至是
/orders
,并依赖于他的凭证,迫使客户知道所有这些URI模式,不如在API入口点给他一个根文档,这会考虑到他的凭据,并为URI提供标准的标题和描述,就像您登录时任何网站所做的一样

假设您使用JSON,您的API是
myapi.com
。这应该是客户端唯一知道的URI。当他向该根文档发出
GET
请求,并使用适当的授权头时,他应该得到一个JSON文档,如:

{"orders": "http://myapi.com/customer/123456/orders"}
显然,他不需要知道“orders”的值是什么,只需要知道它是一个有效的URI,它将引导他找到另一个包含他的订单集合的资源。URI可以是任何东西,它的语义并不重要。这可能是你朋友的建议:

{"orders": "http://myapi.com/orders"}
或任何其他可以随时更改的内容:

{"orders": "http://myapi.com/this/is/a/meaningless/uri"}
当然,您应该努力创建清晰而有意义的URI,但这并不能使您的API或多或少具有RESTful。在哪里