htaccess

htaccess (Acceso de Hiper-Texto) es un archivo de texto que Apache usa para crear reglas sobre los directorios y archivos. Tiene múltiples funciones y en lo personal me parece una herramienta sumamente interesante pero complicada de usar.

El servidor Apache tiene un módulo llamado mod_rewrite que permite redirigir y modificar la URL solicitada basada en reglas expresada en expresiones regulares PCRE. Coloque estos comandos en un archivo texto plano de nombre .htaccess en la raíz del sitio web.

Proporciona una forma flexible y poderosa de manipular URL usando un número ilimitado de reglas. Cada regla puede tener un número ilimitado de condiciones de regla adjuntas, para permitirle reescribir URL en función de variables de servidor, entorno, encabezados HTTP o marcas de tiempo.

1. Directivas

De forma general se puede decir que las directivas en el .htaccess se componen de tres partes: el tipo de directiva (Options, RewriteCond), los parámetros de la directiva y por último el final de cada línea en que se pueden agregar modificaciones adicionales.

Directivas
DirectivaDescripción
DirectoryIndexCambiar la página por defecto.
RedirectRedireccionar el tráfico web.
?Limitar los tipos de archivos que pueden subirse a un directorio.
RewriteCondDefine una condición bajo la cual tendrá lugar la reescritura.
RewriteRuleDefine reglas para el motor de reescritura.
RewriteOptionsEstablece algunas opciones especiales para el motor de reescritura.
RewriteBaseEstablece la URL base para reescrituras por directorio.
RewriteEngineHabilita o deshabilita el motor de reescritura en tiempo de ejecución. on|off.
RewriteMapDefine una función de mapeo para la búsqueda de claves.
.

1.1 Cambiar la página por defecto

Se puede usar esta directiva para cambiar la página por defecto (el orden es importante).

DirectoryIndex inicio.html index.htm index.html index.php

1.2 Redireccionar el tráfico web

Redirect antiguo nuevo
Redirect /antiguo.php http://sitio.com/nuevo.php
Redirect www.sitio.com https://sitio.com
redirect 301 / https://domain.com/
redirect 301 /archivo.html http://www.domain.com/denegado.php

1.3 Redirección permanente

Redirect permanent antiguo nuevo
Redirect permanent / http://www.domain.com/

1.4 Redireccion condicional

Para redirigir en función de lo que se ingrese.

RewriteEngine on
RewriteCond patrón condición [modificador]
RewriteRule patrón sustitucion [modificador]
Patrón:
Puede ser una variable de servidor %{VARIABLE}, una expresion regular que coincide con la URL (despues del nombre del HOST pero antes de ? luego del cual van los parámetros de consulta).
Condición:
Expresion regular, cadena de comparacion o prueba de archivo/carpeta. Luego de http://hostname

Sustitucion:
URL absoluta, ruta hacia archivo, modificacion de parte de la URL, - (no hacer nada)

Modificador:
[NC] ignore case, [OR] or logico, [NV no vary, etc]

1.4.1 RewriteCond

RewriteCond %{HTTP_USER_AGENT} (iPhone|Blackberry|Android) [NC]

1.4.2 RewriteRule

Esta es el verdadero caballo de batalla de la reescritura. La directiva puede ocurrir más de una vez y cada instancia define una sola regla de reescritura. El orden en que se definen estas reglas es importante porque este sera el orden en que se aplicarán en tiempo de ejecución.

RewriteRule patrón sustitucion [modificador]

Primero se comparar el patrón con la parte de la URL despues de nombre del HOST %{HTTP_HOST} y puerto %{SERVER_PORT} pero antes de la cadena de consulta. Ej: app1/index.php

RewriteRule ^/games  /usr/local/games/web                      //Crea un alias
RewriteRule ^/games$  http://sitio.com/juegos.php [R]          //Ruta absoluta
RewriteRule ^/games/(.*)$  http://sitio.com/$1/index.php [R]   //$1 se reemplaza con primer ()
RewriteRule ^(.*)$ http://www.nueva.com/$1 [R=301,L]

Si hay más de una expresión entre paréntesis, estarán disponibles en el orden en las variables $1, $2, $3, y así sucesivamente.

301 (Moved Permanently) esta y todas las peticiones futuras deberían ser dirigidas a la URL dada.

1.5 Activar compresion

Se puede habilitar la compresión de datos inherente de PHP para ahorrar ancho de banda.

<ifmodule mod_php4.c>
   php_value zlib.output_compression 16386
</ifmodule>

1.6 Capturar errores

Por defecto, el servidor Apache muestra una página de error 404 (File Not Found), cuando nuestros visitantes acceden a una página que en el momento no existe. Sin embargo, la página por defecto es poco amigable y no deja una buena impresión. Por lo que, podríamos crear una página especial, a la cual redirigir al cliente cada vez que se produce el error 404.

