如何限制 Rails 路由文件中的资源格式

Posted

技术标签:

【中文标题】如何限制 Rails 路由文件中的资源格式【英文标题】:How to limit the resource formats in the Rails routes file 【发布时间】:2010-11-25 08:32:04 【问题描述】:

在 Rails 中路由资源时,可选的格式属性会自动附加到生成的路由中。这样可以将相关资源请求为 XML、html 等。实际允许的格式通常在控制器中使用respond_to 进行描述。

但在许多情况下,您只想支持 HTML,并且在每个控制器的每个操作中都写 respond_to :html 感觉像是一种开销。因此,如果在 routes.rb 文件中构建路由时已经有一种方法可以限制允许的内容类型,那就太酷了,例如

map.resources :users, :formats => :html
map.resources :users, :formats => [:html, :xml]
map.resources :users, :formats => :index => :html, :show => [:html, :xml]

有没有办法通过本机或插件来实现这一点?

附:解决此问题的常用方法是忽略该问题并且不要在操作中使用respond_to。但这实际上并不限制允许的内容类型。相反,它只期望在视图目录中存在每个可能的内容类型的模板。如果请求时不存在,系统将抛出 HTTP 500 错误。

【问题讨论】:

【参考方案1】:

如果要将这些路由限制为特定格式(例如 html 或 json),则必须将它们包装在范围内。不幸的是,在这种情况下,约束不能按预期工作。

这是一个这样的块的例子......

scope :format => true, :constraints =>  :format => 'json'  do
  get '/bar' => "bar#index_with_json"
end

更多信息可以在这里找到:https://github.com/rails/rails/issues/5548

这个答案是从我之前的答案复制过来的。

Rails Routes - Limiting the available formats for a resource

【讨论】:

【参考方案2】:

由于 Rails 使用等效的通配符来处理格式“.:format”,因此在路由方面防止事情变得有点困难。

取而代之的是,在前置过滤器中捕获任何非 HTML 请求是一种非常简单的方法。这是可能的一种方式:

class ApplicationController < ActionController::Base
  before_filter :check_format

  private

    def check_format
      if request.format != Mime::HTML
        raise ActionController::RoutingError, "Format #params[:format].inspect not supported for #request.path.inspect"
      end
    end

end

ActionController::RoutingErrors 作为 404 错误处理,这是明智的。 如果您确实有需要支持 HTML 以外的其他内容的操作,只需使用:

skip_before_filter :check_format, :only => ACTION_NAME

【讨论】:

【参考方案3】:

我相信你能够做到这样的事情:

respond_to do |format|
  format.html
  format.json  render :json => @things 
  format.any  render :text => "Invalid format", :status => 403 
end

如果用户请求 html 或 json,它会按照应有的方式进行处理,但其他任何内容都会呈现“无效格式”文本。

【讨论】:

这可行,但我认为他想从路线中删除 :format【参考方案4】:

在任何一种情况下,您都不想出现 HTTP 500 错误吗?就像在您的示例的第二行中一样,如果有人请求 JSON 而不是 HTML 或 XML 不是错误代码返回适当的响应?

【讨论】:

不,500 错误意味着服务器出现问题。如果不支持内容类型,则不是服务器错误 - 这是客户端错误(客户端不应该请求它)。 406 将是正确的响应代码。请参阅“HTTP 响应代码”:sitepoint.com/blogs/2008/02/04/restful-rails-part-i 当然,如果您要在 URL 末尾标记 .xml 或 .html 并且不支持该格式,那么您应该返回 404 not found。通过为每个内容类型创建 URL 来忽略 conneg 的使用,然后在接受标头中没有有效的内容类型时窃取响应代码,这似乎有点厚颜无耻! 好吧,你可能有一点道理——尽管这实际上是 Rails 开箱即用的工作方式。但是,这不是我的问题的重点。我仍然想在一个中心位置(最好是路由文件)指定这个 - 无论是在错误时返回 404 还是 406 抛开要返回的正确代码。我认为关键是按照惯例,它正在做它应该做的事情,你所建议的似乎是为了配置而配置。【参考方案5】:

而不是做:

def some_action
  ...
  respond_to do |format|
    format.html
    format.json  whatever 
    format.any  whatever  
  end
end

只需使用:

def some_action
  ...
end

Rails 将默认查找 some_action.html.erb 或任何请求的格式。如果您没有定义除 html 之外的任何视图,那么所有其他格式都将在请求时失败。

【讨论】:

以上是关于如何限制 Rails 路由文件中的资源格式的主要内容,如果未能解决你的问题,请参考以下文章

Rails:将 API 请求限制为 JSON 格式

如何避免Rails 5嵌套资源命名空间路由中的双下划线

Linux中如何解除最大进程数和最大文件句柄打开数限制?

Rails 路由:如何重命名(嵌套)资源块中的 params-Hash 键?

6--Rails架构中的资源2

如何使用 api 网关限制资源访问