Hola, hallamos la solución a tu búsqueda, deslízate y la verás un poco más abajo.
Solución:
Si lo solicita /article
y /article
existe como un directorio físico, entonces el mod_dir de Apache, agregará (por defecto) la barra al final para “arreglar” la URL. Esto se logra con un redireccionamiento permanente 301, por lo que el navegador lo almacenará en caché.
Aunque tener un directorio físico con el mismo nombre de base que un archivo y usar URL sin extensión crea una ambigüedad. p.ej. Es /article
se supone que debe acceder al directorio /article/
o el archivo /article.html
. No parece que desee permitir el acceso directo a los directorios de todos modos, por lo que parecería resolver esa ambigüedad.
Para evitar que Apache mod_dir agregue la barra al final a los directorios, debemos deshabilitar la DirectorySlash
. Por ejemplo:
DirectorySlash Off
Pero como se mencionó, si ha visitado previamente /article
luego la redirección a /article/
habrá sido almacenado en caché por el navegador, por lo que deberá borrar el caché del navegador antes de que esto sea efectivo.
Dado que está eliminando la extensión del archivo, también debe asegurarse de que MultiViews esté deshabilitado; de lo contrario, mod_negotiation emitirá una solicitud secundaria interna para el archivo subyacente y, potencialmente, entrará en conflicto con mod_rewrite. MultiViews está deshabilitado de forma predeterminada, aunque algunos hosts compartidos lo habilitan por alguna razón. Por la salida que está obteniendo, no parece que MultiViews esté habilitado, pero es mejor estar seguro …
# Ensure that MutliViews is disabled
Options -MultiViews
Sin embargo, si necesita poder acceder al directorio en sí, deberá agregar manualmente la barra al final con una reescritura interna. Aunque esto no parece ser un requisito aquí. Sin embargo, debe asegurarse de que las listas de directorios estén deshabilitadas:
# Disable directory listings
Options -Indexes
Intentar acceder a cualquier directorio (que en última instancia no se asigna a un archivo, ver más abajo) y no contiene un DirectoryIndex
El documento devolverá una respuesta 403 Forbidden, en lugar de una lista de directorio.
Tenga en cuenta que la única diferencia que podría ocurrir entre seguir un enlace a domain/article
, actualizando la página y escribiendo manualmente domain/article
es almacenamiento en caché … ya sea por el navegador o cualquier caché de proxy intermediario. (¡¿A menos que tenga JavaScript que intercepte el evento de clic en el ancla ?!)
Aún necesita reescribir las solicitudes de /foo
para /foo.html
O /foo
para /foo/index.html
(ver más abajo), dependiendo de cómo haya configurado su sitio. Aunque sería preferible que elijas uno u otro, en lugar de ambos (como parece que podría ser el caso).
RewriteCond %REQUEST_FILENAME !-d RewriteCond %REQUEST_FILENAME.html -f RewriteRule ^(.*)$ $1.html
No está claro cómo esto aparentemente “funciona” para usted actualmente, a menos que vea una respuesta en caché. Cuando lo solicitas /article
, la primera condición falla porque existe como un directorio físico y la regla no se procesa. Incluso con MultiViews habilitado, mod_dir tendrá prioridad y agregará la barra al final.
La segunda condición que comprueba la existencia de la .html
archivo no necesariamente está comprobando el mismo archivo en el que se está reescribiendo. p.ej. Si lo solicita /foo/bar
, dónde /foo.html
existe, pero no hay un directorio físico /foo
entonces el RewriteCond
la directiva verifica la existencia de /foo.html
– que tiene éxito, pero la solicitud se reescribe internamente a /foo/bar.html
(del capturado RewriteRule
patrón): esto da como resultado un bucle de reescritura interno y una respuesta de error 500 que se devuelve al cliente. Vea mi respuesta a la siguiente pregunta de ServerFault que explica con más detalle lo que realmente está sucediendo aquí.
También podemos realizar una optimización adicional si asumimos que cualquier URL que contenga lo que parece una extensión de archivo (por ejemplo, su static recursos .css
, .js
y archivos de imagen) deben ignorarse, de lo contrario, estamos realizando verificaciones del sistema de archivos en cada solicitud, lo cual es relativamente costoso.
Entonces, para mapear (reescribir internamente) solicitudes del formulario /article
para /article.html
y /article/somearticle
para /article/somearticle.html
necesitaría modificar la regla anterior para leer algo como:
# Rewrite /foo to /foo.html if it exists
RewriteCond %DOCUMENT_ROOT%REQUEST_URI.html -f
RewriteRule !.w2,4$ %REQUEST_URI.html [L]
No es necesario que la barra invertida escape de un punto literal en el RewriteCond
TestString – el punto no tiene ningún significado especial aquí; no es una expresión regular.
Luego, para manejar solicitudes del formulario /foo
que debería mapear a /foo/index.html
puedes hacer algo como lo siguiente:
# Rewrite /foo to /foo/index.html if it exists
RewriteCond %DOCUMENT_ROOT%REQUEST_URI/index.html -f
RewriteRule !.w2,4$ %REQUEST_URI/index.html [L]
Normalmente, permitiría que mod_dir sirva el DirectoryIndex
(p.ej. index.html
), pero habiendo omitido la barra al final del directorio, esto puede ser problemático.
Resumen
Reuniendo los puntos anteriores, tenemos:
# Disable directory indexes and MultiViews
Options -Indexes -MultiViews
# Prevent mod_dir appending a slash to directory requests
DirectorySlash Off
# Rewrite /foo to /foo.html if it exists
RewriteCond %DOCUMENT_ROOT%REQUEST_URI.html -f
RewriteRule !.w2,4$ %REQUEST_URI.html [L]
# Otherwise, rewrite /foo to /foo/index.html if it exists
RewriteCond %DOCUMENT_ROOT%REQUEST_URI/index.html -f
RewriteRule !.w2,4$ %REQUEST_URI/index.html [L]
Esto podría optimizarse aún más, dependiendo de la estructura de su sitio y si está agregando más directivas al .htaccess
expediente. Por ejemplo:
- puede verificar las extensiones de archivo en la URL solicitada en la parte superior del archivo para evitar cualquier procesamiento posterior. los
RewriteRule
La expresión regular en cada regla subsiguiente podría entonces “simplificarse”. - Las solicitudes que incluyen una barra inclinada final se pueden bloquear o redirigir (para eliminar la barra inclinada final).
- Si la solicitud es para un
.html
luego redirigir a la URL sin extensión. Esto se vuelve un poco más complicado si se trata de ambos/foo.html
y/foo/index.html
. Pero esto solo es realmente necesario si cambiando una estructura de URL existente.
Por ejemplo, implementar # 1 y # 2 anteriores, permitiría que las directivas se escribieran así:
# Disable directory indexes and MultiViews
Options -Indexes -MultiViews
# Prevent mod_dir appending a slash to directory requests
DirectorySlash Off
# Prevent any further processing if the URL already ends with a file extension
RewriteRule .w2.4$ - [L]
# Redirect any requests to remove a trailing slash
RewriteRule (.*)/$ /$1 [R=301,L]
# Rewrite /foo to /foo.html if it exists
RewriteCond %DOCUMENT_ROOT/$1.html -f
RewriteRule (.*) $1.html [L]
# Otherwise, rewrite /foo to /foo/index.html if it exists
RewriteCond %DOCUMENT_ROOT/$1/index.html -f
RewriteRule (.*) $1/index.html [L]
Pruebe siempre con una redirección 302 (temporal) antes de cambiar a una redirección 301 (permanente) para evitar problemas de almacenamiento en caché.
Al final de todo puedes encontrar las notas de otros usuarios, tú asimismo tienes la libertad de dejar el tuyo si te gusta.