簡體   English   中英

Rails手動從裸域重定向

[英]Rails manually redirecting from naked domain

因此,由於我的托管服務提供商(Heroku)的限制,目前我手動指向裸域。 一切正常。 問題是如果用戶訪問mydomain.com/route,重定向將返回到沒有/ route的www.mydomain.com。 我將如何重新添加路線,但仍然重定向到www。

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

編輯

我從我的ApplicationController中刪除了上面的代碼,並選擇使用hurikhan77建議的折射gem ,這解決了我的問題。

這是我使用的refraction_rules.rb。

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

我建議使用折射寶石: http//rubygems.org/gems/refraction

理想情況下,您可以在Web服務器配置中設置類似的規則。 請求會變得更快,因為它們甚至不會到達rails堆棧。 您也無需向應用添加任何代碼。

但是,如果您在某些受限制的環境中運行,例如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 !@env["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並將記錄添加到hosts文件(通常是/ etc / hosts)以將yoursubdomain.localhost視為127.0.0.1

不確定這是否是最佳解決方案,但您可以正確使用request.referrer並在.com之后取出任何內容並將其附加到APP_DOMAIN

或者我猜你可以在第一次之前取出所有東西。 request.env['HTTP_HOST']添加替換為http://www. 假設您不打算使用子域。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM