Blog ElCodiguero
31 dic 2009 PHP

Páginas de error HTTP

Los errores HTTP se ven bastante seguido, pueden suceder en cualquier sitio, en cualquier momento. El sitio falla, alguien copia mal un enlace que le pasa a un amigo, alguien escribe mal la dirección a la que quiere ir. Incluso puede pasar que un motor de búsqueda tenga un enlace viejo en su índice.

Se podría decir que estos errores son inevitables, pero eso no es excusa para no saber manejarlos. Un estudio reciente concluyó que el 18% de las personas que ven una página de error 404 cree que se trata de un error debido a que el sitio está mal hecho. ¿Volverías a un sitio que consideras mal hecho si tuvieras una alternativa?

Es muy importante saber qué poner en una página de error, cómo tratar al visitante e intentar retenerlo, y cómo configurar el servidor para que muestre la página que uno quiere que se muestre, en vez de la fea página por defecto.

Hace poco se hizo un artículo sobre el tema en MaestrosdelWeb. En este artículo se mencionan algunas instrucciones a tener en cuenta para crear una página de error que sirva a los intereses del sitio. Es decir, ya que el error se produce y no lo podemos evitar, debemos intentar que la página de error sea útil al visitante que se la encuentra.

Pero el error 404 no es el único que existe (de hecho, en la mayoría de los casos y según la norma HTTP, debería usarse 410 y no 404) Hay otros errores comunes que pueden darse en casos de restricciones de páginas (403 Forbidden) o errores del servidor (500 Internal Server Error).

¿Cómo se hace para especificar una página diferente a la página por defecto?

La forma más sencilla en servidores Apache (la mayoría) es editar el archivo .htaccess ([punto]htaccess) de la raíz del sitio.

Este archivo puede ubicarse en cualquier carpeta, pero hay que tener en cuenta que las directivas que contenga solo se aplicarán a la carpeta que lo contiene, y a sus subcarpetas. Por lo tanto, si se cambian las páginas de error en un archivo .htaccess ubicado dentro de una carpeta cualquiera, solamente se estarán redirigiendo los errores que ocurran en archivos dentro de esa carpeta.

La forma de especificar una página “personalizada” para los errores es la siguiente:

ErrorDocument [código de error] [ruta absoluta a la página que se quiere usar]

Por ejemplo,

ErrorDocument 404 /error404.htmlErrorDocument 500 /error500.html

Puede usarse la misma página para todos los errores, aunque es recomendable especificar lo que sucedió: no es lo mismo un error temporal (la base de datos no está disponible, por ejemplo), que un error permanente como el 404. También es importante crear y lanzar errores que correspondan con el error real: un problema al conectar con la base de datos no provocará por si mismo un error 500 (“Error interno del servidor”) pero si encontramos y detectamos un problema como este, mostrar una página de error 500 puede ser lo apropiado, después de todo sí se produjo un error “interno”.

A la hora de personalizar las páginas de error no solo se pueden usar documentos estáticos, sino que se puede usar también un programa PHP (o en el lenguaje que sea). El servidor Apache pone a disposición de este programa las variables $\_SERVER['REDIRECT\_URI'] y $\_SERVER['REDIRECT\_STATUS'], que indican respectivamente la ruta que se envió y que causó el error, y el código del error que se produjo.

Por ejemplo, para generar el famoso

Error 404: No se pudo encontrar el archivo XXX en este sitio

Se podría hacer lo siguiente con PHP:

<?php
echo 'Error '.$_SERVER['REDIRECT_STATUS'].':No se pudo encontrar el archivo '.$_SERVER['REDIRECT_URI'].' en este sitio';

Según la documentación de Apache, también debe enviarse desde la página PHP al navegador una cabecera HTTP indicando el error, para asegurar que el navegador “se entere” de lo que realmente sucedió. Esto también se menciona en la página del manual de header(), que es la función de PHP que realiza el trabajo de enviar cabeceras HTTP al navegador.

Hay que tener en cuenta un detalle más: PHP puede funcionar en el servidor como módulo de Apache o como CGI. La información de cómo está funcionando PHP puede obtenerse ejecutando la función phpinfo(), y viendo la salida de “Server API“. Si pone “CGI“, PHP está funcionando como CGI, mientras que si pone “Apache Handler“, PHP está funcionando como módulo de Apache.

Debido a un pequeño fallo de PHP, estas 2 formas de funcionamiento tienen comportamientos ligeramente diferentes. En el caso de que PHP funcione como CGI, la cabecera a enviar es:

<?php
header( 'Status: 404 Not Found' );

mientras que si es módulo:

<?php
header( 'HTTP/1.0 404 Not Found' );

Como se ve, la diferencia está en que una versión usa Status: mientras que la otra usa HTTP/1.0 (o HTTP/1.1, con algunas diferencias). Esta diferencia no solamente se da con el error 404, sino también con el resto de los errores HTTP.

Parámetros de header()

La función header tiene 2 parámetros opcionales, que pueden servir para evitar las diferencias de funcionamiento entre las versiones de PHP.

Según el manual oficial, la sintaxis de la función es

void header ( string $string [, bool $replace [, int $http_response_code ]] )

El primer parámetro, $string, es el que usamos siempre: una cadena con el contenido de la cabecera. El segundo, $replace, indica si la cabecera enviada con header() debe sustituir a otra cabecera previa con el mismo nombre. Y el tercero e interesante, $http\_response\_code, indica el código de respuesta HTTP que estará asociado a la cabecera enviada. Por lo que, según pude leer en las notas de usuario del manual de PHP, en vez de usar header como siempre, se puede evitar el problema de saber cómo se ejecuta PHP usando simplemente:

<?php
header(' ', true, 404);

Según la persona que escribió la nota, el primer parámetro de la función no debe ser una cadena vacía, de ahí el uso de un espacio. Y en mis pruebas, esto genera una cabecera de error perfectamente válida.

Vale la pena leer las notas del manual de PHP, muchas veces se encuentran cosas muy interesantes. Y vale la pena también pensar un poco fuera de lo normal para encontrar soluciones prácticas a los problemas de todos los días.

Enlaces relacionados

Activa Javascript para para cargar los comentarios, basados en DISQUS

El Blog de ElCodiguero funciona sobre Pelican

Inicio | Blog | Acerca de