"Enlaces bonitos" es un tema solicitado con frecuencia, pero rara vez se explica completamente. mod_rewrite es una forma de hacer "enlaces bonitos", pero es complejo y su sintaxis es muy concisa, difícil de asimilar, y la documentación asume un cierto nivel de competencia en HTTP. ¿Alguien puede explicar en términos simples cómo funcionan los "enlaces bonitos" y cómo se puede usar mod_rewrite para crearlos?
Otros nombres comunes, alias, términos para URL limpias: URL RESTful , URL fáciles de usar, URL amigables con SEO , slugging y URL MVC (probablemente un nombre inapropiado)
apache
.htaccess
mod-rewrite
friendly-url
difunto
fuente
fuente
reference-mod-rewrite-url-rewriting-explained
es la babosa,/questions/20563772/reference-mod-rewrite-url-rewriting-explained
es la bonita URL..htaccess
ymod-rewrite
deberían actualizarse para incluir un enlace a esta pregunta, ya que cubre gran parte de lo que se pide de forma regular. Pensamientos?Respuestas:
Para comprender qué mod_rewrite necesita primero comprender cómo funciona un servidor web. Un servidor web responde a las solicitudes HTTP . Una solicitud HTTP en su nivel más básico se ve así:
Esta es la simple solicitud de un navegador a un servidor web que le solicita la URL
/foo/bar.html
. Es importante destacar que no solicita un archivo , solo solicita una URL arbitraria. La solicitud también puede verse así:Esta es una solicitud igual de válida para una URL, y obviamente no tiene nada que ver con los archivos.
El servidor web es una aplicación que escucha en un puerto, acepta solicitudes HTTP que ingresan en ese puerto y devuelve una respuesta. Un servidor web es completamente libre de responder a cualquier solicitud de la forma que considere adecuada / de cualquier manera que haya configurado para responder. Esta respuesta no es un archivo, es una respuesta HTTP que puede o no tener algo que ver con archivos físicos en cualquier disco. Un servidor web no tiene que ser Apache, hay muchos otros servidores web que son solo programas que se ejecutan de manera persistente y están conectados a un puerto que responde a las solicitudes HTTP. Puedes escribir uno tú mismo. Este párrafo tenía la intención de divorciarte de cualquier noción de que las URL son iguales a los archivos, lo cual es realmente importante de entender. :)
La configuración predeterminada de la mayoría de los servidores web es buscar un archivo que coincida con la URL en el disco duro. Si la raíz del documento del servidor está configurada en, digamos,
/var/www
puede ver si el archivo/var/www/foo/bar.html
existe y servirlo si es así. Si el archivo termina en ".php", invocará al intérprete PHP y luego devolverá el resultado. Toda esta asociación es completamente configurable; un archivo no tiene que terminar en ".php" para que el servidor web lo ejecute a través del intérprete PHP, y la URL no tiene que coincidir con ningún archivo en particular en el disco para que algo suceda.mod_rewrite es una forma de reescribir el manejo interno de solicitudes. Cuando el servidor web recibe una solicitud de URL
/foo/bar
, puede volver a escribir esa URL en otra cosa antes de que el servidor web busque un archivo en el disco para que coincida. Ejemplo simple:Esta regla dice que siempre que una solicitud coincida con "/ foo / bar", vuelva a escribirla en "/ foo / baz". La solicitud se manejará como si se
/foo/baz
hubiera solicitado en su lugar. Esto se puede usar para varios efectos, por ejemplo:Esta regla coincide con cualquier cosa (
.*
) y la captura ((..)
), luego la reescribe para agregar ".html". En otras palabras, si/foo/bar
fue la URL solicitada, se manejará como si se/foo/bar.html
hubiera solicitado. Consulte http://regular-expressions.info para obtener más información sobre la coincidencia, captura y reemplazo de expresiones regulares.Otra regla que se encuentra a menudo es esta:
Esto, nuevamente, coincide con cualquier cosa y lo reescribe en el archivo index.php con la URL solicitada originalmente adjunta en el
url
parámetro de consulta. Es decir, para todas y cada una de las solicitudes entrantes, el archivo index.php se ejecuta y este archivo tendrá acceso a la solicitud original$_GET['url']
, por lo que puede hacer lo que quiera con él.Principalmente pones estas reglas de reescritura en el archivo de configuración de tu servidor web . Apache también le permite * ponerlos en un archivo llamado
.htaccess
dentro de la raíz de su documento (es decir, al lado de sus archivos .php).* Si lo permite el archivo de configuración principal de Apache; Es opcional, pero a menudo habilitado.
Lo mod_rewrite qué no hacer
mod_rewrite no hace mágicamente todas sus URL "bonitas". Este es un malentendido común. Si tiene este enlace en su sitio web:
no hay nada que mod_rewrite pueda hacer para que sea bonito. Para que este sea un enlace bonito, debes:
Cambie el enlace a un enlace bonito:
Use mod_rewrite en el servidor para manejar la solicitud a la URL
/my/pretty/link
usando cualquiera de los métodos descritos anteriormente.(Se podría usar
mod_substitute
en conjunto para transformar las páginas HTML salientes y sus enlaces contenidos. Aunque esto suele ser más esfuerzo que solo actualizar sus recursos HTML).Hay muchas cosas que mod_rewrite puede hacer y reglas de coincidencia muy complejas que puede crear, incluyendo encadenar varias reescrituras, enviar solicitudes a un servicio o máquina completamente diferente, devolver códigos de estado HTTP específicos como respuestas, redireccionar solicitudes, etc. Es muy poderoso y puede usarse para muy bueno si entiendes el mecanismo fundamental de solicitud-respuesta HTTP. No , no significa automáticamente que sus enlaces bonita.
Consulte la documentación oficial para ver todas las banderas y opciones posibles.
fuente
Para ampliar la respuesta de deceze , quería proporcionar algunos ejemplos y explicaciones de alguna otra funcionalidad mod_rewrite.
Todos los ejemplos a continuación asumen que ya lo ha incluido
RewriteEngine On
en su.htaccess
archivo.Ejemplo de reescritura
Tomemos este ejemplo:
La regla se divide en 4 secciones:
RewriteRule
- comienza la regla de reescritura^blog/([0-9]+)/([A-Za-z0-9-\+]+)/?$
- Esto se llama patrón, sin embargo, me referiré a él como el lado izquierdo de la regla, de lo que desea reescribirblog/index.php?id=$1&title=$2
- llamado la sustitución, o el lado derecho de una regla de reescritura - a lo que desea reescribir[NC,L,QSA]
son banderas para la regla de reescritura, separadas por una coma, que explicaré más adelanteLa reescritura anterior le permitiría vincular a algo así
/blog/1/foo/
y en realidad se cargaría/blog/index.php?id=1&title=foo
.Lado izquierdo de la regla
^
indica el inicio del nombre de la página, por lo que se reescribiráexample.com/blog/...
pero noexample.com/foo/blog/...
(…)
paréntesis representa una expresión regular que podemos capturar como una variable en el lado derecho de la regla. En este ejemplo:([0-9]+)
coincide con una cadena con un mínimo de 1 carácter de longitud y solo con valores numéricos (es decir, 0-9). Se puede hacer referencia a esto$1
en el lado derecho de la regla-
o+
(la nota+
se escapa con una barra invertida, ya que sin escapar se ejecutará como una expresión regular) personaje de repetición ). Se puede hacer referencia a esto$2
en el lado derecho de la regla?
medios que el carácter anterior es opcional, por lo tanto, en este caso/blog/1/foo/
y/blog/1/foo
se re-escribir al mismo lugar$
indica que este es el final de la cadena que queremos hacer coincidirBanderas
Estas son opciones que se agregan entre corchetes al final de la regla de reescritura para especificar ciertas condiciones. Una vez más, hay muchos indicadores diferentes que puede leer en la documentación , pero revisaremos algunos de los indicadores más comunes:
El indicador de no caso significa que la regla de reescritura no distingue entre mayúsculas y minúsculas, por lo que para la regla de ejemplo anterior esto significaría que ambos
/blog/1/foo/
y/BLOG/1/foo/
(o cualquier variación de esto) coincidirían.El último indicador indica que esta es la última regla que debe procesarse. Esto significa que si y solo si esta regla coincide, no se evaluarán más reglas en la ejecución del proceso de reescritura actual. Si la regla no coincide, todas las demás reglas se probarán en el orden habitual. Si no establece el
L
indicador, todas las siguientes reglas se aplicarán a la URL reescrita después.Desde Apache 2.4 también puede usar la
[END]
bandera. Una regla que coincida con ella terminará completamente el procesamiento de alias / reescritura adicional. (Mientras que la[L]
bandera a menudo puede desencadenar una segunda ronda, por ejemplo, al reescribir dentro o fuera de subdirectorios).El indicador de cadena de consulta nos permite pasar variables adicionales a la URL especificada que se agregará a los parámetros de obtención originales. Para nuestro ejemplo, esto significa que algo así
/blog/1/foo/?comments=15
se cargaría/blog/index.php?id=1&title=foo&comments=15
Esta bandera no es una que usé en el ejemplo anterior, pero creo que vale la pena mencionarla. Esto le permite especificar una redirección http, con la opción de incluir un código de estado (por ejemplo
R=301
). Por ejemplo, si quisieras hacer una redirección 301 en / myblog / to / blog / simplemente escribirías una regla como esta:Reescribir condiciones
Las condiciones de reescritura hacen que las reescrituras sean aún más potentes, lo que le permite especificar reescrituras para situaciones más específicas. Hay muchas condiciones sobre las que puede leer en la documentación , pero mencionaré algunos ejemplos comunes y los explicaré:
Esta es una práctica muy común, que antepondrá su dominio
www.
(si aún no está allí) y ejecutará una redirección 301. Por ejemplo, cargarlohttp://example.com/blog/
te redirigirá ahttp://www.example.com/blog/
Esto es un poco menos común, pero es un buen ejemplo de una regla que no se ejecuta si el nombre de archivo es un directorio o archivo que existe en el servidor.
%{REQUEST_URI} \.(jpg|jpeg|gif|png)$ [NC]
solo ejecutará la reescritura de archivos con una extensión de archivo de jpg, jpeg, gif o png (no distingue entre mayúsculas y minúsculas).%{REQUEST_FILENAME} !-f
comprobará si el archivo existe en el servidor actual y solo ejecutará la reescritura si no existe%{REQUEST_FILENAME} !-d
comprobará si el archivo existe en el servidor actual y solo ejecutará la reescritura si no existefuente
Referencias
Stack Overflow tiene muchos otros excelentes recursos para comenzar:
eliminar la barra inclinada en los
^/
prefijos de patrones para su.htaccess
uso).Y descripciones de expresiones regulares amigables para los recién llegados, incluso:
Marcadores de posición usados con frecuencia
.*
coincide con cualquier cosa, incluso una cadena vacía. No desea utilizar este patrón en todas partes, pero a menudo en la última regla alternativa.[^/]+
se usa más a menudo para segmentos de ruta. Coincide con cualquier cosa menos la barra diagonal.\d+
solo coincide con cadenas numéricas.\w+
coincide con caracteres alfanuméricos. Básicamente es una forma abreviada de[A-Za-z0-9_]
.[\w\-]+
para segmentos de ruta de estilo "slug", usando letras, números, guiones-
y_
[\w\-.,]+
agrega puntos y comas. Prefiere un\-
guión escapado en[…]
charclasses.\.
denota un período literal. De lo contrario,.
fuera de[…]
es un marcador de posición para cualquier símbolo.Cada uno de estos marcadores de posición suele estar entre
(…)
paréntesis como grupo de captura. Y todo el patrón a menudo en los^………$
marcadores de inicio + final. Citar "patrones" es opcional.RewriteRules
Los siguientes ejemplos están centrados en PHP y son un poco más incrementales, más fáciles de adaptar para casos similares. Son solo resúmenes, a menudo vinculados a más variaciones o preguntas y respuestas detalladas.
Mapeo estático
/contact
,/about
Acortar algunos nombres de página a esquemas de archivos internos es lo más simple:
Identificadores numéricos
/object/123
Introducir accesos directos como
http://example.com/article/531
los scripts PHP existentes también es fácil. El marcador de posición numérico se puede reasignar a un$_GET
parámetro:Marcadores de posición de estilo babosa
/article/with-some-title-slug
Puede ampliar fácilmente esa regla para permitir
/article/title-string
marcadores de posición:Tenga en cuenta que su script debe ser capaz (o estar adaptado) de asignar esos títulos de nuevo a los identificadores de la base de datos. RewriteRules solo no puede crear o adivinar información de la nada.
Babosas con prefijos numéricos
/readable/123-plus-title
Por lo tanto, a menudo verá
/article/529-title-slug
caminos mixtos utilizados en la práctica:Ahora puede omitir el paso de
title=$2
todos modos, ya que su script generalmente dependerá de la base de datos de identificación de todos modos. La-title-slug
decoración de URL se ha convertido en arbitraria.Uniformidad con listas alternativas
/foo/…
/bar/…
/baz/…
Si tiene reglas similares para múltiples rutas de página virtuales, puede hacer coincidirlas y compactarlas con
|
listas alternativas. Y nuevamente, simplemente reasignarlos a los parámetros internos de GET:Puede dividirlos en
RewriteRule
s individuales si esto se vuelve demasiado complejo.Envío de URL relacionadas a diferentes backends
/date/SWITCH/backend
Un uso más práctico de listas alternativas consiste en asignar rutas de solicitud a scripts distintos. Por ejemplo, para proporcionar URL uniformes para una aplicación web más antigua y más nueva en función de las fechas:
Esto simplemente reasigna las publicaciones 2009-2011 en un script, y todos los demás años implícitamente en otro controlador. Tenga en cuenta la regla más específica que viene primero . Cada script puede usar diferentes parámetros GET.
Otros delimitadores además de los
/
cortes de ruta/user-123-name
Lo más común es ver RewriteRules para simular una estructura de directorio virtual. Pero no estás obligado a ser poco creativo. También puede usar
-
guiones para segmentar o estructurar.Para el
/wiki:section:Page_Name
esquema también común :Ocasionalmente, es adecuado alternar entre
/
-delimitadores y /:
o.
incluso en la misma regla. O tenga dos RewriteRules nuevamente para mapear variantes en diferentes scripts.Barra
/
inclinada opcional/dir
=/dir/
Al optar por rutas de estilo de directorio, puede hacerlo accesible con y sin un final /
Ahora esto maneja ambos
http://example.com/blog/123
y/blog/123/
. Y el/?$
enfoque es fácil de agregar a cualquier otra RewriteRule.Segmentos flexibles para rutas virtuales.
.*/.*/.*/.*
La mayoría de las reglas que encontrará asignan un conjunto restringido de
/…/
segmentos de ruta de recursos a parámetros GET individuales. Sin embargo, algunos scripts manejan un número variable de opciones . El motor regexp de Apache no permite la opción de un número arbitrario de ellos. Pero puede expandirlo fácilmente en un bloque de reglas usted mismo:Si necesita hasta cinco segmentos de ruta, copie este esquema en cinco reglas. Por supuesto, puede usar un
[^/]+
marcador de posición más específico para cada uno. Aquí el orden no es tan importante, como tampoco se superpone. Por lo tanto, tener los caminos más utilizados primero está bien.Alternativamente, puede utilizar los parámetros de matriz de PHP a través de
?p[]=$1&p[]=$2&p[]=3
cadena de consulta aquí, si su script simplemente los prefiere previamente divididos. (Aunque es más común usar una regla general y dejar que el script expanda los segmentos fuera de REQUEST_URI).Consulte también: ¿Cómo transformo mis segmentos de ruta URL en pares de clave-valor de cadena de consulta?
Segmentos opcionales
prefix/opt?/.*
Una variación común es tener prefijos opcionales dentro de una regla. Esto generalmente tiene sentido si tiene cadenas estáticas o marcadores de posición más restringidos:
Ahora, el patrón más complejo
(?:/([^/])+)?
simplemente envuelve un grupo que no captura(?:…)
y lo hace opcional)?
. El marcador de posición contenido([^/]+)
sería un patrón de sustitución$2
, pero estaría vacío si no hay una/…/
ruta intermedia .Captura el resto
/prefix/123-capture/…/*/…whatever…
Como se dijo antes, a menudo no quieres patrones de reescritura demasiado genéricos. Sin embargo, tiene sentido combinar comparaciones estáticas y específicas con
.*
algunas veces.Esto opcionalizó cualquier
/…/…/…
segmento de ruta final. Lo cual, por supuesto, requiere la secuencia de comandos de manejo para dividirlos, y los parámetros extraídos de forma variable (que es lo que hacen los marcos web "MVC" ).Archivo final "extensiones"
/old/path.HTML
Las URL realmente no tienen extensiones de archivo. De eso se trata toda esta referencia (= las URL son localizadores virtuales, no necesariamente una imagen directa del sistema de archivos). Sin embargo, si antes tenía una asignación de archivos 1: 1, puede crear reglas más simples:
Otros usos comunes son la reasignación de
.html
rutas obsoletas a.php
controladores más nuevos , o simplemente alias de nombres de directorio solo para archivos individuales (reales / reales).Ping-Pong (redirige y reescribe al unísono)
/ugly.html
← →/pretty
Entonces, en algún momento, está reescribiendo sus páginas HTML para que solo contengan enlaces bonitos, como se describe en deceze . Mientras tanto, seguirá recibiendo solicitudes de los viejos caminos, a veces incluso de marcadores. Como solución alternativa , puede utilizar los navegadores de ping-pong para mostrar / establecer las nuevas URL.
Este truco común implica enviar una redirección 30x / Location cada vez que una URL entrante sigue el esquema de nombres obsoleto / feo. Los navegadores volverán a solicitar la nueva / bonita URL, que luego se reescribe (solo internamente) a la ubicación original o nueva.
Observe cómo este ejemplo solo se usa en
[END]
lugar de[L]
alternar de manera segura. Para versiones anteriores de Apache 2.2, puede usar otras soluciones alternativas, además de reasignar los parámetros de la cadena de consulta, por ejemplo: Redirigir URL fea a bonita, reasignar nuevamente a la ruta fea, sin bucles infinitosEspacios ␣en patrones
/this+that+
No es tan bonito en las barras de direcciones del navegador, pero puede usar espacios en las URL. Para reescribir patrones, use
\␣
espacios con barra invertida . De lo contrario,"
cite todo el patrón o sustitución:Los clientes serializan URL con
+
o%20
para espacios. Sin embargo, en RewriteRules se interpretan con caracteres literales para todos los segmentos de ruta relativos.Duplicados frecuentes:
Catch-all para un script de despachador central / controlador frontal
El cual es usado frecuentemente por frameworks PHP o WebCMS / scripts de portal. La división de ruta real se maneja en PHP usando
$_SERVER["REQUEST_URI"]
. Así que, conceptualmente, es casi lo opuesto al manejo de URL "por mod_rewrite". (Solo useFallBackResource
en su lugar).Eliminar
www.
del nombre de hostTenga en cuenta que esto no copia una cadena de consulta, etc.
Consulte también:
· Reescritura de URL para diferentes protocolos en .htaccess
· Redirección genérica de htaccess www a no www
· .htaccess: cómo forzar "www". de manera genérica?
Tenga en cuenta que los combos RewriteCond / RewriteRule pueden ser más complejos, con coincidencias (
%1
e$1
) interactuando en ambas direcciones incluso:Manual de Apache - introducción de mod_rewrite , Copyright 2015 The Apache Software Foundation, AL-2.0
Redirigir a
HTTPS://
Ver también: https://wiki.apache.org/httpd/RewriteHTTPToHTTPS
"Eliminando" la extensión PHP
Ver también: Eliminar la extensión .php con mod_rewrite
Alias de rutas antiguas .html a scripts .php
Ver: http://httpd.apache.org/docs/2.4/rewrite/remapping.html#backward-compatibility
Reescriba desde URL como "/ page" a un script como "/index.php/page"
Ver mod_rewrite, php y el archivo .htaccess
Redireccionar subdominio a una carpeta
Consulte ¿Cómo puedo hacer que mi htaccess funcione (subdominios)?
prevalentes
.htaccess
trampasAhora tome esto con un grano de sal. No todos los consejos se pueden generalizar a todos los contextos. Este es solo un resumen simple de obstáculos conocidos y algunos no obvios:
Habilitar
mod_rewrite
y.htaccess
Para usar RewriteRules en archivos de configuración por directorio, debe:
Comprueba que tu servidor esté
AllowOverride All
habilitado . De lo contrario, sus.htaccess
directivas por directorio se ignorarán y RewriteRules no funcionará.Obviamente lo has
mod_rewrite
habilitado en lahttpd.conf
sección de tus módulos.Anteponga cada lista de reglas con
RewriteEngine On
still. Mientras que mod_rewrite está implícitamente activo en<VirtualHost>
y<Directory>
secciones, los.htaccess
archivos por directorio lo necesitan convocar individualmente.La barra diagonal
^/
no coincidiráNo debería comenzar sus
.htaccess
patrones RewriteRule con^/
normalidad:Esto se ve a menudo en antiguos tutoriales. Y solía ser correcto para las antiguas versiones de Apache 1.x. Hoy en día, las rutas de solicitud están convenientemente relacionadas con el directorio en
.htaccess
RewriteRules. Solo deja la guía/
.· Tenga en cuenta que la barra inclinada aún es correcta en las
<VirtualHost>
secciones. Es por eso que a menudo lo ves^/?
opcional para la paridad de reglas.· O cuando utilizas un
RewriteCond %{REQUEST_URI}
todavía te corresponde para un líder/
.· Consulte también Webmaster.SE: ¿Cuándo se necesita la barra diagonal (/) en los patrones mod_rewrite?
<IfModule *>
envoltorios se fueron!Probablemente has visto esto en muchos ejemplos:
<VirtualHost>
secciones - si se combina con otra opción de reserva, como ScriptAliasMatch. (Pero nadie hace eso nunca)..htaccess
conjuntos de reglas predeterminados con muchos proyectos de código abierto. Ahí solo se entiende como reserva, y mantiene las URL "feas" funcionan por defecto.Sin embargo, generalmente no lo desea en sus propios
.htaccess
archivos.500
errores HTTP . Lo que generalmente logra es agradecer a sus usuarios con404
errores HTTP . (No es mucho más fácil de usar si lo piensas).No lo use a
RewriteBase
menos que sea necesarioMuchos ejemplos de copiar + pegar contienen una
RewriteBase /
directiva. Que resulta ser el valor implícito predeterminado de todos modos. Entonces realmente no necesitas esto. Es una solución alternativa para los sofisticados esquemas de reescritura de VirtualHost y las rutas DOCUMENT_ROOT erróneas para algunos servidores compartidos.Tiene sentido usarlo con aplicaciones web individuales en subdirectorios más profundos. Puede acortar los patrones de RewriteRule en tales casos. En general, es mejor preferir especificadores de ruta relativa en conjuntos de reglas por directorio.
Consulte también Cómo funciona RewriteBase en .htaccess
Deshabilitar
MultiViews
cuando las rutas virtuales se superponenLa reescritura de URL se utiliza principalmente para admitir rutas de entrada virtuales . Comúnmente sólo tiene un guión despachador (
index.php
) o un par de manipuladores individuales (articles.php
,blog.php
,wiki.php
, ...). Este último podría chocar con rutas virtuales similares de RewriteRule.Una solicitud, por
/article/123
ejemplo, podría correlacionarsearticle.php
con un/123
PATH_INFO implícitamente. Tendría que proteger sus reglas con CommonplaceRewriteCond
!-f
+!-d
y / o deshabilitar el soporte PATH_INFO, o tal vez simplemente deshabilitarOptions -MultiViews
.Lo que no quiere decir que siempre tengas que hacerlo . La negociación de contenido es solo un automatismo de los recursos virtuales.
Ordenar es importante
Vea todo lo que siempre quiso saber sobre mod_rewrite si aún no lo ha hecho. La combinación de múltiples RewriteRules a menudo conduce a la interacción. Esto no es algo para evitar habitualmente por
[L]
bandera, sino un esquema que adoptará una vez versado. Usted puede re-re-re escritura caminos virtuales de una regla a otra, hasta que llega a un controlador objetivo real.Aún así, a menudo querrá tener las reglas más específicas (
/forum/…
patrones de cadena fijos o marcadores de posición más restrictivos[^/.]+
) en las primeras reglas..*
Es mejor dejar las reglas genéricas de slurp-all ( ) posteriores . (Una excepción es unRewriteCond -f/-d
guardia como bloque primario).Las hojas de estilo y las imágenes dejan de funcionar
Cuando introduce estructuras de directorios virtuales
/blog/article/123
esto afecta las referencias relativas de recursos en HTML (como<img src=mouse.png>
). Que se puede resolver mediante:href="https://stackoverflow.com/old.html"
osrc="/logo.png"
<base href="https://stackoverflow.com/index">
a su HTML<head>
sección . Esto implícitamente vuelve a unir referencias relativas a lo que eran antes.Alternativamente, podría crear más RewriteRules para volver a unir
.css
o.png
rutas a sus ubicaciones originales. Pero eso es innecesario o incurre en redirecciones adicionales y dificulta el almacenamiento en caché.Ver también: CSS, JS y las imágenes no se muestran con URL bonita
RewriteConds simplemente enmascara una RewriteRule
Una mala interpretación común es que un RewriteCond bloquea múltiples RewriteRules (porque están visualmente organizadas juntas):
Que no lo hace por defecto. Puedes encadenarlos usando el
[S=2]
bandera. De lo contrario, tendrás que repetirlos. Si bien a veces puedes crear una regla primaria "invertida" para [FINALIZAR] el proceso de reescritura temprano.QUERY_STRING exento de RewriteRules
No puede coincidir
RewriteRule index.php\?x=y
, porque mod_rewrite se compara solo con las rutas relativas por defecto. Sin embargo, puede combinarlos por separado a través de:Consulte también ¿Cómo puedo hacer coincidir las variables de cadena de consulta con mod_rewrite?
.htaccess
vs.<VirtualHost>
Si está utilizando RewriteRules en un archivo de configuración por directorio, entonces no tiene sentido preocuparse por el rendimiento de expresiones regulares. Apache retiene los patrones PCRE compilados por más tiempo que un proceso PHP con un marco de enrutamiento común. Sin embargo, para los sitios de alto tráfico, debe considerar mover los conjuntos de reglas a la configuración del servidor vhost, una vez que hayan sido probados en batalla.
En este caso, prefiera el
^/?
prefijo separador de directorio opcional . Esto permite mover RewriteRules libremente entre PerDir y los archivos de configuración del servidor.Cuando algo no funciona
No temas.
Compara
access.log
yerror.log
A menudo, puedes descubrir cómo se comporta mal una RewriteRule solo con mirar tu
error.log
yaccess.log
. Correlacione los tiempos de acceso para ver qué ruta de solicitud entró originalmente y qué ruta / archivo no pudo resolver Apache (error 404/500).Esto no te dice qué RewriteRule es el culpable. Pero los caminos finales inaccesibles como
/docroot/21-.itle?index.php
pueden revelar dónde inspeccionar más. De lo contrario, deshabilite las reglas hasta que obtenga algunas rutas predecibles.Habilite RewriteLog
Vea los documentos de Apache RewriteLog . Para la depuración, puede habilitarlo en las secciones de vhost:
Eso produce un resumen detallado de cómo las rutas de solicitud entrantes se modifican por cada regla:
Lo que ayuda a reducir las reglas demasiado genéricas y los contratiempos de expresiones regulares.
Consulte también:
· .htaccess no funciona (mod_rewrite)
· Consejos para depurar reglas de reescritura de .htaccess
Antes de hacer tu propia pregunta
Como ya sabrás, Stack Overflow es muy adecuado para hacer preguntas sobre mod_rewrite. Hazlos sobre el tema al incluir investigaciones e intentos previos (evite respuestas redundantes), demuestre lo básicoregex comprensión y:
$_SERVER
entorno si se trata de una falta de coincidencia de parámetros.access.log
yerror.log
para verificar lo que resolvieron las reglas existentes. Mejor aún, unrewrite.log
resumen.Esto proporciona respuestas más rápidas y exactas, y las hace más útiles para otros.
Comenta tu
.htaccess
Si copia ejemplos de algún lugar, tenga cuidado de incluir a
# comment and origin link
. Si bien es simplemente de mala educación omitir la atribución, a menudo realmente perjudica el mantenimiento más adelante. Documente cualquier código o fuente de tutorial. En particular, mientras no esté versado, debería estar más interesado en no tratarlos como cajas negras mágicas.No es "SEO" -URLs
Descargo de responsabilidad: solo un motivo favorito. A menudo escuchas bonitos esquemas de reescritura de URL conocidos como enlaces "SEO" o algo así. Si bien esto es útil para buscar ejemplos en Google, es un nombre inapropiado.
Ninguno de los modernos motores de búsqueda son muy perturbado por
.html
y.php
en los segmentos de trazado, o?id=123
cadenas de consulta para el caso. Los motores de búsqueda de la antigüedad, tales como AltaVista, hicieron evitar el rastreo de sitios web con las rutas de acceso potencialmente ambiguas. Los rastreadores modernos a menudo incluso anhelan recursos web profundos.Lo que las URL "bonitas" deberían usarse conceptualmente es hacer que los sitios web sean fáciles de usar .
/common/tree/nesting
.Sin embargo, no sacrifique requisitos únicos para el conformismo.
Herramientas
Existen varias herramientas en línea para generar RewriteRules para la mayoría de las URL de parámetros GET:
En su mayoría solo genera
[^/]+
marcadores de posición genéricos, pero probablemente sea suficiente para sitios triviales.fuente
Alternativas a mod_rewrite
Se pueden lograr muchos esquemas básicos de URL virtual sin usar RewriteRules. Apache permite invocar scripts PHP sin
.php
extensión y con unPATH_INFO
argumento virtual .Usa el PATH_INFO , Luke
Hoy en día a
AcceptPathInfo On
menudo está habilitado de forma predeterminada. Lo que básicamente permite.php
y otras URL de recursos llevar un argumento virtual:Ahora esto
/virtual/path
aparece en PHP como$_SERVER["PATH_INFO"]
donde puedes manejar cualquier argumento extra como quieras.Esto no es tan conveniente como tener Apache segmentos de trayectoria de entrada separado en
$1
,$2
,$3
y que pasa a ellos como distintas$_GET
variables en PHP. Simplemente está emulando "URL bonitas" con menos esfuerzo de configuración.Habilitar MultiViews para ocultar la
.php
extensión.La opción más simple para evitar también
.php
"extensiones de archivo" en las URL es habilitar:Esto tiene Apache select
article.php
para solicitudes HTTP activadas/article
debido al nombre base coincidente. Y esto funciona bien junto con la función PATH_INFO antes mencionada. Así que solo puedes usar URL comohttp://example.com/article/virtual/title
. Lo que tiene sentido si tiene una aplicación web tradicional con múltiples puntos / scripts de invocación PHP.Sin embargo, tenga en cuenta que MultiViews tiene un propósito diferente / más amplio. Incurre en una penalización de rendimiento muy pequeña , porque Apache siempre busca otros archivos con nombres de base coincidentes. De hecho, es destinado a negociación de contenido , por lo que los navegadores reciban la mejor alternativa entre los recursos disponibles (como
article.en.php
,article.fr.php
,article.jp.mp4
).SetType o SetHandler para sin extensión
.php
scripts sinUn enfoque más dirigido para evitar llevar
.php
sufijos en las URL es configurar el controlador PHP para otros esquemas de archivos. La opción más simple es anular el tipo MIME / controlador predeterminado mediante.htaccess
:De esta manera, podría cambiar el nombre de su
article.php
script a soloarticle
(sin extensión), pero aún así procesarlo como script PHP.Ahora esto puede tener algunas implicaciones de seguridad y rendimiento, porque todos los archivos sin extensión se canalizarían a través de PHP ahora. Por lo tanto, también puede configurar este comportamiento solo para archivos individuales:
Esto depende en cierta medida de la configuración de su servidor y del PHP SAPI utilizado. Las alternativas comunes incluyen
ForceType application/x-httpd-php
oAddHandler php5-script
.Otros esquemas de reescritura de Apache
Entre sus muchas opciones, Apache proporciona
mod_alias
características, que a veces funcionan tan bien comomod_rewrite
las RewriteRules. Tenga en cuenta que la mayoría de ellos deben configurarse en una<VirtualHost>
sección, no en.htaccess
archivos de configuración por directorio .ScriptAliasMatch
es principalmente para scripts CGI, pero también debería funcionar para PHP. Permite expresiones regulares como cualquier otraRewriteRule
. De hecho, es quizás la opción más robusta para configurar un controlador frontal universal.Y una simple
Alias
ayuda con algunos esquemas simples de reescritura también.Incluso una
ErrorDocument
directiva simple podría usarse para permitir que un script PHP maneje rutas virtuales. Tenga en cuenta que esta es una solución poco clara, sin embargo, prohíbe todo menos las solicitudes GET e inunda el error.log por definición.Consulte http://httpd.apache.org/docs/2.2/urlmapping.html para obtener más sugerencias.
fuente