Versión móvil y clásica de un web con mod_rewrite
Cada vez es más habitual que las páginas web dispongan de versiones específicas para poder ser vistas en dispositivos pequeños como los smartphones. Como no podía ser de otra forma, en Kukers.com, nuestra red social de cocina, también ofrecemos esta posibilidad desde hace un tiempo.
El objetivo es que si un usuario entra con un dispositivo móvil se le redirija al dominio m.kukers.com
, en el que está la versión móvil. Además queremos hacer que este dominio apunte a la misma carpeta que www.kukers.com
para aprovechar los recursos existentes (imágenes, css, js) y que el usuario pueda elegir navegar por la versión clásica aunque le hayamos redirigido a la móvil.
Para complicar un poco el asunto, hay que tener en cuenta que en Kukers.com todas las URL que se utilizan en el web son virtuales. Cuando se solicita por ejemplo la página http://www.kukers.com/recetas
, en el servidor no existe una carpeta con este nombre. Lo que se hace es redirigir esta petición utilizando mod_rewrite a http://www.kukers.com/index.php/recetas
, de tal forma que es el archivo index.php
el que se encarga de procesar la petición procesando la cadena de texto que viene a continuación. Este programa se encarga de procesar la petición con el controlador adecuado, por ejemplo con el encargado de obtener el listado de recetas.
Simplificando otras cuestiones, para realizar esta tarea utilizamos un .htaccess con el siguiente contenido. Lo que hace es redirigir todas las peticiones que no correspondan a archivos y carpetas existentes a index.php
.
RewriteEngine on RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php/$1 [L] |
Para ampliar este funcionamiento lo primero que necesitamos es detectar que el usuario está accediendo con un dispositivo móvil. Las siguientes reglas comprueban una buena cantidad de navegadores existentes en dispositivos móviles y si el usado está entre ellos redirige a m.kukers.com
. Además tiene en cuenta que no estemos ya en la versión móvil, para evitar un bucle infinito. Estas comprobaciones puedes obtenerlas en la página detectmobilebrowser.com.
# varias comprobaciones de navegador utilizado RewriteCond %{HTTP_USER_AGENT} android|avantgo|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge\ |maemo|midp|mmp|opera\ m(ob|in)i|palm(\ os)?|phone|p(ixi|re)\/|plucker|pocket|psp|symbian|treo|up\.(browser|link)|vodafone|wap|windows\ (ce|phone)|xda|xiino [NC,OR] RewriteCond %{HTTP_USER_AGENT} ^(1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a\ wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r\ |s\ )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1\ u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp(\ i|ip)|hs\-c|ht(c(\-|\ |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac(\ |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt(\ |\/)|klon|kpt\ |kwc\-|kyo(c|k)|le(no|xi)|lg(\ g|\/(k|l|u)|50|54|e\-|e\/|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-|\ |o|v)|zz)|mt(50|p1|v\ )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v\ )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-|\ )|webc|whit|wi(g\ |nc|nw)|wmlb|wonu|x700|xda(\-|2|g)|yas\-|your|zeto|zte\-) [NC] # comprobamos que no estemos ya en la versión móvil RewriteCond %{HTTP_HOST} !^m\. # redirigimos a la versión móvil RewriteRule ^ http://m.kukers.com [R=302,L] |
Queremos también permitir que el usuario pueda pasar de la versión móvil a la clásica. Esto complica un poco la cosa ya que no basta con redirigir a www.kukers.com
, se volvería a detectar que estamos con un dispositivo móvil y acabaríamos de nuevo en m.kukers.com
. Para resolver esta situación lo que se hace para pasar a la versión clásica es utilizar una url con un parámetro extra, en nuestro caso www.kukers.com?m=0
, que indica que no queremos que se nos redirija de nuevo a la versión móvil.
Para que no se produzca la redirección es necesario ampliar las reglas de detección del dispositivo móvil para que compruebe este parámetro. Como una vez que estemos en la versión clásica los enlaces no tendrán este parámetro, lo que se hace es crear una cookie en la que se indica que queremos seguir navegando por la versión clásica.
# se comprueba si se está utilizando el parámetro m para no redirigir a la versión móvil RewriteCond %{QUERY_STRING} (^|&)m=0(&|$) # si es así se crea la cookie RewriteRule ^ - [CO=mredir:0:www.kukers.com] # varias comprobaciones de navegador utilizado RewriteCond %{HTTP_USER_AGENT} android|avantgo|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge\ |maemo|midp|mmp|opera\ m(ob|in)i|palm(\ os)?|phone|p(ixi|re)\/|plucker|pocket|psp|symbian|treo|up\.(browser|link)|vodafone|wap|windows\ (ce|phone)|xda|xiino [NC,OR] RewriteCond %{HTTP_USER_AGENT} ^(1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a\ wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r\ |s\ )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1\ u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp(\ i|ip)|hs\-c|ht(c(\-|\ |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac(\ |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt(\ |\/)|klon|kpt\ |kwc\-|kyo(c|k)|le(no|xi)|lg(\ g|\/(k|l|u)|50|54|e\-|e\/|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-|\ |o|v)|zz)|mt(50|p1|v\ )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v\ )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-|\ )|webc|whit|wi(g\ |nc|nw)|wmlb|wonu|x700|xda(\-|2|g)|yas\-|your|zeto|zte\-) [NC] # comprobamos que no estemos ya en la versión móvil RewriteCond %{HTTP_HOST} !^m\. # no se puede leer y escribir una cookie en la misma petición, hay que duplicar la condición RewriteCond %{QUERY_STRING} !(^|&)m=0(&|$) # se comprueba que no se haya configurado antes la cookie RewriteCond %{HTTP_COOKIE} !^.*mredir=0.*$ [NC] # redirigimos a la versión móvil RewriteRule ^ http://m.kukers.com [R=302,L] |
De esta forma todas las peticiones que lleguen a www.kukers.com
se redirigirán a la versión móvil cuando accedamos con un dispositivo móvil. En el caso de que únicamente queramos redirigir determinadas páginas, por ejemplo por no haber versión móvil de todas las existentes, sería necesario añadir condiciones complementarias antes del RewriteRule
. Por ejemplo podríamos redirigir únicamente la portada y el detalle de las recetas.
..... # solo se hace redirección de la portada y de los detalles de receta RewriteCond %{REQUEST_URI} ^(/|/receta/[0-9]+/[A-Za-z0-9\-]+)$ # redirigimos a la versión móvil RewriteRule ^ http://m.kukers.com [R=302,L] |
Con esto ya tenemos la versión clásica y la móvil montada y permitimos pasar de una a otra, sin embargo al final todas las peticiones acaban en el mismo programa y con la misma información (/index.php/recetas
). Para servir contenido diferente en el caso de la versión móvil lo que hemos hecho ha sido reescribir la petición cuando se ha realizado desde m.kukers.com
, para que quede de la forma /index.php/m/recetas
. Así el programa index.php
, procesará la petición con el controlador encargado de generar el listado de recetas de la versión móvil.
Para ello se añaden unas reglas más a las originales, de forma que si estamos navegando por la versión móvil se añada el /m
al principio de cada petición.
# Esta regla redirige la raíz a la home mobile RewriteCond %{REQUEST_URI} / RewriteCond %{HTTP_HOST} ^m\. RewriteRule ^$ index.php/m [L] # Esta regla redirige los contenidos de la versión móvil RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{HTTP_HOST} ^m\. RewriteRule ^(.*)$ index.php/m/$1 [L] # Para la versión clásica RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php/$1 [L] |
Y con todo esto junto ya tenemos montada la versión móvil montada en el subdominio m.kukers.com
. Hay más alternativas para hacer esto mismo pero creo que esta es la que más se ajusta a nuestras necesidades.
RewriteEngine on RewriteBase / # se comprueba si se está utilizando el parámetro m para no redirigir a la versión móvil RewriteCond %{QUERY_STRING} (^|&)m=0(&|$) # si es así se crea la cookie RewriteRule ^ - [CO=mredir:0:www.kukers.com] # varias comprobaciones de navegador utilizado RewriteCond %{HTTP_USER_AGENT} android|avantgo|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge\ |maemo|midp|mmp|opera\ m(ob|in)i|palm(\ os)?|phone|p(ixi|re)\/|plucker|pocket|psp|symbian|treo|up\.(browser|link)|vodafone|wap|windows\ (ce|phone)|xda|xiino [NC,OR] RewriteCond %{HTTP_USER_AGENT} ^(1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a\ wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r\ |s\ )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1\ u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp(\ i|ip)|hs\-c|ht(c(\-|\ |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac(\ |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt(\ |\/)|klon|kpt\ |kwc\-|kyo(c|k)|le(no|xi)|lg(\ g|\/(k|l|u)|50|54|e\-|e\/|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-|\ |o|v)|zz)|mt(50|p1|v\ )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v\ )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-|\ )|webc|whit|wi(g\ |nc|nw)|wmlb|wonu|x700|xda(\-|2|g)|yas\-|your|zeto|zte\-) [NC] # comprobamos que no estemos ya en la versión móvil RewriteCond %{HTTP_HOST} !^m\. # no se puede leer y escribir una cookie en la misma petición, hay que duplicar la condición RewriteCond %{QUERY_STRING} !(^|&)m=0(&|$) # se comprueba que no se haya configurado antes la cookie RewriteCond %{HTTP_COOKIE} !^.*mredir=0.*$ [NC] # solo se hace redirección de la portada y de los detalles de receta RewriteCond %{REQUEST_URI} ^(/|/receta/[0-9]+/[A-Za-z0-9\-]+)$ # redirigimos a la versión móvil RewriteRule ^ http://m.kukers.com [R=302,L] # Esta regla redirige la raíz a la home mobile RewriteCond %{REQUEST_URI} / RewriteCond %{HTTP_HOST} ^m\. RewriteRule ^$ index.php/m [L] # Esta regla redirige los contenidos de la versión móvil RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{HTTP_HOST} ^m\. RewriteRule ^(.*)$ index.php/m/$1 [L] # Para la versión clásica RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php/$1 [L] |
Con este código se me vuelve a redireccionar a la versión movil…
¿hago algo mal?
# se comprueba si se está utilizando el parámetro m para no redirigir a la versión móvil
RewriteCond %{QUERY_STRING} (^|&)m=0(&|$)
# si es así se crea la cookie
RewriteRule ^ – [CO=mredir:0:www.vuelosmadridbarcelona.net]
# varias comprobaciones de navegador utilizado
RewriteCond %{HTTP_USER_AGENT} android|avantgo|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge\ |maemo|midp|mmp|opera\ m(ob|in)i|palm(\ os)?|phone|p(ixi|re)\/|plucker|pocket|psp|symbian|treo|up\.(browser|link)|vodafone|wap|windows\ (ce|phone)|xda|xiino [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^(1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a\ wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r\ |s\ )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1\ u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp(\ i|ip)|hs\-c|ht(c(\-|\ |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac(\ |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt(\ |\/)|klon|kpt\ |kwc\-|kyo(c|k)|le(no|xi)|lg(\ g|\/(k|l|u)|50|54|e\-|e\/|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-|\ |o|v)|zz)|mt(50|p1|v\ )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v\ )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-|\ )|webc|whit|wi(g\ |nc|nw)|wmlb|wonu|x700|xda(\-|2|g)|yas\-|your|zeto|zte\-) [NC]
# comprobamos que no estemos ya en la versión móvil
RewriteCond %{HTTP_HOST} !^m\.
# no se puede leer y escribir una cookie en la misma petición, hay que duplicar la condición
RewriteCond %{QUERY_STRING} !(^|&)m=0(&|$)
# se comprueba que no se haya configurado antes la cookie
RewriteCond %{HTTP_COOKIE} !^.*mredir=0.*$ [NC]
# redirigimos a la versión móvil
RewriteRule ^ http://m.vuelosmadridbarcelona.net [R=301,L]