4

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

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

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

我已经问过 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”):

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

4

4 回答 4

2

你也可以使用rack-host-redirect宝石。添加到 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.

于 2016-07-15T23:02:59.627 回答
0

根据gem 的 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如果域是正确的,它会返回。在这种情况下,不会采取任何行动,请求将“通过”应用程序(到其他中间件)。
于 2016-07-14T21:14:20.467 回答
0

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

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

所以,寻找:

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

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

于 2016-07-15T06:20:00.623 回答
0

我发现我在使用这个 gem 时遇到了两个问题。

首先是我将重定向代码放在 Application_Controller 而不是 conig.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
于 2016-07-15T08:47:54.590 回答