ErrorDocument error pagina
Errores del cliente
CódigoDescripción
400Bad RequestEl servidor no procesará la solicitud, porque no puede, o no debe, debido a algo que es percibido como un error del cliente (ej: solicitud malformada, sintaxis errónea, etc). La solicitud contiene sintaxis errónea y no debería repetirse.
401UnauthorizedSimilar al 403 (Forbidden), pero específicamente para su uso cuando la autentificación es posible pero ha fallado o aún no ha sido provista.
403ForbiddenLa solicitud fue legal, pero el servidor rehúsa responderla dado que el cliente no tiene los privilegios para realizarla. En contraste a una respuesta 401 No autorizado, autenticarse previamente no va a cambiar la respuesta.
404Not FoundRecurso no encontrado. Se usa cuando el servidor web no encuentra la página o recurso solicitado.
429Too Many RequestsHay muchas conexiones desde esta dirección de internet.
ErrorDocument 404 /tiburon.php

1.7 Prevenir navegación de carpetas

Cuando un directorio no tiene la página de index, cualquier visitante puede observar los archivos contenidos en el directorio y navegar a través de ellos.

Options All -Indexes

1.8 Forzar uso de SSL

Para forzar la conexion SSL en todo el sitio con ModRewrite.

RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [R,L]

Si queremos forzar SSL y quitar añadir el www:

RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} !^www\..+$ [NC]
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

2. Parámetros

Los parámetros son expresiones regulares o patrones de cadenas de textos que se definen usando símbolos como el ^ para indicar el inicio, el $ para señalar el final, ? para un carácter opcional (un comodin), el * para varios caracteres opcionales (comodines).

