如何限制 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 路由文件中的资源格式的主要内容,如果未能解决你的问题,请参考以下文章