如何使用gem rack-rewrite将301重定向从裸域到www域的完整URL

时间:2016-07-05 06:42:39

标签: ruby-on-rails rack-rewrite

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

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

然而问题是搜索引擎看到内容是重复的,所以我想从裸域重定向到www子域。

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

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

然而,我真的是一个关于此的NOOB,我不知道如何设置它,以便裸域中的任何URL将被重定向到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 Middleware中这样做。

有人可以告诉我如何使用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(未定义的局部变量或方法`config' for ApplicationController:Class):

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

4 个答案:

答案 0 :(得分:2)

您也可以使用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的请求都将被重定向到www.yourdomain.com

答案 1 :(得分:0)

根据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. /.*/是一个正则表达式,匹配任何请求路径和网址参数,因此,网站上的任何页面。
  2. 'http://www.example.com$&'是页面的新完整网址(重定向后)。它有正确的域名和附加到它的原始请求路径 - $&符号表示“第一个参数匹配的任何内容”,它匹配所有内容。
  3. if: ->(env){env['SERVER_NAME'] != 'www.example.com'}是此重写规则的选项哈希。在这种情况下,它只有一个名为if的选项。选项的值是lambda函数:->(env){env['SERVER_NAME'] != 'www.example.com'}
  4. gem会为每个请求调用此lambda。它会将所有环境变量的哈希值作为参数传递给它。 (我调用了参数env,但名称可以是任意名。)

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

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

答案 2 :(得分:0)

  

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

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

所以,请寻找:

  1. 重定向类型:301永久
  2. 转发设置:仅转发
  3. 保持相对路径
  4. 这应该在您的域名注册商级别上提供。

答案 3 :(得分:0)

我发现在使用这个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