我试图通过在文件的路由上设置一个约束来对特定文件进行IP白名单访问。
## config/routes.rb
get 'SOME FILE',
to: 'main#(function that renders the file as plain)',
constraints: <IP CONSTRAINT CLASS>.new
## (ip constraint class).rb
require 'ipaddr'
WHITELIST = %w(8.8.8.8/27).freeze
def matches?(request)
request && APPLE_IP_WHITELIST.reduce(false) do |match, range|
match || IPAddr.new(range).include?(request.remote_addr)
end
end
对于白名单之外的is,将抛出一个RoutingError。我尝试使用catch all路由来处理错误。
## config/routes.rb
get '*unmatched_route', :to => 'application#show_not_found', via: :all
## app/controllers/application_controller.rb
def show_not_found
render_error_status(404)
end
def render_error_status(status)
@status = status
template = case @status
when 400, 401, 403, 405
'application/errors/standard'
when 404, 422
'application/errors/with_block'
when 500
'application/errors/custom_500'
end
render template: template, layout: 'error', status: @status
end
有趣的是,当我尝试访问一些无意义的路由时,比如'localhost:3000/asdf',将显示正确的404页(application/errors/with_lock.html.haml)。但是,当处理白名单RoutingError时,我将得到一个
ActionView::MissingTemplate (缺少模板应用程序/错误/ with _block与{:locale=>:en,:formats=>:text,:variants=>[],:handlers=>:raw,:erb,:html,:builder,:ruby,:haml,:咖啡})。搜索:*“./app/view”*“. /.rbenv/versions/2.5.7/lib/ruby/gems/2.5.0/gems/kaminari-0.17.0/app/views”):
tldr:如何处理由于约束失败而产生的RoutingError?
编辑:它似乎是格式::html需要在调用呈现时添加-但是为什么这是必要的现在而不是其他时候,当render_error_status被调用?
发布于 2020-02-26 03:20:31
主要问题在于请求类型,当路由约束失败Rails试图查找文本格式的文件时,请参见错误:
ActionView::MissingTemplate (Missing template application/errors/with_block with {:locale=>[:en], :formats=>[:text]
这是因为您从路由请求文本文件,由于路由约束失败,无法返回该文本文件。因此,当请求类型为text
时,错误页面也应该是该格式的。例如,如果我有一个API,其中我发送了一个JSON
请求,如果存在权限问题,并且我提供了HTML
响应,那么它对API没有任何用处。因此,在使用默认约定时,Rails中的请求和响应格式应该是相同的。
您的方法应该有如下所示的不同响应类型:
def render_error_status(status)
status = status
template = case status
when 400, 401, 403, 405
'application/errors/standard'
when 404, 422
'application/errors/with_block'
when 500
'application/errors/custom_500'
end
respond_to do |format|
format.html { render template, status: status }
format.text { render text: 'Not found', status: :not_found }
end
end
还有其他选项可以这样做,比如在遇到文本请求时使用HTML进行响应,但是标准的Rails方式是这样的。
https://stackoverflow.com/questions/60411506
复制