Mirror del Joomla antiguo: versionar los scripts y reponer los assets que faltaban
Los scripts del mirror (00-90) vivian solo en el disco. Van al repo; los datos que generan no (16 GB entre crawl, snapshot del origen y Joomla restaurado) -> .gitignore. Nuevo 91-repone-assets404.sh: repone los ficheros que el crawl no capturo porque se referencian SOLO desde CSS y el crawler seguia enlaces HTML (system.css, los fondos de fe_adulta_1, ratingstars.gif de K2). Salian como 404 en los logs de nginx del Hetzner. Descarga por HTTP desde el Joomla local aislado, nunca del filesystem -- mismo principio que el crawl, para no arrastrar los .php comprometidos del #183 -- y escanea PHP embebido antes de copiar a site/. Resultado sobre las 286 rutas unicas con 404 del log: 196 repuestas y verificadas en produccion (196/196 en 200 tras el rsync), 82 que dan 301->404 tambien en el origen (ya estaban rotas en la web original) y 8 rutas basura /%22/... de HTML mal formado. Refs #180 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
# mirror-antiguo — mirror estático del Joomla legacy de feadulta
|
||||
|
||||
Construcción del mirror HTML read-only de `antiguo.feadulta.com` (issue
|
||||
[rafa/feadulta#180](https://gitea.feadulta.com/rafa/feadulta/issues/180), remediación de #183).
|
||||
|
||||
**Regla de diseño:** el mirror se genera **solo por HTTP**, nunca copiando el filesystem. Así es
|
||||
imposible arrastrar los `.php` comprometidos del incidente. Lo que se captura es lo que Joomla
|
||||
*renderiza*.
|
||||
|
||||
## Origen del crawl
|
||||
|
||||
No es producción: es el **Joomla legacy restaurado en local**.
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Contenedor | `joomla-mirror-web` (`php:7.4-apache`), red `joomla-migration_joomla-net`, IP `172.20.0.5` |
|
||||
| Acceso | `http://127.0.0.1:8086` o `http://antiguo.feadulta.com` (entrada en `/etc/hosts` → 172.20.0.5) |
|
||||
| BD | `joomla_mirror` dentro del contenedor `joomla-mysql` |
|
||||
| Snapshot fuente | `source/antiguo-20260729.tar.gz` + `source/fejoomla3-20260729.sql.gz`, hashes en `MANIFEST-source.sha256` |
|
||||
|
||||
⚠️ La imagen base necesitó `mysqli`, `pdo_mysql`, `gd`, `zip` y `mod_rewrite` instalados en caliente:
|
||||
**se pierden si el contenedor se recrea**, no si solo se para/arranca. Para cambiar memoria o política
|
||||
de reinicio usar `docker update`, nunca `docker rm` + `docker run`.
|
||||
|
||||
⚠️ WSL2 se apaga cuando no queda ninguna sesión abierta desde Windows, y al apagarse para los
|
||||
contenedores. Antes de un proceso de horas, dejar un proceso ancla vivo en WSL.
|
||||
|
||||
## Datos del sitio
|
||||
|
||||
- SEF: `sef=1`, `sef_rewrite=1`, `sef_suffix=1` → las URLs terminan en `.html`.
|
||||
- Un solo idioma de contenido publicado: `es-ES` (sef `es`); todo el contenido es `language='*'`.
|
||||
El sitio hace **301 de `/x` → `/es/x`**, así que el inventario se genera ya con `/es/`.
|
||||
- Solo 2 categorías K2 y un único ítem de menú de K2: `buscadoravanzado` (Itemid 138).
|
||||
Las URLs de ítem son `/es/buscadoravanzado/item/<id>-<alias>.html`.
|
||||
- 16.269 ítems K2 publicados · 9.079 artículos com_content · 216 ítems de menú · 68 categorías.
|
||||
|
||||
## Método
|
||||
|
||||
El inventario **no se reconstruye a mano**: lo genera el propio router de Joomla. `_genurls.php`
|
||||
(en la raíz del sitio restaurado) arranca el framework por HTTP y llama a `JRoute::_()` y
|
||||
`K2HelperRoute::getItemRoute()`, así que las URLs son idénticas a las que el sitio imprime.
|
||||
|
||||
Cuatro pases, todos acotados por listas — **nunca por recursión libre** (ver post-mortem del
|
||||
2026-07-29 en #180 comment-497):
|
||||
|
||||
| Pase | Qué captura | Script |
|
||||
|---|---|---|
|
||||
| A | Las 25.437 URLs del inventario | `21-crawl-html.sh` |
|
||||
| B | Recursos (css/js/img/mp3/pdf) referenciados por el HTML capturado | `30-extract-links.py` + `31-fetch-assets.sh` |
|
||||
| C | Huecos: rutas de menú alternativas, páginas de autor de K2, `/anterior`, `/ediciones` | `43-pendientes.sh` |
|
||||
| D | `/anterior`, la web estática anterior a Joomla (HTML plano, recursión finita) | `37-pase-d-anterior.sh` |
|
||||
|
||||
`raw/` es **inmutable**. `site/` es el derivado servible (`45-normalize-links.py`).
|
||||
|
||||
## Trampas encontradas (y cómo se resuelven)
|
||||
|
||||
1. **Paginación de K2**: los enlaces acumulan `&start=` en vez de reemplazarlo → espacio de URLs
|
||||
infinito. Es lo que tumbó la VM el 29-jul. Se evita capturando por inventario, y el
|
||||
`--reject-regex` incluye `start|limitstart|limit|print|tmpl|format|searchword|task|orderby|filter`.
|
||||
2. **Alias con `?` literal**: ~198 artículos tienen el signo de interrogación dentro del alias
|
||||
(`...-dios-nos-ama?.html`). Para cualquier cliente HTTP eso es el separador de query, así que la
|
||||
ruta real es la parte anterior al `?` y wget guarda un fichero **sin extensión**. Es correcto para
|
||||
servirlo estáticamente, pero nginx necesita `default_type text/html` en esa ubicación o el
|
||||
navegador se lo descargará en vez de mostrarlo.
|
||||
3. **Assets con cache-busting** (`core.js?a32fb…`): wget mete la query en el nombre del fichero. El
|
||||
paso de normalización deja también una copia con el nombre limpio, que es la que pedirá el
|
||||
servidor estático.
|
||||
4. **Menús cuyo componente ya no existe** (`com_surveys`, `com_breezingforms`): `JRoute` no les
|
||||
construye ruta y devuelven 404. Ya son 404 en producción; para el resto de ítems de menú la ruta
|
||||
autoritativa es la columna `path` de `#__menu` (`41-menu-paths.sh`).
|
||||
|
||||
## Scripts
|
||||
|
||||
Numerados por orden de ejecución en `scripts/`. `23-estado.sh` da el estado en cualquier momento;
|
||||
`22-monitor.sh` vigila el crawl y **lo aborta** si el servidor pasa de 100 respuestas 500 o si la RAM
|
||||
libre baja de 800 MB. `60-restaurar-entorno.sh` rearranca los contenedores parados durante el crawl.
|
||||
Reference in New Issue
Block a user