2012-11-23 31 views
4

因此,目前我手動從裸域導致由於與我的託管服務提供商(Heroku)的限制。一切正常。問題是,如果用戶訪問mydomain.com/route,重定向將發送回www.mydomain.com而不使用/ route。我將如何去重新添加路線,但仍然重定向到www。 ?Rails手動從裸域重定向

class ApplicationController < ActionController::Base 
protect_from_forgery 
before_filter :ensure_domain 
APP_DOMAIN = 'www.domain.com' 
def index 
end 
def ensure_domain 
    if Rails.env.production? 
     if request.env['HTTP_HOST'] != APP_DOMAIN 
      redirect_to "http://#{APP_DOMAIN}", :status => 301 
     end 
    end 
end 
end 

EDIT

我刪除我上面的​​代碼從我的ApplicationController,並選擇了使用refraction gem通過hurikhan77的建議,這解決了問題。

這是我使用的refraction_rules.rb。

Refraction.configure do |req| 
    if req.host == "domain.com" 
    req.permanent! :host => "www.domain.com" 
    end 
end 

回答

0

不知道這是最好的解決辦法,但你可以在正則表達式和request.referrer後.COM拉出任何東西,追加到APP_DOMAIN

或者我想你可以只取出之前的所有第一。在request.env['HTTP_HOST']中假設您不打算使用子域名,請使用http://www.添加替換項。

2

理想情況下,你將建立像在Web服務器的配置規則。請求會變得更快,因爲他們甚至不會到達鐵路棧。不需要添加任何代碼到您的應用程序。但是,如果你在一些受限制的環境中運行,比如heroku,我建議添加一個機架中間件。 (只是爲了指導方針,也不能保證,如果這個特殊的代碼是免費的bug)

class Redirector 
    SUBDOMAIN = 'www' 

    def initialize(app) 
    @app = app 
    end 

    def call(env) 
    @env = env 
    if redirect? 
     redirect 
    else 
     @app.call(env) 
    end 
    end 

private 

    def redirect? 
    # do some regex to figure out if you want to redirect 
    end 

    def redirect 
    headers = { 
     "location" => redirect_url 
    } 
    [302, headers, ["You are being redirected..."]] # 302 for temp, 301 for permanent 
    end 

    def redirect_url 
    scheme = @env["rack.url_scheme"] 

    if @env['SERVER_PORT'] == '80' 
     port = '' 
    else 
     port = ":#{@env['SERVER_PORT']}" 
    end 

    path = @env["PATH_INFO"] 

    query_string = "" 
    if [email protected]["QUERY_STRING"].empty? 
     query_string = "?" + @env["QUERY_STRING"] 
    end 

    host = "://#{SUBDOMAIN}." + domain # this is where we add the subdomain 
    "#{scheme}#{host}#{path}#{query_string}" 
    end 

    def domain 
    # extract domain from request or get it from an environment variable etc. 
    end 
end 

您還可以測試在整個事件中隔離

describe Redirector do 
     include Rack::Test::Methods 

     def default_app 
     lambda { |env| 
      headers = {'Content-Type' => "text/html"} 
      headers['Set-Cookie'] = "id=1; path=/\ntoken=abc; path=/; secure; HttpOnly" 
      [200, headers, ["default body"]] 
     } 
     end 

     def app() 
     @app ||= Rack::Lint.new(Redirector.new(default_app)) 
     end 

     it "redirects unsupported subdomains" do 
     get "http://example.com/zomg?a=1" 
     last_response.status.should eq 301 
     last_response.header['location'].should eq "http://www.example.com/zomg?a=1" 
     end 
    # and so on 
end 

然後你就可以將其添加到生產(或任何首選環境)只

# production.rb 
# ... 
config.middleware.insert_after 'ActionDispatch::Static', 'Redirector' 

如果你想在開發測試它,添加相同的行development.rb和記錄添加到您的主機文件(通常是/ etc/hosts文件)來治療yoursubdomain.localhos t as 127.0.0.1