Expresiones regulares mas comunes
ParámetroDescripciónEjemplo
.Coincide con cualquier carácter. Comodín.c.t puede ser: cat, cot, cut, etc
+Repite el carácter anterior una o más veces.a+ puede ser: a, aa, aaa, etc
*Repite el carácter anterior cero o más veces.a* puede ser: mismo que a+ pero también vacío.
?Hace el carácter opcional. Solo uno.s?to puede ser: sato, seto, sito, etc
\Escapa el siguiente carácter.sitio\.com, nota que es específicamente el punto.
()Agrupa varios caracteres en una sola unidad y captura una coincidencia para usar en una referencia.(abc)+ igual que a+ pero se aplica al grupo.
[]Una clase de personaje: coincide con uno de los personajesc[aou]t puede ser: cat, cot o cut.
(.*)  cualquier expresión.
.*    indica cero o más caracteres arbitrarios.
/*    indica cero o más "/".
Expresiones de posición
ParámetroDescripción
^marca el inicio del argumento.
$marca el fin del argumento.
^$     indica un "empty string".
^.*$   indica cualquier cosa.
Expresiones regulares
ParámetroDescripción
#Se ignora la línea. Es un comentario.
[]+se usa para hacer combinaciones.
[^]excluye los carácteres dentro del paréntesis, de los resultados. Ejemplo [^xyz].
a{n}especifica el número exacto del carácter que le precede.
a{n,}especifica el número "o más" del carácter que le precede.
a{n,m}especifica un rango entre n y m. Ejemplo: x{4,7} = resulta 4,5,6 o 7 caracteres 'x'.
[a-z]solamente letras.
[a-z]{3}palabra de 3 caracteres.
[a-z]{1,10}palabra de entre 1 y 10 caracteres.
[0-9]solamente números.
[0-9]{4}número de 4 dígitos.
!Negar expresion. Es decir, se considerará que una cadena ha coincidido solo si no coincide con la expresión.
-instrucción “not to”.
|declara "or". Ejemplo (x|y) resulta "x" o "y".
\para leer caracteres especiales. Ejemplo “\.” indica literalmente un punto.
[^/.]+define, ningún número de carácter que sea "/" ni ".".
http://es literalmente “http://”.
^sitio.*define una cadena que comienza con la palabra "sitio" y continúa con cualquier número de caracteres.
^sitio\.com$define exactamente “sitio.com”.
-dprueba si la cadena es un directorio existente.
-fprueba si la cadena es un archivo existente.
-sprueba si el archivo en el string no tiene valor cero.

3. Modificadores

Los valores que aparecen entre corchetes al final de cada línea son modificadores o acciones. Por ejemplo, para RewriteCond se comun usar [NC] para indicar que en la directiva no debe distinguirse entre mayúsculas y minúsculas (no case), u [OR] para indicar que la expresión actual debe interpretase como una alternativa a la anterior. Por su parte, RewriteRule admite otros modificadores propios, como [F] para forzar un acceso denegado (forbidden), o [L] para indicar que es la última regla que debe aplicarse (last rule).

Modificadores
ParámetroDescripciónUso
[NC]No Case: para indicar que en la directiva no debe distinguirse entre mayúsculas y minúsculas.RewriteCond
[F]Forbidden: para forzar un acceso denegado. 403 Forbidden.RewriteRule
[L]Last rule: para indicar que es la última regla que debe aplicarse.RewriteRule
[N]Next: indica continuación hasta que las directivas sean logradas
[G]Gone: indica al servidor entregar "Gone" (ya no existe)
[P]Proxy: instruye al servidor para manejar los pedidos por mod_proxy
[C]Chain: Instruye al servidor para encadenar la regla actual con la regla previa.RewriteCond
[OR]Or: para indicar que la expresión actual debe interpretase como una alternativa a la anterior.RewriteCond
[R=n]Redirect: indica redirección. Ej: [R=301]RewriteRule
[PT]Pass Through: pasa el URL al Apache para seguir procesando.RewriteRule
[NE]No Escape: instruye al servidor para analizar las salidas sin escapar carácteres.
[NS]No Subrequest: para saltar directivas de sub-pedidos internos.
[QSA]Append Query String: para agregar un query string al final de la expresión (URL).RewriteRule
[S=n]Skip: para saltar las siguientes "n" reglas.
[E=variable:valor]Environmental Variable: para agregar un valor a una variable.
[T=MIME-type]Mime Type: declara mime-type al recurso.

4. Variables de servidor

El analizador de expresiones proporciona una serie de variables de la forma %{HTTP_HOST}. Tenga en cuenta que el valor de una variable puede depender de la fase del procesamiento de la solicitud en la que se evalúa. Por ejemplo, una expresión usada en una directiva <If > se evalúa antes de que se realice la autenticación. Por lo tanto, %{REMOTE_USER} no se establecerá en este caso.

Encabezados HTTP
VariableDescripción
HTTP_ACCEPT
HTTP_COOKIE
HTTP_FORWARDED
HTTP_HOSTRepresenta la parte del dominio del URL
HTTP_PROXY_CONNECTION
HTTP_REFERER
HTTP_USER_AGENT
Solicitud de conexión
VariableDescripción
AUTH_TYPE
CONN_REMOTE_ADDR
CONTEXT_PREFIX
CONTEXT_DOCUMENT_TOOT
IPV6on si la conexión usa IPv6 y off de lo contrario.
PATH_INFO
QUERY_STRINGEs la consulta, lo que esta luego de ? Ej: http://sitio.com/index.php?id=3 osea id=3
REMOTE_ADDRLa dirección IP del host remoto (consulte el módulo mod_remoteip).
REMOTE_HOSTEl nombre de host del host remoto
REMOTE_IDENTEl nombre de usuario establecido por mod_ident
REMOTE_PORTEl puerto del host remoto (2.4.26 y posterior)
REMOTE_USEREl nombre del usuario autenticado, si lo hay (no disponible durante <If>)
REQUEST_METHODMétodo HTTP usado: GET o POST
Internas del servidor
VariableDescripción
DOCUMENT_ROOT
SCRIPT_GROUP
SCRIPT_USER
SERVER_ADDR
SERVER_ADMINEl usuario administrador del HOST actual
SERVER_NAMENombre del servidor HOST actual
SERVER_PORTPuerto del servidor HOST actual
SERVER_PROTOCOLEl protocolo usado en la solicitud.
SERVER_SOFTWAREVersion de servidor
Especiales
VariableDescripción
API_VERSIONEsta es la versión de la API del módulo httpd de Apache (la interfaz interna entre el servidor y el módulo) en la compilación httpd actual, como se define en include / ap_mmn.h. La versión del módulo API corresponde a la versión de Apache httpd en uso (en la versión de lanzamiento de Apache httpd 1.3.14, por ejemplo, es 19990320: 10), pero es de interés principalmente para los autores de módulos.
CONN_REMOTE_ADDRDesde 2.4.8: la dirección IP de la conexión (consulte el módulo mod_remoteip).
HTTPSContendrá el texto "on" si la conexión está usando SSL/TLS, o "off" en caso contrario. (Esta variable se puede usar de forma segura independientemente de si se carga mod_ssl).
IS_SUBREQ
REQUEST_FILENAMELa ruta completa del sistema de archivos local al archivo o script que coincide con la solicitud, si esto ya ha sido determinado por el servidor en el momento en que se hace referencia a REQUEST_FILENAME. De lo contrario, como cuando se usa en un contexto de host virtual, el mismo valor que REQUEST_URI. Dependiendo del valor de AcceptPathInfo, es posible que el servidor solo haya usado algunos de los componentes principales de REQUEST_URI para asignar la solicitud a un archivo.
REQUEST_SCHEMEContendrá el esquema de la solicitud (generalmente "http" o "https"). Este valor puede ser influenciado con ServerName.
REQUEST_STATUSEl estado de error HTTP de la solicitud (no disponible durante <If>)
REQUEST_LOG_IDLa identificación del registro de errores de la solicitud (ver ErrorLogFormat)
REQUEST_URIEl componente de ruta del URI solicitado, como "/index.html". Esto excluye notablemente la cadena de consulta que está disponible como su propia variable llamada QUERY_STRING.
THE_REQUESTLa línea de solicitud HTTP completa enviada por el navegador al servidor (por ejemplo, "GET /index.html HTTP / 1.1"). Esto no incluye ningún encabezado adicional enviado por el navegador. Este valor no se ha salvado (decodificado), a diferencia de la mayoría de las otras variables a continuación.
Fecha y hora
VariableDescripción
TIME_YEARAño (2020)
TIME_MONMes (1 a 12)
TIME_DAYDia (1 a 31)
TIME_HOURHora (0 a 23)
TIME_MINMinutos (0 a 59)
TIME_SECSegundos (0 a 59)
TIME_WDAYDia de la semana (0=Domingo)
TIMEFecha y hora. (20201231235959)

5. Estructura de control

If, Else, ElseIf

<If "%{HTTP_HOST} == 'sitio.com'">
    Redirect permanent "/" "http://www.sitio.com/"
</If>

6. Tester de htaccess

De todas formas estos scripts son muy difíciles de depurar por lo que te recomiendo una pagina de testeo.

htaccess tester de makewithlove.

7. Comentarios

Pronto...

8. Ejemplos

8.1 Redireccionar permanentemente www.sitio.com a sitio.com

#Este es un comentario
RewriteEngine on
Options +FollowSymLinks
RewriteCond %{HTTP_HOST} ^www\.sitio\.com$ [NC]
RewriteRule ^(.*)$ http://sitio.com/$1 [R=301,L]

8.2 Redireccionar permanentemente sitio.com a www.sitio.com

RewriteEngine on
Options +FollowSymLinks
RewriteCond %{HTTP_HOST} ^sitio\.com$ [NC]
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]

8.3 Redireccionar todo el trafico a un nuevo dominio

RewriteEngine On
RewriteRule ^(.*)$ http://www.nuevodominio.com/$1 [R=301,L]

8.4 Cambiar una parte al medio de la URL.

Supongamos que queremos transformar sitio.com/wiki/algo, en sitio.com/index.php/algo

RewriteEngine On
RewriteCond %{REQUEST_URI} ^/wiki/ [NC]
RewriteRule ^wiki/(.+) /index.php/$1 [R=301,L]

Para eliminar desde cirto punto la URL usa un ? al final ver ejemplo.

8.5 Desvia IP

Para desviar un rango de IP (10.2.x.x) a otro servidor diferente.

RewriteEngine On
RewriteCond %{REMOTE_ADDR} ^10\.2\. 
RewriteRule (.*) http://sitio.com$1 

8.6 Encademar condiciones

Cuando se impone mas de un RewriteCond todos deben coincidir para que se aplica RewriteRule. En este caso si tiene la palabra piratear en su cadena de consulta (QUERY_STRING) y en la cookie (HTTP_COOKIE) No tiene la palabra goto, no te lleva a ningun lado.

RewriteEngine On
RewriteCond %{QUERY_STRING}  piratear [NC]
RewriteCond %{HTTP_COOKIE}  !goto [NC]
RewriteRule . - [F] 

8.7 Disgregar los mobiles

Si tu navegador se autoidentifica como navegador de mobil lo enviamos a la pagina mobil.htm si no a la normal.php.

RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} (iPhone|Blackberry|Android)
RewriteRule ^/$                /mobil.htm    [L]
RewriteRule ^/$                /normal.php   [L]

Si se aplica la primera RewriteRule no se aplica la segunda gracias al modificador [L] (Last Rule)

Tambien podrias eliminar la segunda opcion si en lugar de normal.php usas index.php que es por default.

8.7 Redireccionar un parametro de query

Cuando tenemos un parametro que queremos convertir en una pagina podemos usar esto.

/index.php?id=3 -> http://sitio.com/3.php
/index.php?id=37 -> http://sitio.com/37.php
/index.php?id=371 -> http://sitio.com/371.php
RewriteEngine on
RewriteCond %{QUERY_STRING} ^id=([0-9]+)$
RewriteRule .* http://sitio.com/%1.php? [R=302,L,QSA]

8.8 No mostrar ninguna carpeta

Si una cierta carpeta no tiene index.* muestra el contenido los archivos.

IndexIgnore *

9. Referencias

Algunas referencias usadas para elaborar esta seccion fueron: