【问题标题】:Why is post request favoured over delete in rails?为什么在 Rails 中发布请求优于删除?
【发布时间】:2011-08-05 12:43:03
【问题描述】:

我在很多使用 Ruby-on-Rails 编写的代码中都看到了这一点。

似乎帖子请求通常比删除请求更受欢迎

 def destroy 
  relation = IssueRelation.find(params[:id])
  if request.post? && @issue.relations.include?(relation)
    relation.destroy
    @issue.reload
  end
 end

我觉得这有点奇怪,因为它似乎不遵循 Rails 中如此多使用的 REST 约定。

这是否与安全有关,还是为了与一些不支持删除请求的旧浏览器兼容?

【问题讨论】:

  • 除了其他人提供的信息外,它还确保请求不是获取请求,它可以由爬虫触发,您不想丢失您网站上的所有数据,因为有人被试图漫不经心地抓取它。

标签: ruby-on-rails ruby ruby-on-rails-3 ruby-on-rails-plugins redmine


【解决方案1】:

您基本上回答了您自己的问题,浏览器并不完全支持所有 HTTP 动词。有一个不错的网站,您可以在其中测试您当前的浏览器支持什么,看看有哪些失败之处,我相信您会注意到一些关于 delete 的内容,例如涉及重定向时:

http://www.mnot.net/javascript/xmlhttprequest/

【讨论】:

    【解决方案2】:

    删除请求不是完整的真正删除请求。它实际上是伪造的,就像您在保存的对象上使用 form_for 时的 put 请求一样。据我所知,没有理由不使用提供的 REST 约定。

    另一方面,sn-p 中的代码是您自己的代码,还是示例?有点好奇为什么您要检查您要删除的记录是否与父级相关联。我想总有可能在您单击删除和它收到请求之间,有人在其他地方更改了它的父项。

    编辑,这是我在 rails 3 脚手架应用程序中单击删除链接时的标题信息:

    Request URL:http://phone_qa.dev/sites/2
    Request Method:POST
    Status Code:302 Moved Temporarily
    Request Headersview source
    Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
    Accept-Encoding:gzip,deflate,sdch
    Accept-Language:en-US,en;q=0.8
    Cache-Control:max-age=0
    Connection:keep-alive
    Content-Length:86
    Content-Type:application/x-www-form-urlencoded
    Cookie: _phone_qa_session=BAh7B0kiD3Nlc3Npb25faWQGOgZFRkkiJTg4Y2Q4ZTgyOGYwM2IyMWI1N2Y4MjYyMTcwMzJiMzMwBjsAVEkiEF9jc3JmX3Rva2VuBjsARkkiMVY0QkFIOXdzRFZXZi9yYnlkODJCUEdLTisvT2V6dVpkVDYyckkyR3JQSzg9BjsARg%3D%3D--e8244fd59e5fc34b37a93c2e768ace7a3bfffe44
    Host:phone_qa.dev
    Origin:http://phone_qa.dev
    Referer:http://phone_qa.dev/sites
    User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.107 Safari/535.1
    Form Dataview URL encoded
    _method:delete
    authenticity_token:V4BAH9wsDVWf/rbyd82BPGKN /OezuZdT62rI2GrPK8=
    

    你可以看到它实际上是一个post请求,但是在表单数据下,有一个名为_method的变量,其值为delete。

    【讨论】:

    • 代码是我从 Redmine 控制器类中获取的示例 sn-p。
    【解决方案3】:

    该代码 sn-p 来自 Redmine,于 2007 年 5 月提交:https://github.com/edavis10/redmine/blob/92b02014d21f0e60230fc7a5c3c5ad71dac6e472/app/controllers/issue_relations_controller.rb

    那是很久以前的事了,如果我没记错的话,那时 REST 并没有那么广为人知,也没有在 Rails 中得到很好的实现。上述模式在当时是一种明智的做事方式。

    为了比较,现在 Redmine 中的相同操作如下所示:

    verify :method => :delete, :only => :destroy, :render => {:nothing => true, :status => :method_not_allowed }
    def destroy
      raise Unauthorized unless @relation.deletable?
      @relation.destroy
    
      respond_to do |format|
        format.html { redirect_to :controller => 'issues', :action => 'show', :id => @issue }
        format.js { render(:update) {|page| page.remove "relation-#{@relation.id}"} }
        format.api { head :ok }
      end
    rescue ActiveRecord::RecordNotFound
      render_404
    end
    

    它不仅验证 HTTP 动词是否为 DELETE(尽管由于浏览器缺乏支持而被伪造),而且它还能够响应不同 MIME 类型的请求 - 现在更加 RESTful。

    【讨论】:

    • 100% 正确。 Redmine 中的很多代码都在 REST 流行之前,因此使用了 POST 和 POST-back 操作。我重构了一堆,但还剩下很多。
    猜你喜欢
    • 2018-03-15
    • 2021-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-23
    • 1970-01-01
    • 2019-11-19
    • 1970-01-01
    相关资源
    最近更新 更多