3

所以,我正在学习 Ruby on Rails。我了解了应用程序架构的 RESTful 方法的基础知识,但我还没有完全构建一个 RESTful 应用程序。

在传统的 Web 应用程序中,幂等请求(不改变任何状态)是通过 HTTP 的GET方法发出的,所有非幂等请求通常都是通过该POST方法发出的。为了让应用程序区分POST请求可能触发的不同操作,通常在POST请求中包含一个隐藏字段,例如action=deleteaction=add_to_foo_file。这是一个相当简单的架构,并且在今天很常见,但是 REST 方法让我们远离它,并建议“让我们发布所有内容!” 设计被认为是有害的。

相反,RESTful 架构让我们通过唯一标识资源的 URI(名词)和 HTTP 请求方法(动词)来操作资源,而不是根据请求中的单独字段确定要采取的操作:

GET    => show the resource
PUT    => update the resource
POST   => create a new resource
DELETE => destroy the resource

所以现在我们来到 Ruby on Rails。在 Rails 中,PUT并由DELETEJavaScript 实现,它将您的链接更改为带有隐藏字段的表单,称为_method. 浏览器通过 接收表单POST,然后 Rails 查找该字段并决定是否将请求路由到控制器的PUTDELETE方法。

等等,什么?这听起来有点像——甚至完全像——传统 Web 应用程序的行为,它通过接收所有状态更改请求POST并检查特定字段以决定是否销毁或修改记录。

那么,Rails 的方法怎么能说是 RESTful呢,因为在底层,它只是对 REST 专门试图摆脱的“让我们发布一切”方法的重新实现?

而且,这种方法不会阻止我的 Rails 应用程序优雅地降级,因为在浏览器中关闭了 JS 的人?

4

3 回答 3

4

What makes a system RESTful or not isn't so much the verb it uses, but the fact the interactions are driven by the hypermedia (in this case, this includes code-on-demand JavaScript).

The GET/PUT/POST/DELETE mapping you're quoting works fine for CRUD operations, but isn't necessarily appropriate for everything (and isn't necessarily supported by all browsers). This is a reasonable rule of thumb to design a RESTful system, but it's neither sufficient nor necessary. (It's in the same category of ideas as what people insist on when they want "RESTful" URIs: there's no such thing.)

Part of this comes under influence of books like RESTful Web Services. It's a good book, but it came out at a time where WS-*/SOAP was predominant, and where everything was tunnelled through POST. A reaction to SOAP was to make people aware that there were other HTTP verbs they could use.

For REST, what really matters in particular is to respect the notions behind the URI concept, the semantics of each HTTP verb (no side-effects, idempotent requests, ..., where appropriate and if you're using HTTP) and the HATEOS principle. It's an architectural style, don't stress too much about what POST/PUT/DELETE the JavaScript does underneath.

You should certainly read these:

EDIT: (Following comments)

What I should have said was this: If most frameworks turn DELETE http://server.tld/resource/1 into POST http://server.tld/resource/1?_method=DELETE, then what's the advantage of that approach over just using POST http://server.tld/resource/1?my_method=delete in the first place?

  • It makes the overall goal a little bit cleaner/clearer, in terms of API design. REST frameworks can ultimately only be as RESTful as one uses them, since REST is an architectural style, not a protocol or an implementation.
  • In addition, strictly speaking, the URI includes the query component, so http://server.tld/resource/1 and http://server.tld/resource/1?my_method=DELETE could identify different resources in principle (although that wouldn't be a good design choice).
  • It's good for the framework to be able to expose DELETE/PUT as such directly, but have a fallback solution via POST for the clients that don't support it.

    The reason for this is that clients that do support DELETE/PUT will be able to make use of them, and make assumptions about their usage. It's not so much of a problem for the client to treat a request as non-idempotent even if it was idempotent in principle as the opposite. If the client thinks it can send at most 1 request (non-idempotent) when it could have sent N+1 of the requests, this doesn't cause major problems; if the client thinks it can send N+1 times the same request for something that shouldn't be idempotent, this can cause quite a lot of problems. Emulating PUT through POST is OK, you're just not making the most of PUT, emulating POST through PUT would be problematic.

于 2012-07-27T19:12:57.443 回答
1

Rails 当然支持正确的 HTTP 动词(很快甚至支持 PATCH)。唯一的问题是:浏览器不支持,因为它们只支持 GET 和 POST。_method为了规避这个限制,Rails 提供了额外的工具来使用您所描述的参数“覆盖”实际的 HTTP 动词。

使用 API 的主要且正确的方法是通过实际的 HTTP 动词来代替。有了一个有能力的客户,您可以并且被鼓励这样做。

至于您关于优雅降级的第二个问题,由您作为开发人员来确保您的应用程序在所有对您重要的情况下都能正常工作。如果您希望您的应用程序在没有 JavaScript 的情况下运行,您可以随时创建实际的 HTML 表单和提交按钮。如果您真的想要一个创建 PUT 的链接,生成的 Javascript 链接只是另一种方式。同样,Rails 认为这不是什么好东西,而是一种规避当前所有浏览器实现所施加的限制的方法。

于 2012-07-27T18:58:37.970 回答
1

PUT 和 DELETE 请求的问题在于 HTML 表单不支持它。大多数框架处理这个问题的方式是通过 POST 请求对它们进行隧道传输。

您仍然可以执行“curl -X DELETE http://example.com/posts/1 ”,这仍然有效。

虽然,对 Rails 和 Rest 有很多误解。看看http://en.wikipedia.org/wiki/HATEOAShttp://nicksda.apotomo.de/2010/12/rails-misapprehensions-rest-is-more-than-get-post-put-和删除/

于 2012-07-27T19:01:02.270 回答