5

そのため、現在、ホスティング プロバイダー (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 の提案に従って屈折宝石を使用することを選択しました。これで問題が解決しました。

これが私が使用したrefraction_rules.rbです。

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

3 に答える 3

5

これには屈折gemを使用することをお勧めします:http://rubygems.org/gems/refraction

于 2012-11-24T00:42:01.387 に答える
2

理想的には、Web サーバー構成でそのようなルールを設定します。リクエストは Rails スタックにさえ到達しないため、より高速になります。アプリにコードを追加する必要もありません。

ただし、heroku などの制限された環境で実行している場合は、ラック ミドルウェアを追加することをお勧めします。(ガイドラインとして、この特定のコードにバグがないかどうかは保証できません)

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 として扱います。

于 2012-11-24T13:10:39.280 に答える