# BEGIN CMOX TIENDA ESTATICA
# La tienda es un sitio estatico. WordPress se queda instalado debajo: sigue
# teniendo los pedidos, los clientes y el panel, y volver atras es quitar este
# bloque.
#
# Lo escribe `despliegue/publicar.sh` en cada despliegue, sustituyendo lo que
# hubiera entre BEGIN y END. Se reescribe siempre y no solo si falta: antes
# solo se anadia cuando no estaba, asi que ninguna correccion llegaba a un
# servidor que ya lo tuviera. Es literalmente por lo que las cabeceras de
# cache no existieron durante horas.
#
# NO se inventan reglas de reescritura aqui. Una regla «protectora» en el
# .htaccess de cmox.es tumbo /panelcmox y /wp-admin enteros en su dia. Lo unico
# que hace falta para que convivan la tienda estatica y WordPress es el
# DirectoryIndex: la reescritura de WordPress solo actua cuando el fichero NO
# existe, asi que cada carpeta que trae el sitio nuevo la sirve Apache directo.
DirectoryIndex index.html index.php
# Sin indices de directorio.
#
# Medido: https://tienda.cmox.es/img/ devolvia un «Index of /img» con el arbol
# entero de fotografias navegable, y wp-content/uploads/ igual. Eso da la lista
# completa de nombres de fichero a quien pase por ahi, incluida la de las fotos
# que la regla de mas abajo protege de que las enlacen desde fuera: se puede
# tapar la puerta y dejar el listin pegado al lado.
#
# Y no es solo cosa de fotos. Un indice de wp-content/uploads/ ensena que
# plugins hay, con sus carpetas, y eso es la mitad del trabajo de quien busca
# una version vieja con un agujero conocido.
#
# No es una regla de reescritura: no enruta nada y no puede tumbar el panel.
# Lo unico que hace es que Apache deje de fabricar una pagina de listado cuando
# una carpeta no tiene indice.
Options -Indexes
# Las legales viejas del WordPress, a las nuevas.
#
# Estaban despublicadas desde ayer, asi que ya caian en el 404 del sitio nuevo.
# Un 404 esta bien para /carrito/ o para un articulo de relleno; para una
# politica de privacidad no: quien la busca la busca por un motivo, y llevarle
# a un error deja peor sabor que no haberla tenido nunca.
#
# Redirect y no RewriteRule: esto no enruta nada, solo dice que una direccion
# se ha movido.
# /aviso-legal/ NO lleva redireccion, y es a proposito: la pagina NUEVA vive
# en esa misma direccion. Redirigirla a si misma es un bucle infinito, y el
# navegador corta con ERR_TOO_MANY_REDIRECTS. La vieja estaba despublicada,
# asi que el fichero estatico ya gana sin ayuda.
Redirect 301 /privacidad/ https://tienda.cmox.es/politica-de-privacidad/
# /politica-de-cookies/ TAMPOCO lleva redireccion ya. La llevaba mientras la
# tienda no tenia analitica y no habia pagina propia que ofrecer; desde que se
# anadio Google Analytics existe de verdad, y la redireccion la tapaba: la
# pagina se compilaba y el servidor mandaba a otra parte antes de servirla.
Redirect 301 /terminos-y-condiciones/ https://tienda.cmox.es/aviso-legal/
RewriteEngine On
# Las direcciones viejas que ya no existen, a su sitio nuevo.
#
# Con destino relativo, Apache reconstruye la URL absoluta y le mete el
# puerto: salia «https://tienda.cmox.es:443/catalogo/». Funciona, pero se ve
# en la barra y en los buscadores. Con la URL entera no reconstruye nada.
RewriteRule ^productos/?$ https://tienda.cmox.es/catalogo/ [R=301,L]
RewriteRule ^tienda/?$ https://tienda.cmox.es/catalogo/ [R=301,L]
# ^empresa/?$ SE QUITO el 27/08/2026, y conviene saber por que.
#
# Mandaba a https://cmox.es/sobre-nosotros/, y esa pagina paso a devolver 404
# ese mismo dia --Toni: fuera todo lo que no sea la web nueva--. Quedaba una
# redireccion que terminaba en un error: quien pulsara el resultado aterrizaba
# en una pagina rota, y Google veia un 301 hacia nada. Eso es peor que
# cualquiera de las dos opciones limpias.
#
# Se elige el 404 y no repuntar a la portada porque repuntar seria reponer,
# un salto antes, justo lo que se acababa de quitar.
#
# Lo que costo, para que este el numero y no la sensacion: /empresa/ tenia 28
# apariciones en 90 dias en POSICION 1,5 --el mejor puesto de toda la
# tienda-- y 1 clic.
#
# Las de arriba se quedan, y no es incoherencia: /productos/ y /tienda/ no son
# paginas viejas que sobrevivan, son punteros a /catalogo/, que es pagina de
# la web nueva y que por si sola no tiene ni una aparicion en Google.
# ── Las fotografias ──────────────────────────────────────────────────
# Solo se sirven a paginas de cmox.es. Con esto, otra web no puede
# enlazarlas desde aqui —cargandole a CMOX el trafico y la propiedad de la
# foto— y no se bajan pegando la URL en la barra. Es lo mismo que ya hacia
# cmox.es con /img/v2/ desde el 24/08; la tienda se habia quedado sin ello.
#
# Lo que NO puede hacer ninguna configuracion del mundo: evitar que quien ve
# la foto en la pagina la tenga ya en su ordenador. Para verla, el navegador
# ha tenido que descargarla. Eso es la web.
#
# Se limita a escenas y productos a proposito. El logotipo, los iconos y la
# imagen de vista previa tienen que seguir siendo accesibles sin referente,
# o WhatsApp, LinkedIn y Google dejan de poder leerlas.
RewriteCond %{HTTP_REFERER} !^https?://([a-z0-9-]+\.)?cmox\.es(/|$) [NC]
RewriteRule ^img/(escenas|productos)/ - [F,L]
AddType image/avif .avif
AddType image/webp .webp
AddType font/woff2 .woff2
# ── Seguridad ────────────────────────────────────────────────────────
# No habia ninguna. Son las que no rompen nada: NO se pone una
# Content-Security-Policy completa porque la tienda usa scripts en linea a
# proposito —el captcha, los precios, el idioma— y una CSP mal puesta no
# protege: apaga la web.
# Que el navegador no adivine el tipo de un fichero. Sin esto, algo subido
# como imagen que en realidad lleve HTML puede acabar ejecutandose. Importa
# aqui mas que en un sitio estatico normal: WordPress sigue debajo y acepta
# subidas.
Header always set X-Content-Type-Options "nosniff"
# Nadie mete esta tienda en un iframe. Es como se monta una pagina que
# parece la tuya y recoge lo que el visitante escribe. Va en CSP porque
# X-Frame-Options esta obsoleto, y tambien en X-Frame-Options porque los
# navegadores viejos solo entienden aquel.
Header always set Content-Security-Policy "frame-ancestors 'self'"
Header always set X-Frame-Options "SAMEORIGIN"
# Al salir a otra web se manda el dominio, no la direccion completa. Con la
# ruta entera, un enlace desde /producto/linak-cb12/ le cuenta a quien lo
# recibe que ese visitante estaba mirando esa reparacion.
Header always set Referrer-Policy "strict-origin-when-cross-origin"
# Camara, microfono, ubicacion y pagos: esta tienda no usa ninguno, y
# decirlo impide que los pida un script de terceros que entre por donde sea.
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()"
# HTTPS obligatorio durante seis meses. SIN `includeSubDomains` a proposito:
# eso lo aplicaria tambien a vortex, rain y crm, y no se decide por otros
# sitios desde el .htaccess de este. Sin `preload` por lo mismo: entrar en
# la lista de los navegadores es facil y salir tarda meses.
Header always set Strict-Transport-Security "max-age=15552000"
# ── Cache ────────────────────────────────────────────────────────────
# El HTML no se guarda. Sin esto la tienda no mandaba NINGUNA cabecera de
# cache, asi que el CDN de OVH se quedaba el HTML por su cuenta y seguia
# sirviendo la pagina vieja despues de desplegar: X-CDN-Cache: HIT y una
# portada de hace horas. cmox.es ya lo hacia bien; la tienda no.
#
# `no-store` ademas de `no-cache` porque no-cache permite guardar y
# revalidar, y el CDN de por medio hace de eso lo que quiere.
Header set Cache-Control "no-store, no-cache, must-revalidate, max-age=0"
# Lo de _astro/ lleva el hash del contenido en el nombre: si cambia el
# fichero cambia la URL, asi que se puede guardar para siempre. Estaba en 15
# minutos, que es tirar la cache sin ganar nada.
Header set Cache-Control "public, max-age=31536000, immutable"
# Fotos y fuentes: un mes. No llevan hash, pero cambian poco y cuando
# cambian no es urgente que se vea al segundo.
Header set Cache-Control "public, max-age=2592000"
# END CMOX TIENDA ESTATICA
# BEGIN WordPress
# Las directivas (líneas) entre «BEGIN WordPress» y «END WordPress» son
# generadas dinámicamente y solo deberían ser modificadas mediante filtros de WordPress.
# Cualquier cambio en las directivas que hay entre esos marcadores serán sobrescritas.
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
# END WordPress