37

在查询字符串与请求正文中的 REST URL 中传递数据的经验法则是什么?

即:您正在创建一项服务来添加曲棍球运动员。你可以去:

PUT /players 
{ "name": Gretzky }

或者

PUT /players?name=Gretzky

如果您要传递大量数据,则需要使用选项 #1,因为 URL 长度有限制。但除此之外,为什么不直接使用查询字符串来传递数据呢?


更新:删除了您可以在浏览器中测试选项 #2 的评论。意识到(duh)您只能在浏览器中执行 GET-s。

4

4 回答 4

34

根据 HTTP 对 PUT 的定义,您的第一个请求是用仅包含一个玩家名称的新列表覆盖玩家列表。它没有添加到玩家列表中。

第二个选项对我来说没有多大意义。没有body 做PUT 与PUT 的含义并不完全一致。

考虑到 POST 的标准定义之一是附加到现有资源,我不确定你为什么不这样做

POST /players 
{ "name": Gretzky }

如果您确定所有玩家名称都是唯一的,那么您可以像这样使用 PUT:

PUT /player/Gretzky
{ "name": Gretzky }

当您决定在 HTTP 上执行 REST 时,您同意以 RFC2616 中定义的方式使用 HTTP。这就是统一接口约束的含义。只是为了迂腐,没有 REST URL 这样的东西,你不能在浏览器中测试任何一个选项,因为没有 javascript,你不能在浏览器中执行 PUT。

于 2009-10-25T02:14:24.890 回答
3

选项 #1 很好,尽管可能有点矫枉过正。选项 #1不好,因为它不是幂等的。

选项#2 是个主意。那将是滥用 PUT。PUT 应该主要用于当您的请求数据有效负载是不透明的数据块时,通常是大的或分层的。较小的、非分层的有效载荷作为 POST 更有意义。

另外,尽量避免通过查询参数改变状态。如果不是 GET 请求,这在技术上没有什么危险,但它并不是真正的 RESTful。

在这种情况下,您应该做的是:

POST /players HTTP/1.1
Host: www.example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 12

name=Gretsky

这应该返回一个201 Created响应。(有一个例外:如果您不立即创建资源,并且以后可能会被拒绝,请202 Accepted改用。)

只有在阅读了HTTP 规范之后,才能编写使用比 POST 和 GET 更多的 HTTP 的 REST Web 服务。(这是一本非常有用的读物​​。)如果您使用的是为您做出所有决定的框架,那么该规则会稍微宽松一些。

于 2009-10-24T23:10:00.580 回答
2

我对 REST 操作的理解是 URL 唯一标识资源,而请求的主体包含资源的表示。鉴于此,您的任何一个选项是否真的是 RESTful 都值得怀疑。

第一个是,假设资源被命名为“玩家”并且该资源上的 GET 返回一个玩家列表(我不会讨论该 GET 是否返回其他资源 URL 的问题......菲尔丁会说它应该,通过单独的请求来获取资源数据)。

第二个是,假设请求正文包含名称为“Gretsky”的信息。但是,这需要您在外部生成密钥。

于 2009-10-24T22:44:27.040 回答
-2

使用的 url 应该通过路径组件或查询参数来标识正文中的资源,尽管我更喜欢路径组件来表示名称或 id 之类的东西。身体应该是一个代表;您 PUT 的内容应该与您从同一 url 获取的内容相同或相似(或者可以获取,在多种格式的情况下)

示例 #1 不合适,因为您将单个玩家的表示发送到所有玩家的 url。在这种情况下,POST 会更合适。

如果扩展到所有字段,示例 #2 会稍微不合适,因为您将在 url 中发送表示数据。

于 2009-10-24T22:35:30.200 回答