Rails 如何在 routes.rb 中忽略掉一个 route,使其不被 routes.rb 中的规则匹配到?

ibachue · December 07, 2011 · Last by 404 replied at June 07, 2012 · 3486 hits

我们希望设定 custom 的 404 页面,因此在 config/routes.rb 的最后加了句: match '*path' => 'home#construction' 这个是可以成功的,但是我们的网站还是用了 omniauth 用于做新浪的 oauth,在 oauth 的过程中,有一步是要跳转到'/auth/tsina'这个路径,这个路径没有出现在 routes.rb 中,是由 omniauth 在底层用 rack 处理的。如果 config/routes.rb 中没有match '*path' => 'home#construction'这句,rails 在 routes 中找不到匹配'/auth/tsina'的路径后就会由 rack 处理,从而 omniauth 可以正常处理。但是加了 match '*path' => 'home#construction',所有路径都会被匹配到,所以访问'/auth/tsina'就会到'home#construction'去,oauth 无法正常运行。所以希望在 match '*path' => 'home#construction'前能够忽略掉'/auth/tsina',不匹配这个地址,然后把这个地址转移到 rack 处理。请问如何实现?

你这样做 404 不对吧,这只是路由没匹配上的情况,如果是 find() 没找到的 404 你不就漏掉了么

rack 处理比 route 要前,应该不会被路由规则干扰阿。

然后处理 404 应该用 rescue_from(曾经某个版本的 rescue_from 不能正确处理路由缺失,现在已经好了)

@Rei,我刚才在 Rails 3.1.3 里测试了 rescue_from,依旧不能成功捕获到 ActionController::RoutingError 这个错误(之前知道这个函数,也知道它有 Bug),所以我不知道你说“现在已经好了”是什么情况。能给一个成功的例子么?

#3 楼 @iBachue 抱歉,我也是道听途说,刚测试了一下,依然无法捕获

https://github.com/rails/rails/issues/671

看后面讨论似乎是不打算修复了,依然需要那条路由。

然后回到主题,omniauth 运行在 rack 层,应该不会被 route 里面的规则影响阿。

$cd ruby-china
$rake middleware
use ActionDispatch::Static
use Rack::Lock
use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x00000003bbfa50>
use Rack::Runtime
use Rack::MethodOverride
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use ActionDispatch::RemoteIp
use Rack::Sendfile
use ActionDispatch::Reloader
use ActionDispatch::Callbacks
use ActionDispatch::Cookies
use ActionDispatch::Session::CookieStore
use ActionDispatch::Flash
use ActionDispatch::ParamsParser
use ActionDispatch::Head
use Rack::ConditionalGet
use Rack::ETag
use ActionDispatch::BestStandardsSupport
use Warden::Manager
use Rack::Mongoid::Middleware::IdentityMap
use OmniAuth::Strategies::GitHub
use OmniAuth::Strategies::Twitter
use OmniAuth::Strategies::Douban
use OmniAuth::Strategies::OpenID
run RubyChina::Application.routes

最后才到 Route::Application.routes

如果真的不行,把 404 路由改成

match '*path' => 'home#construction', :constraints => { :path => /^(?!auth).*/ }

#4 楼 @Rei 为什么 omniauth 在 routes 之后被匹配我也不知道,但是很感谢你的后面一句语句,我现在就是这么实现的。谢谢。

@iBachue

match '*path' => proc { |env| ApplicationController.action(:not_found).call(env) }, :constraints => {:path => /^(?!users\/auth).*/}

结果

=>        /*path(.:format)                         {:path=>/.+?/}

再怎么配 constraints ,path 结果都是/.+?/ 比较郁闷呢,除非把 'path' 改 '', 但 proc 就不执行了 遇到了同样的问题

#5 楼 @iBachue 感谢人,不能感谢语句。XD

fuck,终于 ok 了,这叫个难受呀

match '*path' => proc { |env| ApplicationController.action(:not_found).call(env) }, :constraints => proc {|req| req.path =~ /ooxx/}
9 Floor has deleted
You need to Sign in before reply, if you don't have an account, please Sign up first.