在Rails 3上,我正在尝试从没有尾部斜杠的URL重定向到带有斜杠的规范URL。
match "/test", :to => redirect("/test/")
但是,上面的路由匹配/ test和/ test /导致重定向循环。
如何使其仅匹配没有斜杠的版本?
答案 0 :(得分:5)
您可以在控制器级别强制重定向。
# File: app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
protected
def force_trailing_slash
redirect_to request.original_url + '/' unless request.original_url.match(/\/$/)
end
end
# File: app/controllers/test_controller.rb
class TestController < ApplicationController
before_filter :force_trailing_slash, only: 'test' # The magic
# GET /test/
def test
# ...
end
end
答案 1 :(得分:2)
ActionDispatch中有一个名为trailing_slash
的选项,可用于强制URL末尾的斜杠。我不确定它是否可以用在路由定义中。
def tes_trailing_slsh
add_host!
options = {:controller => 'foo', :trailing_slash => true, :action => 'bar', :id => '33'}
assert_equal('http://www.basecamphq.com/foo/bar/33/', W.new.url_for(options) )
end
在您的情况下,最好的方法是使用Rack或您的Web服务器来执行重定向。 在Apache中,您可以添加诸如
之类的定义RewriteEngine on
RewriteRule ^(.+[^/])$ $1/ [R=301,L]
将没有尾部斜杠的所有路由重定向到带有斜杠的相应路径。
或者您可以使用rack-rewrite在机架级别的Rails应用中执行相同的任务。
答案 2 :(得分:2)
我想为博客创建一个 cannonical 网址,这是有效的
match 'post/:year/:title', :to => redirect {|env, params| "/post/#{params[:year]}/#{params[:title]}/" }, :constraints => lambda {|r| !r.original_fullpath.end_with?('/')}
match 'post/:year/:title(/*file_path)' => 'posts#show', :as => :post, :format => false
然后我有另一个规则来处理帖子内的相对路径。顺序很重要,所以前者是先行,而通用则先行。
答案 3 :(得分:1)
防弹解决方案:
before_action :force_trailing_slash
...
private
def force_trailing_slash
return if trailing_slash?
url = url_for \
request.path_parameters
.merge(request.query_parameters)
.merge(trailing_slash: true)
redirect_to url, status: :moved_permanently
end
def trailing_slash?
URI(request.original_url).path.ends_with? '/'
end
答案 4 :(得分:0)
也许它适用于
match "/test$", :to => redirect("/test/")