【问题标题】:How to use gem rack-rewrite to 301 redirect for full URL from naked domain to www domain如何使用 gem rack-rewrite 到 301 重定向从裸域到 www 域的完整 URL
【发布时间】:2016-07-05 06:42:39
【问题描述】:

我在 Heroku 上托管了一个 Rails 2.3.2 应用程序。

裸域和 www 子域是多年前添加的,它们对搜索引擎都有一定的权限。

但问题是搜索引擎将内容视为重复,因此我想从裸域执行 301 重定向到 www 子域。

我问过 Zerigo DNS 是否可以通过他们的平台来做这件事,他们说不行,我必须在 Heroku 这边做。 Heroku 不允许访问服务器,所以我需要一些 Rack 中间件来执行此操作。

根据这个答案here gem rack-rewrite 可以做到这一点。

但是我真的是一个 NOOB,我不知道如何设置它,以便裸域中的任何 url 都将被 301 重定向到 www 子域。

例子:

example.com/products/12 => www.example.com/products/12

我目前在应用程序控制器中做错如下:

 before_filter :ensure_domain

protected 

  def ensure_domain
      app_domain = "www.example.com"
      naked_domain = "example.com"
      page_path = request.fullpath
    if request.env['HTTP_HOST'] == naked_domain  && RAILS_ENV == 'production'
      #HTTP 301 is a permanent redirect
        redirect_to "http://#{app_domain}#{page_path}", :status => 301
    end
  end

这可行,但我知道我应该在机架中间件中这样做。

谁能告诉我如何使用 rack-rewrite gem 进行设置?

我已将以下内容添加到我的 application_controller.rb 文件中:

config.middleware.insert_before(Rack::Lock, Rack::Rewrite) do
 r301 %r{.*}, 'http://www.example.com$&', :if => Proc.new {|rack_env|
  rack_env['SERVER_NAME'] != 'www.example.com'
}
end

这会产生以下错误:

NameError(ApplicationController:Class 的未定义局部变量或方法“config”):

关于如何使此设置正常工作的任何想法?

【问题讨论】:

    标签: ruby-on-rails rack-rewrite


    【解决方案1】:

    您也可以使用rack-host-redirect gem。添加到 Gemfile:

    gem 'rack-host-redirect'
    

    config/environments/production.rb:

    config.middleware.use Rack::HostRedirect, {
      'yourdomain.com' => 'www.yourdomain.com'
    }
    

    使用此配置,所有对yourdomain.com 的请求都将被301 重定向到www.yourdomain.com

    【讨论】:

      【解决方案2】:

      example.com/products/12 => www.example.com/products/12

      为了解决 Heroku 的这个问题,我必须正确设置我的域名托管服务商。您要查找的内容称为转发。接下来,您要启用“保留相对路径”选项。

      所以,寻找:

      1. 重定向类型:301 永久
      2. 转发设置:仅转发
      3. 保持相对路径

      这一切都应该在您的域名注册商级别上可用。

      【讨论】:

      • 我联系了我的 DNS 主机,但他们没有这个选项。这就是为什么我用 rack-rewrite 尝试这条路径。他们有一个转发选项,但没有“保持相对路径”。
      【解决方案3】:

      原来我在使用这个 gem 时遇到了两个问题。

      首先是我将重定向代码放在 Application_Controller 而不是 congig.ru 文件中。

      第二个是我使用的代码不正确。

      这是我放在 config.ru 文件中的代码:

      if RAILS_ENV =='production'
          use Rack::Rewrite do
              r301 %r{.*}, 'http://www.example.com$&', :if => Proc.new {|rack_env|
              rack_env['SERVER_NAME'] != 'www.example.com'
              }
          end
      end
      

      【讨论】:

      • 您可以将此代码移至config/environments/production.rb,而不是if RAILS_ENV =='production'
      • 你应该把生产配置放在config/environments/production.rb
      • 我添加了 if RAILS_ENV='production' 以便重定向不会在我的本地主机上发生。
      • 我将此代码放在 config.ru 中,因为这就是该 gem 的文档所述的内容。当我将它放在 production.rb 文件中时,我也遇到了错误
      【解决方案4】:

      根据the gem's README,您需要将以下内容添加到您的应用程序的config/application.rb

      config.middleware.insert_before(Rack::Lock, Rack::Rewrite) do
        moved_permanently /.*/, 'http://www.example.com$&', if: ->(env){env['SERVER_NAME'] != 'www.example.com'}
      end
      

      我已经对示例代码进行了现代化改造,并在 Rails 3 应用程序上对其进行了测试。

      moved_permanently 方法的参数是:

      1. /.*/ 是一个正则表达式,匹配任何请求路径和 url 参数,因此匹配网站上的任何页面。
      2. 'http://www.example.com$&' 是页面的新完整 URL(重定向后)。它具有正确的域名和附加的原始请求路径——$& 符号表示“与第一个参数匹配的任何内容”,它匹配所有内容。
      3. if: ->(env){env['SERVER_NAME'] != 'www.example.com'} 是此重写规则的选项哈希。在这种情况下,它只有一个名为if 的选项。该选项的值是一个 lambda 函数:->(env){env['SERVER_NAME'] != 'www.example.com'}

      gem 将为每个请求调用此 lambda。它将所有环境变量的哈希作为参数传递给它。 (我调用了参数env,但名称可以是任何名称。)

      lambda 从它读取客户端用来向站点发出请求的域名:env['SERVER_NAME']。它会检查域是否正确。

      • 如果域不正确,则返回true。在这种情况下,并且仅在这种情况下,gem 将重写 URL 并向客户端返回状态 301。
      • 如果域是正确的,它返回false。在这种情况下,不会执行任何操作,请求将“传递”到应用程序(传递到其他中间件)。

      【讨论】:

      • 谢谢伊利亚。我想了解这是否会重定向所有 URL 而不仅仅是基本主机。所以 example.com/products/34 到 www.example.com/products/34
      • 是的。我添加了参数说明。希望这会有所帮助!
      猜你喜欢
      • 2021-06-02
      • 2015-01-07
      • 2011-04-01
      • 2020-02-17
      • 2013-10-31
      • 2014-03-29
      • 1970-01-01
      • 1970-01-01
      • 2012-01-19
      相关资源
      最近更新 更多