ruby on rails - ¿Cómo redirigir sin www usando Rails 3/Rack?
ruby-on-rails redirect (9)
Entiendo que hay muchas preguntas que responden esto. Estoy familiarizado con los métodos .htaccess
y nginx.conf
, pero no tengo acceso a esos métodos de configuración tradicionales en heroku.
Simone Carletti dio esta respuesta que aprovecha Rails 2.x Metals, pero estoy usando Rails 3 y esto no es compatible. Redirija las solicitudes que no son www a www urls en Rails
Tenga en cuenta:
No estoy buscando un before_filter
simple en mi ApplicationController. Me gustaría lograr una reescritura similar a la de Simone. Creo que este es un trabajo para el servidor web o middleware, como Rack, por lo menos, así que me gustaría dejar este bit fuera del código de la aplicación real.
Gol
redirect to status
----------------------------------------------------
www.foo.com foo.com 301
www.foo.com/whatever foo.com/whatever 301
Solo los hosts que coincidan con /^www/./
deberían redirigirse. Todas las demás solicitudes deben ser ignoradas.
Eche un vistazo a este middleware, debería hacer exactamente lo que quiere:
http://github.com/iSabanin/www_ditcher
Avíseme si eso funcionó para usted.
En Rails 3
#config/routes.rb
Example::Application.routes.draw do
constraints(:host => "www.example.net") do
match "(*x)" => redirect { |params, request|
URI.parse(request.url).tap { |x| x.host = "example.net" }.to_s
}
end
# ....
# .. more routes ..
# ....
end
Hay un mejor enfoque si estás utilizando Rails 3. Solo aprovecha el asombroso enrutamiento.
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
No hay nada malo con los enfoques anteriores, pero también hay un par de gemas que proporcionan middleware Rack para hacer esto.
Me gusta la forma en que mantienen este comportamiento separado de la aplicación en sí, pero no es un argumento particularmente fuerte de ninguna manera. También uso el middleware para hacer esto cuando trabajo con Sinatra, así que prefiero usar una técnica que pueda usar en aplicaciones creadas desde Rails y / o Sinatra (a menudo ejecuto Nesta incrustado en Rails).
De todos modos, aquí están:
El primero es más simple (y el que he estado usando), mientras que el segundo ofrece un par de características más (que aún necesito, pero aprecio).
Para Rails 4, las soluciones anteriores deben adjuntarse a la construcción Verb, por ejemplo, a via: [:get, :post]
. La solución de Duke se convierte en:
constraints(:host => /^www/./) do
match "(*x)" => redirect { |params, request|
URI.parse(request.url).tap {|url| url.host.sub!(''www.'', '''') }.to_s
}, via: [:get, :post]
end
Realmente me gusta usar el Rails Router para tales cosas. Las respuestas anteriores fueron buenas, pero quería algo de propósito general que pueda usar para cualquier url que comience con "www".
Creo que esta es una buena solución:
constraints(:host => /^www/./) do
match "(*x)" => redirect { |params, request|
URI.parse(request.url).tap {|url| url.host.sub!(''www.'', '''') }.to_s
}
end
Si desea redirigir desde el dominio de nivel superior (TLD) al subdominio www, use este código:
constraints :subdomain => '''' do
match ''(*any)'' => redirect { |p, req| req.url.sub(''//'', ''//www.'') }
end
Nota: Este código usa sub, no gsub, porque sub reemplaza la primera ocurrencia de barras dobles donde gsub reemplazaría todas las barras diagonales.
Una versión de una línea de la solución de Duke. Solo agrega a la parte superior de routes.rb
match ''(*any)'' => redirect { |p, req| req.url.sub(''www.'', '''') }, :constraints => { :host => /^www/./ }
en Rails 4 eliminando www. desde cualquier URL mientras se mantiene el nombre de ruta se puede lograr simplemente usando:
# config/routes.rb
constraints subdomain: ''www'' do
get '':any'', to: redirect(subdomain: nil, path: ''/%{any}''), any: /.*/
end
Por el contrario, agregando www. al comienzo de cualquier URL que aún no lo tenga se puede lograr:
# config/routes.rb
constraints subdomain: false do
get '':any'', to: redirect(subdomain: ''www'', path: ''/%{any}''), any: /.*/
end