feat(404): página custom con SSI de cPanel + htaccess con Options +Includes
- 404.shtml duplicado de 404.html con SSI embedded (REQUEST_URI, REMOTE_ADDR, HTTP_USER_AGENT, etc.) - .htaccess actualizado: ErrorDocument 404 /404.shtml, Options +Includes, AddHandler server-parsed - cPanel deshabilita Includes por default en cada VirtualHost, hay que activarlo en el .htaccess del usuario - Verificado online: SSI procesa correctamente, URL/UA/IP visibles en la página
This commit is contained in:
parent
ae56e43bb6
commit
db6668793e
@ -20,6 +20,12 @@ cp /root/opencode/development/hostingdelsur.net/src/forms/api-htaccess "$DIST/ap
|
||||
# Copy root .htaccess (HTTPS forzado, security headers)
|
||||
cp /root/opencode/development/hostingdelsur.net/scripts/htaccess.conf "$DIST/.htaccess"
|
||||
|
||||
# cPanel recognizes 404.shtml specifically (Server-Side Includes)
|
||||
# Astro generates 404.html — duplicate as .shtml for cPanel
|
||||
if [ -f "$DIST/404.html" ]; then
|
||||
cp "$DIST/404.html" "$DIST/404.shtml"
|
||||
fi
|
||||
|
||||
# rsync with --delete to mirror (preserva mwp/, .well-known/, etc.)
|
||||
rsync -avz --delete \
|
||||
--exclude='mwp' \
|
||||
|
||||
@ -57,4 +57,15 @@
|
||||
</FilesMatch>
|
||||
|
||||
# No listado de directorios
|
||||
Options -Indexes
|
||||
Options -Indexes +Includes
|
||||
|
||||
# Páginas de error custom
|
||||
ErrorDocument 404 /404.shtml
|
||||
ErrorDocument 500 /500.shtml
|
||||
|
||||
# Habilitar SSI para .shtml (cPanel lo desactiva por default)
|
||||
AddType text/html .shtml
|
||||
AddHandler server-parsed .shtml
|
||||
<IfModule mod_include.c>
|
||||
Options +Includes
|
||||
</IfModule>
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
---
|
||||
import BaseLayout from '@/layouts/BaseLayout.astro';
|
||||
import CloudDivider from '@/components/CloudDivider.astro';
|
||||
---
|
||||
<BaseLayout
|
||||
title="404 — Ups, el server se fue a buscar yerba"
|
||||
description="La página que buscás no existe. Pero tenemos un robot tomando mate para hacerte compañía."
|
||||
description="La página que buscás no existe, pero tenemos un robot tomando mate para hacerte compañía."
|
||||
>
|
||||
<section class="relative overflow-hidden py-16 md:py-24 min-h-[80vh] flex items-center" style="background: var(--hds-bg-soft);">
|
||||
<div class="absolute inset-0 particle-grid opacity-40" aria-hidden="true"></div>
|
||||
@ -28,10 +27,8 @@ import CloudDivider from '@/components/CloudDivider.astro';
|
||||
</filter>
|
||||
</defs>
|
||||
|
||||
<!-- Fondo circular -->
|
||||
<circle cx="240" cy="240" r="220" fill="url(#bg-grad)"/>
|
||||
|
||||
<!-- Patrón de cuadraditos naranja (estilo logo) alrededor -->
|
||||
<g opacity="0.35">
|
||||
<rect x="60" y="80" width="8" height="8" fill="#FA9F5C" rx="1"/>
|
||||
<rect x="68" y="80" width="8" height="8" fill="#FA9F5C" rx="1"/>
|
||||
@ -48,65 +45,49 @@ import CloudDivider from '@/components/CloudDivider.astro';
|
||||
<rect x="412" y="388" width="8" height="8" fill="#FFCBA1" rx="1"/>
|
||||
</g>
|
||||
|
||||
<!-- Sombra del robot -->
|
||||
<ellipse cx="240" cy="420" rx="100" ry="10" fill="#EE7623" opacity="0.12"/>
|
||||
|
||||
<!-- Cuerpo (pecho) -->
|
||||
<g filter="url(#soft-shadow)">
|
||||
<rect x="160" y="240" width="160" height="140" rx="20" fill="#E8E2D5" stroke="#EE7623" stroke-width="3"/>
|
||||
<!-- Detalle del pecho (LED) -->
|
||||
<circle cx="200" cy="280" r="6" fill="#EE7623">
|
||||
<animate attributeName="opacity" values="1;0.3;1" dur="1.8s" repeatCount="indefinite"/>
|
||||
</circle>
|
||||
<circle cx="200" cy="280" r="6" fill="#EE7623" opacity="0.3"/>
|
||||
<rect x="220" y="276" width="80" height="8" rx="2" fill="#1A1612" opacity="0.15"/>
|
||||
<rect x="220" y="290" width="60" height="6" rx="2" fill="#1A1612" opacity="0.1"/>
|
||||
<!-- Botón de pánico -->
|
||||
<circle cx="280" cy="340" r="14" fill="#FAF6EE" stroke="#EE7623" stroke-width="2"/>
|
||||
<circle cx="280" cy="340" r="6" fill="#EE7623"/>
|
||||
</g>
|
||||
|
||||
<!-- Cabeza -->
|
||||
<g filter="url(#soft-shadow)">
|
||||
<rect x="170" y="100" width="140" height="140" rx="24" fill="#F5EFE3" stroke="#EE7623" stroke-width="3"/>
|
||||
</g>
|
||||
|
||||
<!-- Antena -->
|
||||
<line x1="240" y1="100" x2="240" y2="68" stroke="#EE7623" stroke-width="4" stroke-linecap="round"/>
|
||||
<circle cx="240" cy="60" r="8" fill="#EE7623">
|
||||
<animate attributeName="r" values="6;9;6" dur="2s" repeatCount="indefinite"/>
|
||||
</circle>
|
||||
|
||||
<!-- Ojos (cierra uno como diciendo "uy") -->
|
||||
<g>
|
||||
<!-- Ojo izquierdo: cerrado/apretado (guiño de "uy") -->
|
||||
<path d="M 200 165 Q 210 172 220 165" stroke="#1A1612" stroke-width="4" fill="none" stroke-linecap="round"/>
|
||||
<line x1="195" y1="158" x2="225" y2="155" stroke="#1A1612" stroke-width="2" stroke-linecap="round" opacity="0.5"/>
|
||||
<!-- Pestaña del ojo cerrado -->
|
||||
<path d="M 195 158 Q 210 168 225 158" stroke="#1A1612" stroke-width="3" fill="none" stroke-linecap="round"/>
|
||||
|
||||
<!-- Ojo derecho: abierto y mirando de reojo (culpable) -->
|
||||
<ellipse cx="260" cy="167" rx="10" ry="12" fill="#FAF6EE" stroke="#1A1612" stroke-width="2"/>
|
||||
<circle cx="263" cy="170" r="5" fill="#1A1612"/>
|
||||
<circle cx="264" cy="167" r="2" fill="#FAF6EE"/>
|
||||
</g>
|
||||
|
||||
<!-- Mejillas rosadas (apenas sonrojado) -->
|
||||
<ellipse cx="190" cy="195" rx="8" ry="4" fill="#FA9F5C" opacity="0.6"/>
|
||||
<ellipse cx="290" cy="195" rx="8" ry="4" fill="#FA9F5C" opacity="0.6"/>
|
||||
|
||||
<!-- Boca: "Oops" -->
|
||||
<ellipse cx="240" cy="210" rx="14" ry="10" fill="#1A1612"/>
|
||||
<ellipse cx="240" cy="212" rx="10" ry="6" fill="#FAF6EE"/>
|
||||
<line x1="240" y1="205" x2="240" y2="218" stroke="#1A1612" stroke-width="1.5" opacity="0.3"/>
|
||||
|
||||
<!-- Brazos -->
|
||||
<g filter="url(#soft-shadow)">
|
||||
<!-- Brazo izquierdo: en gesto "ups" (mano levantada, como diciendo "yo no fui") -->
|
||||
<rect x="120" y="180" width="24" height="80" rx="12" fill="#F5EFE3" stroke="#EE7623" stroke-width="3" transform="rotate(-25 132 220)"/>
|
||||
<!-- Mano izquierda abierta -->
|
||||
<circle cx="110" cy="170" r="18" fill="#F5EFE3" stroke="#EE7623" stroke-width="3"/>
|
||||
<!-- Dedos abiertos -->
|
||||
<line x1="92" y1="160" x2="86" y2="152" stroke="#EE7623" stroke-width="3" stroke-linecap="round"/>
|
||||
<line x1="98" y1="155" x2="94" y2="145" stroke="#EE7623" stroke-width="3" stroke-linecap="round"/>
|
||||
<line x1="106" y1="153" x2="104" y2="142" stroke="#EE7623" stroke-width="3" stroke-linecap="round"/>
|
||||
@ -114,34 +95,24 @@ import CloudDivider from '@/components/CloudDivider.astro';
|
||||
<line x1="120" y1="162" x2="124" y2="155" stroke="#EE7623" stroke-width="3" stroke-linecap="round"/>
|
||||
</g>
|
||||
|
||||
<!-- Brazo derecho: sosteniendo el mate -->
|
||||
<g filter="url(#soft-shadow)">
|
||||
<rect x="336" y="220" width="24" height="80" rx="12" fill="#F5EFE3" stroke="#EE7623" stroke-width="3" transform="rotate(30 348 260)"/>
|
||||
<!-- Mano -->
|
||||
<circle cx="358" cy="290" r="16" fill="#F5EFE3" stroke="#EE7623" stroke-width="3"/>
|
||||
</g>
|
||||
|
||||
<!-- MATE (en la mano derecha) -->
|
||||
<g transform="translate(330 280)">
|
||||
<!-- Cuerpo del mate (calabaza) -->
|
||||
<ellipse cx="22" cy="28" rx="24" ry="20" fill="#1A1612"/>
|
||||
<!-- Brillo del mate -->
|
||||
<ellipse cx="14" cy="22" rx="6" ry="4" fill="#FAF6EE" opacity="0.2"/>
|
||||
<!-- Borde superior (donde va la yerba) -->
|
||||
<ellipse cx="22" cy="14" rx="20" ry="5" fill="#EE7623"/>
|
||||
<ellipse cx="22" cy="13" rx="18" ry="3" fill="#FFCBA1"/>
|
||||
<!-- Bombilla (pico) -->
|
||||
<rect x="35" y="6" width="8" height="14" rx="2" fill="#8A8580"/>
|
||||
<rect x="36" y="2" width="6" height="6" rx="1" fill="#C8C2B8"/>
|
||||
<!-- Capa de yerba encima -->
|
||||
<ellipse cx="22" cy="11" rx="14" ry="2" fill="#2E7D5B" opacity="0.8"/>
|
||||
</g>
|
||||
|
||||
<!-- Vapor del mate animado -->
|
||||
<g opacity="0.4">
|
||||
<path d="M 380 270 Q 384 262 380 254" stroke="#8A8580" stroke-width="2" fill="none" stroke-linecap="round">
|
||||
<animate attributeName="opacity" values="0;0.6;0" dur="2.5s" repeatCount="indefinite"/>
|
||||
<animate attributeName="transform" values="translateY(0); translateY(-10px); translateY(0)" dur="2.5s" repeatCount="indefinite"/>
|
||||
</path>
|
||||
<path d="M 392 270 Q 396 262 392 254" stroke="#8A8580" stroke-width="2" fill="none" stroke-linecap="round">
|
||||
<animate attributeName="opacity" values="0;0.6;0" dur="2.5s" begin="0.5s" repeatCount="indefinite"/>
|
||||
@ -151,18 +122,15 @@ import CloudDivider from '@/components/CloudDivider.astro';
|
||||
</path>
|
||||
</g>
|
||||
|
||||
<!-- Piernas -->
|
||||
<g filter="url(#soft-shadow)">
|
||||
<rect x="195" y="380" width="30" height="50" rx="10" fill="#F5EFE3" stroke="#EE7623" stroke-width="3"/>
|
||||
<rect x="255" y="380" width="30" height="50" rx="10" fill="#F5EFE3" stroke="#EE7623" stroke-width="3"/>
|
||||
<!-- Pies -->
|
||||
<ellipse cx="210" cy="432" rx="22" ry="8" fill="#EE7623"/>
|
||||
<ellipse cx="270" cy="432" rx="22" ry="8" fill="#EE7623"/>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<!-- Texto -->
|
||||
<div class="order-1 lg:order-2 text-center lg:text-left">
|
||||
<div class="inline-block">
|
||||
<span class="inline-flex items-center gap-3 text-xs font-semibold tracking-[0.25em] uppercase" style="color: var(--color-hds-naranja);">
|
||||
@ -190,11 +158,36 @@ import CloudDivider from '@/components/CloudDivider.astro';
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="mt-10 pt-6 border-t flex flex-wrap items-center justify-center lg:justify-start gap-x-6 gap-y-2 text-sm" style="border-color: var(--hds-line); color: var(--hds-fg-muted);">
|
||||
<a href="/servicios/" class="hover:text-hds-naranja transition-colors">Ver servicios</a>
|
||||
<a href="/planes/" class="hover:text-hds-naranja transition-colors">Ver planes</a>
|
||||
<a href="/contacto/" class="hover:text-hds-naranja transition-colors">Contacto</a>
|
||||
<!-- Server-side include (SSI) — cPanel pone el HTML y Apache lo procesa -->
|
||||
<!--#if expr="$REMOTE_ADDR" -->
|
||||
<div class="mt-10 pt-6 border-t" style="border-color: var(--hds-line);">
|
||||
<p class="text-xs font-semibold tracking-[0.2em] uppercase mb-3" style="color: var(--color-hds-naranja);">
|
||||
Detalles técnicos
|
||||
</p>
|
||||
<dl class="text-xs space-y-1.5" style="color: var(--hds-fg-muted); font-family: ui-monospace, monospace;">
|
||||
<div class="flex gap-2">
|
||||
<dt class="w-32 flex-shrink-0" style="color: var(--hds-fg-soft);">URL solicitada:</dt>
|
||||
<dd class="break-all"><!--#echo var="REQUEST_URI" --></dd>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<dt class="w-32 flex-shrink-0" style="color: var(--hds-fg-soft);">URL de referencia:</dt>
|
||||
<dd class="break-all"><!--#echo var="HTTP_REFERER" --></dd>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<dt class="w-32 flex-shrink-0" style="color: var(--hds-fg-soft);">IP del visitante:</dt>
|
||||
<dd><!--#echo var="REMOTE_ADDR" --></dd>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<dt class="w-32 flex-shrink-0" style="color: var(--hds-fg-soft);">Navegador:</dt>
|
||||
<dd class="break-all"><!--#echo var="HTTP_USER_AGENT" --></dd>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<dt class="w-32 flex-shrink-0" style="color: var(--hds-fg-soft);">Servidor:</dt>
|
||||
<dd><!--#echo var="SERVER_NAME" --></dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
<!--#endif -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user