如何使用 gem rack-rewrite to 301 redirect 从裸域到 www 域的完整 URL
How to use gem rack-rewrite to 301 redirect for full URL from naked domain to www domain
我有一个 Rails 2.3.2 应用程序托管在 Heroku 上。
裸域和www子域是几年前添加的,都对搜索引擎有一定的权限。
然而,问题是搜索引擎将内容视为重复内容,因此我想进行从裸域到 www 子域的 301 重定向。
我问过 Zerigo DNS 是否可以通过他们的平台来做这件事,他们说不行,我必须在 Heroku 那边做。 Heroku 不允许访问服务器,所以我需要一些 Rack 中间件来执行此操作。
根据这个答案here gem rack-rewrite 可以做到这一点。
然而我真的是一个菜鸟,我不知道如何设置它,以便任何来自裸域的 url 都将被 301 重定向到 www 子域。
示例:
例子。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”):
关于如何让这个设置工作的任何想法?
根据 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
方法的参数是:
/.*/
是匹配任何请求路径和 url 参数的正则表达式,因此,站点上的任何页面。
'http://www.example.com$&'
是页面的新完整 URL(重定向后)。它具有正确的域名和附加的原始请求路径——$&
符号表示 "whatever is matched by the first parameter",它匹配所有内容。
if: ->(env){env['SERVER_NAME'] != 'www.example.com'}
是此重写规则的选项散列。在这种情况下,它只有一个名为 if
的选项。该选项的值是一个 lambda 函数:->(env){env['SERVER_NAME'] != 'www.example.com'}
。
gem 将为每个请求调用此 lambda。它将所有环境变量的散列作为参数传递给它。 (我将参数命名为 env
但名称可以是任何名称。)
lambda 从中读取客户端用来向站点发出请求的域名:env['SERVER_NAME']
。它会检查域是否正确。
- 它 returns
true
如果域不正确。在这种情况下,并且仅在这种情况下,gem 会将 URL 和 return 状态 301 重写给客户端。
- 它 returns
false
如果域是正确的。在这种情况下,不会采取任何操作,请求将 "fall through" 发送到应用程序(发送到其他中间件)。
example.com/products/12 => www.example.com/products/12
为了解决 Heroku 的这个问题,我必须正确设置我的域名托管服务商的设置。您要查找的内容称为 Forwarding。接下来,您要启用 'keep relative path' 选项。
所以,寻找:
- 重定向类型:301 永久
- 转发设置:仅转发
- 保持相对路径
这应该都可以在您的域注册商级别上使用。
我发现我在使用这个 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
您也可以使用 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
。
我有一个 Rails 2.3.2 应用程序托管在 Heroku 上。
裸域和www子域是几年前添加的,都对搜索引擎有一定的权限。
然而,问题是搜索引擎将内容视为重复内容,因此我想进行从裸域到 www 子域的 301 重定向。
我问过 Zerigo DNS 是否可以通过他们的平台来做这件事,他们说不行,我必须在 Heroku 那边做。 Heroku 不允许访问服务器,所以我需要一些 Rack 中间件来执行此操作。
根据这个答案here gem rack-rewrite 可以做到这一点。
然而我真的是一个菜鸟,我不知道如何设置它,以便任何来自裸域的 url 都将被 301 重定向到 www 子域。
示例:
例子。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”):
关于如何让这个设置工作的任何想法?
根据 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
方法的参数是:
/.*/
是匹配任何请求路径和 url 参数的正则表达式,因此,站点上的任何页面。'http://www.example.com$&'
是页面的新完整 URL(重定向后)。它具有正确的域名和附加的原始请求路径——$&
符号表示 "whatever is matched by the first parameter",它匹配所有内容。if: ->(env){env['SERVER_NAME'] != 'www.example.com'}
是此重写规则的选项散列。在这种情况下,它只有一个名为if
的选项。该选项的值是一个 lambda 函数:->(env){env['SERVER_NAME'] != 'www.example.com'}
。
gem 将为每个请求调用此 lambda。它将所有环境变量的散列作为参数传递给它。 (我将参数命名为 env
但名称可以是任何名称。)
lambda 从中读取客户端用来向站点发出请求的域名:env['SERVER_NAME']
。它会检查域是否正确。
- 它 returns
true
如果域不正确。在这种情况下,并且仅在这种情况下,gem 会将 URL 和 return 状态 301 重写给客户端。 - 它 returns
false
如果域是正确的。在这种情况下,不会采取任何操作,请求将 "fall through" 发送到应用程序(发送到其他中间件)。
example.com/products/12 => www.example.com/products/12
为了解决 Heroku 的这个问题,我必须正确设置我的域名托管服务商的设置。您要查找的内容称为 Forwarding。接下来,您要启用 'keep relative path' 选项。
所以,寻找:
- 重定向类型:301 永久
- 转发设置:仅转发
- 保持相对路径
这应该都可以在您的域注册商级别上使用。
我发现我在使用这个 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
您也可以使用 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
。