How to redirect without www using Rails 3 / Rack?

2019-01-21 05:46发布

I understand there are a lot of questions that answer this. I'm familiar with .htaccess and nginx.conf methods, but I do not have access to such traditional configuration methods on heroku.

Simone Carletti gave this answer that leverages Rails 2.x Metals, but I'm using Rails 3 and this isn't compatible. Redirect non-www requests to www urls in Rails

Please note:

I'm not looking for a simple before_filter in my ApplicationController. I'd like to accomplish a rewrite similar to Simone's. I believe this is job for the webserver or middleware like Rack at the very least, so I'd like to leave this bit out of the actual app code.

Goal

redirect                to                  status
----------------------------------------------------
www.foo.com             foo.com             301
www.foo.com/whatever    foo.com/whatever    301

Only hosts matching /^www\./ should be redirect. All other requests should be ignored.

9条回答
聊天终结者
2楼-- · 2019-01-21 06:02

If you want to redirect from the top-level domain (TLD) to the www subdomain, use this code:

constraints :subdomain => '' do
  match '(*any)' => redirect { |p, req| req.url.sub('//', '//www.') }
end

Note: This code the use of sub, not gsub, because sub replaces the first occurrence of the double-slashes where gsub would replace all double-slashes.

查看更多
3楼-- · 2019-01-21 06:06

Take a look at this middleware, it should do precisely what you want:

http://github.com/iSabanin/www_ditcher

Let me know if that worked for you.

查看更多
Viruses.
4楼-- · 2019-01-21 06:07

in Rails 4 removing www. from any URL whilst maintaining the pathname can be achieved simply by using:

# config/routes.rb

constraints subdomain: 'www' do
  get ':any', to: redirect(subdomain: nil, path: '/%{any}'), any: /.*/
end

In contrast, adding www. to the beginning of any URL that doesn't already have it can be achieved by:

# config/routes.rb

constraints subdomain: false do
  get ':any', to: redirect(subdomain: 'www', path: '/%{any}'), any: /.*/
end
查看更多
对你真心纯属浪费
5楼-- · 2019-01-21 06:10

There's a better approach if you're using Rails 3. Just take advantage of the routing awesomeness.

Foo::Application.routes.draw do
  constraints(:host => /^example.com/) do
    root :to => redirect("http://www.example.com")
    match '/*path', :to => redirect {|params| "http://www.example.com/#{params[:path]}"}
  end
end
查看更多
三岁会撩人
6楼-- · 2019-01-21 06:10

Nothing wrong with the approaches above, but there are also a couple of gems that provide Rack middleware to do this.

I like the way that they keep this behaviour separate from the app itself, but it's not a particularly strong argument either way. I also use middleware to do this when working with Sinatra, so prefer to use a technique that I can use on apps built from Rails and/or Sinatra (I often run Nesta embedded in Rails).

Anyway, here they are:

The first is simpler (and the one I've been using) while the second offers a couple more features (that I'm yet to need, but appreciate).

查看更多
Summer. ? 凉城
7楼-- · 2019-01-21 06:14

A one-line version of Duke's solution. Just add to the top of routes.rb

match '(*any)' => redirect { |p, req| req.url.sub('www.', '') }, :constraints => { :host => /^www\./ }
查看更多
登录 后发表回答