【问题标题】:In a RESTful application, how do we differentiate between an "action" and an HTTP verb (GET, POST, PUT, DELETE)?在 RESTful 应用程序中,我们如何区分“动作”和 HTTP 动词(GET、POST、PUT、DELETE)?
【发布时间】:2012-08-05 00:46:56
【问题描述】:

在 RESTful 应用程序中,我们如何区分“动作”和 HTTP 动词(GETPOSTPUTDELETE)?

例如,据我了解,对资源 /productsGET 请求应返回所有产品的列表。对/productsPOST 请求应该会创建一个新产品。那么,用户如何请求用于创建产品的原始表单?我最初的响应是对同一 URI 的 GET 请求,但如上所述,它应该返回所有产品的列表 - 而不是用于创建产品的空白表单。

在我研究过的大多数框架中,这个问题是通过将“动作”作为 URI 的一部分来解决的。例如,对/products/createPOST 请求将创建一个新产品,而对/products/createGET 请求将提供用于创建产品的空白表单。要获得所有产品的列表,将根据所讨论的框架向/products/products/get/products/read 等发送GET 请求。这种方法解决了上面的歧义,但它与我读到的关于传统 REST 设计的内容相冲突。

【问题讨论】:

  • but it conflicts with what I've read about traditional REST design -- 为什么?
  • @RobertHarvey:因为“动作”对于 HTTP 动词是多余的。如果在 URI 中指定了一个动作,那么您只需要两个动词(即GETPOST)。
  • 在纯 REST 环境中,您将访问资源,而不是操作。因此,要获取创建新产品的表单,您将在 /products/form URI 上发出 GET。然后,您可能会使用 Javascript 将表单转换为 JSON 请求,然后您将 PUT 发送到 /products。正如您已经指出的那样,它很少以这种方式工作,可能部分是出于方便的原因,部分是因为大多数 Web 资源通常没有充分利用 REST。
  • @RobertHarvey:如果我理解正确,您是说新产品的空白表单应该被视为它自己的资源(仅支持GET 方法),而不是而不是产品资源的操作?
  • 在 ASP.NET MVC 中,POST 动词由不同的控制器方法重载支持,该方法在提交时接受表单数据。

标签: api model-view-controller http url rest


【解决方案1】:

这里是 Rails 的例子

REST request path    |  action name | Description
---------------------|-------------------|-------------
GET    /profile/new  | new               | Render a form for creating the profile
POST   /profile      | create            | Create a the profile from the received data
GET    /profile      | show              | Render a the profile
GET    /profile/edit | edit              | Render a form for editing the profile
PUT    /profile      | update            | Update the profile based on the received data
DELETE /profile      | destroy           | Destroy the profile

我没有看到任何冲突,想法是这样的 url 是人类可读的,您可以引入新的 URI 来显示同一资源的不同表示。 (如 profile/1/edit 和 profile/1) /profile/new - 为空的配置文件的地址(如 show 方法中的 profile/1、profile/2 .. 等) 但是,如果您愿意,可以建议 profile/1/edit 是某种不同的 - profile/1/ 资源的嵌套资源,但我喜欢它只是 profile/1/ 资源的其他表示 =)

当您使用多个资源或一个示例时,使用复数和单数 URI 也是一个好主意

/profile/1.html - gives you 1 resource
/profiles.html - gives you list of profiles

【讨论】:

  • 嗯,有点。此方法仍然包括newedit 的“动作”,但忽略了其他多余的动作。我想这比DELETE /products/delete/123 之类的要好。
  • @drrcknlsn:在 ASP.NET MVC 中,这将是一个 POST 到 /products/delete/123。我从未见过有人真正在那里使用 DELETE 动词。
  • @RobertHarvey:这对我来说更令人困惑,因为我认为除了DELETE 之外不会使用任何其他东西来删除资源。不过,我有点理解使用 PUT 背后的基本原理,如果您打算将操作包含在 URI 中(比 GET /products/delete/123 或其他任何方法更有意义)。
  • @drrcknlsn:部分问题是您需要一个删除确认页面。所以delete url 实际上是一个确认页面的 GET。然后在提交确认表单时在 POST 控制器方法中在后台进行删除。无论如何,HTML 实际上只支持 GET 和 POST 动词。请参阅stephenwalther.com/archive/2009/01/21/… 了解更多信息。
  • @RobertHarvey,我们的谈话是关于 REST,而不是关于 HTML 真正支持的内容 =) REST 是关于 HTTP,几乎在所有 Web 框架中都有模拟 PUT、PATCH 和其他用于 html 的 http 动词的方法
【解决方案2】:

恕我直言,最好的选择是将请求方法作为控制器操作的一部分。

假设您正在访问 http://who.cares/product/42http://who.cares/product/42/specification 。这个对网络服务器的查询将转换为Product 控制器。动作名称需要结合请求方法和命令来创建:

DELETE "http://who.cares/product/42"

    controller: "Product", 
    action:     "deleteProduct()" 


GET "http://who.cares/product/42/details"

    controller: "Product", 
    action:     "getDetails()"


POST "http://who.cares/product/42/review"

    controller: "Product", 
    action:     "postReview()"


GET "http://who.cares/products/ 

    controller: "Products", 
    action:     "getProducts()"


POST "http://who.cares/products/ 

    controller: "Products", 
    action:     "postProducts()"

【讨论】:

  • 此选项如何处理请求空白表格以输入新产品? URI 和操作是什么?
  • 这或多或少是它在 ASP.NET MVC 中的工作方式。但由于控制器方法通常是 URL 的一部分,因此您仍然可以在 URL 中看到控制器方法名称,如 /products/create。 GET 和 POST 仅在表单请求和 SUBMIT 之间拆分。
  • @tereško:但这并不能解释请求新产品表单和提交表单之间的区别。我知道提交它会是一个POST /product,但是请求表单是什么?它不能是GET /product,因为它应该返回所有产品的集合。
  • @drrcknlsn , POST "http://who.cares/products/ 会变成 postProducts() 方法。回退命令(如果在 URI 中没有设置)与控制器的名称相同。老实说,我对PUTPOST 之间的区别还是有些困惑(我认为它们翻译为“save”和“add”)。您应该使用不同的控制器来处理项目列表:Products。还有一个处理单品的:Product.
  • @drrcknlsn ,我会选择GET "/products/new"。 REST 接口并非真正针对 HTML 应用程序。你这样做是为 3rd 方应用程序创建一个 API。因此,返回 HTML 表单的请求不必是 RESTful。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-12-27
  • 2013-08-26
  • 1970-01-01
  • 2018-06-23
  • 1970-01-01
  • 2011-01-30
  • 1970-01-01
相关资源
最近更新 更多