在Rails 3中没有尾随斜杠的情况下重定向到规范路由

时间:2011-12-21 12:30:48

标签: ruby-on-rails ruby-on-rails-3 redirect routing canonical-link

在Rails 3上,我正在尝试从没有尾部斜杠的URL重定向到带有斜杠的规范URL。

match "/test", :to => redirect("/test/")

但是,上面的路由匹配/ test和/ test /导致重定向循环。

如何使其仅匹配没有斜杠的版本?

5 个答案:

答案 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/")