2009-11-10 10 views
8

Problème simple mais n'arrive pas à trouver une réponse en faisant un peu de googling rapide. Quel est le moyen de Rails de ce faire 301 directe (http://x.com/abc>http://www.x.com/abc). Un before_filter?Redirige les requêtes non-www vers www urls dans Rails

+1

pourquoi voulez-vous www là-bas? qu'est-ce que ça te donne? Caisse http://no-www.org/index.php –

+0

@James - Une utilisation courante de www. est ainsi que vous n'avez pas besoin d'un second domaine "sans cookie" pour servir le contenu statique. – MiffTheFox

Répondre

17

Idéalement, vous le feriez dans votre configuration de serveur Web (Apache, nginx, etc.) afin que la requête ne touche même pas Rails.

Ajouter la before_filter suivante à votre ApplicationController:

class ApplicationController < ActionController::Base 
    before_filter :add_www_subdomain 

    private 
    def add_www_subdomain 
    unless /^www/.match(request.host) 
     redirect_to("#{request.protocol}x.com#{request.request_uri}", 
        :status => 301) 
    end 
    end 
end 

Si vous ne voulez faire la redirection en utilisant Apache, vous pouvez utiliser ceci:

RewriteEngine on 
RewriteCond %{HTTP_HOST} !^www\.x\.com [NC] 
RewriteRule ^(.*)$ http://www.x.com/$1 [R=301,L] 
+0

Grande réponse John. Si vous utilisez Rails> = 2.3, je suggère d'utiliser un Metal à la place. :) –

+0

Merci! Oui, bon point sur le Metal. –

+0

De rien! –

7

Alors que la réponse de John est parfaitement bien, si vous utilisez Rails> = 2.3 Je suggère de créer un nouveau métal. Rails Metals sont plus efficaces et offrent de meilleures performances.

$ ruby script/generate metal NotWwwToWww 

Puis ouvrez le fichier et collez le code suivant.

# Allow the metal piece to run in isolation 
require(File.dirname(__FILE__) + "/../../config/environment") unless defined?(Rails) 

class NotWwwToWww 
    def self.call(env) 
    if env["HTTP_HOST"] != 'www.example.org' 
     [301, {"Content-Type" => "text/html", "Location" => "www.#{env["HTTP_HOST"]}"}, ["Redirecting..."]] 
    else 
     [404, {"Content-Type" => "text/html"}, ["Not Found"]] 
    end 
    end 
end 

Bien sûr, vous pouvez personnaliser davantage le métal.

Si vous souhaitez utiliser Apache, here's a few configurations.

+0

Simone, un conseil sur comment utiliser ceci avec Rails 3? J'aimerais rediriger 'www.foo.com' vers' foo.com'. –

+0

Avec Rails 3, c'est encore plus simple: utilisez la méthode de routage 'redirect'. Pas besoin d'utiliser un métal. –

3

Il y a une meilleure Rails 3 voies - mettre ceci dans votre fichier routes.rb:

constraints(:host => "example.com") do 
    # Won't match root path without brackets around "*x". (using Rails 3.0.3) 
    match "(*x)" => redirect { |params, request| 
     URI.parse(request.url).tap { |x| x.host = "www.example.com" }.to_s 
    } 
    end 

Mise à jour

Voici comment le rendre domaine agnostique:

constraints(subdomain: '') do 
    match "(*x)" => redirect do |params, request| 
     URI.parse(request.url).tap { |x| x.host = "www.#{x.host}" }.to_s 
    end 
    end 
+0

Le lien est rompu. – iamnotmaynard

7

Pour rails 4, utilisez-le -

before_filter :add_www_subdomain 

    private 
    def add_www_subdomain 
    unless /^www/.match(request.host) 
     redirect_to("#{request.protocol}www.#{request.host_with_port}",status: 301) 
    end 
    end 
+1

sauvé ma vie merci – Kathan

+2

cela rejette le chemin de l'URL –

+1

oui, il redirige vers la page d'accueil, donc pas très utile :( – Gediminas

0

Vous pouvez le code ci-dessous -

location/{ 
    if ($http_host ~* "^example.com"){ 
    rewrite ^(.*)$ http://www.example.com$1 redirect; 
    } 
} 
Questions connexes