# Servelts y JSP

# Códigos de Estado HTTP

1. Introducción
2. Especificar Códigos de Estado
3. Códigos de Estado HTTP 1.1 y sus Significados
4. Ejemplo: Motor de Búsqueda

## 1. Introducción

Cuando un servidor Web responde a una petición de un navegador u otro cliente Web, la respuesta consiste típicamente en una línea de estado, algunas cabeceras de respuesta, una línea en blanco, y el documento. Aquí tenemos un ejemplo mínimo:

>      HTTP/1.1 200 OK
>     Content-Type: text/plain

>     Hello World

La línea de estado consiste en la versión HTTP, y un entero que se interpreta como código de estado, y un mensaje muy corto que corresponde con el código de estado. En la mayoría de los casos, todas las cabeceras son opcionales excepto Content-Type, que especifica el tipo MIME del documento que sigue. Aunque muchas respuestas contienen un documento, algunas no lo tienen. Por ejemplo, las respuestas a peticiones HEAD nunca deberían incluir un documento, y hay una gran variedad de códigos de estado que esencialmente indican fallos, y o no incluyen un documento o sólo incluyen un pequeño "mensaje de error de documento".

Los servlets pueden realizar una variedad de tareas manipulando la línea de estado y las cabeceras de respuesta. Por ejemplo, reenviar al usuario a otros sites; indicar que el documento adjunto es una imagen, un fichero Acrobat, o (más comunmente) un fichero HTML; decirle al usuario que se requiere una password para acceder al documento; etc. Esta sección explica varios códigos de estados diferentes y como se pueden conseguir, mientras que la página siguiente describe la cabeceras de respuesta.

## 2. Especificar Códigos de Estado

Como se describe arriba, la línea de estado de respuesta HTPP consiste en una versión HTTP, un código de estado, y un mensaje asociado. Como el mensaje está asociado directamente con el código de estado y la versión HTTP está determinada por el servidor, todo lo que servidor tiene que hacer es seleccionar el código de estado. La forma de hacer esto es mediante el método setStatus de HttpServletResponse. El método setStatus toma un int (el código de estado) como argumento, pero en vez de usar los número explícitamente, es más claro y legible usar las constantes definidas en HttpServletResponse. El nombre de cada constante está derivado del mensaje estándard HTTP 1.1 para cada constante, todo en mayúsculas con un prefijo SC (por Status Code) y los espacios se cambian por subrayados. Así, como el mensaje para 404 es Not Found, la constante equivalente en HttpServletResponse es SC_NOT_FOUND. Sin embargo, hay dos excepciones. Por alguna razón oculta la constante para el código 302 se deriva del mensaje HTTP 1.0, no de HTTP 1.1, y la constante para el código 307 no existe tampoco.

Seleccionar el código de estado no siempre signifia que no necesitemos devolver un documento. Por ejemplo, aunque la mayoría de los servidores generarán un pequeño mensaje "File Not Found" para respuestas 404, un servlet podría querer personalizar esta respuesta. Sin embargo, si hacemos esto, necesitamos estar seguros de llamar a response.setStatus antes de enviar el contenido mediante PrintWriter.

Aunque el método general de selección del código de estado es simplemente llamar a response.setStatus(int), hay dos casos comunes para los que se proporciona un método atajo en HttpServletResponse. El método sendError genera un respuesta 404 junto con un mensaje corto formateado dentro de un documento HTML. Y el método sendRedirect genera una respuesta 302 junto con una cabecera Location indicando la URL del nuevo documento.

## 3. Códigos de Estado HTTP 1.1 y sus Significados

Aquí hay una lista de todas los códigos de estado disponibles en HTTP 1.1 junto con sus mensajes asociados y su interpretación. Deberíamos ser cuidadosos al utilizar los códigos de estado que están disponibles sólo en HTTP 1.1, ya que muchos navegadores sólo soportan HTTP 1.0. Si tenemos que usar códigos de estado específicos para HTTP 1.1, en la mayoría de los casos querremos chequear explícitamente la versión HTTP de la petición (mediante el método getProtocol de HttpServletRequest) o reservarlo para situaciones donde no importe el significado de la cabecera HTTP 1.0.

Código de Estado | Mensaje Asociado | Significado
--- | --- | ---
100 | Continue | Continúa con petición parcial (nuevo en HTTP 1.1)
101 | Switching Protocols | El servidor cumplirá con la cabecera Upgrade y cambiará a un protocolo diferente. (Nuevo en HTTP 1.1)
200 | OK | Todo está bien; los documentos seguidos por peticiones GET y POST. Esto es por defecto para los Servlets, si no usamos setStatus, obtendremos esto.
201 | Created | El servidor creo un documento; la cabecera Location indica la URL.
202 | Accepted | La petición se está realizando, el proceso no se ha completado.
203 | Non-Authoritative Information | El documento está siendo devuelto normalmente, pero algunas cabeceras de respuesta podrían ser incorrectas porque se está usando una copia del documento (Nuevo en HTTP 1.1)
204 | No Content | No hay un documento nuevo; el navegador contínua mostrando el documento anterior. Esto es útil si el usuario recarga periódicamente una página y podemos determinar que la página anterior ya está actualizada. Sin embargo, esto no funciona para páginas que se recargan automáticamente mediante cabeceras de respuesta Refresh o su equivalente <META HTTP-EQUIV="Refresh" ...>,ya que al devolver este código de estado se pararán futuras recargas.
205 | Reset Content | No hay documento nuevo, pero el navegador debería resetear el documento. Usado para forzar al navegador a borrar los contenidos de los campos de un formulario CGI (Nuevo en HTTP 1.1)
206 | Partial Content | El cliente envía una petición parcial con una cabecera Range, y el servidor la ha completado. (Nuevo en HTTP 1.1)
300 | Multiple Choices | El documento pedido se puede encontrar en varios sitios; serán listados en el documento devuelto. Si el servidor tiene una opción preferida, debería listarse en la cabecera de respuesta Location .
301 | Moved Permanently | El documento pedido está en algún lugar, y la URL se da en la cabecera de respuesta Location. Los navegadores deberían seguir automáticamente el enlace a la nueva URL.
302 | Found | Similar a 301, excepto que la nueva URL debería ser interpretada como reemplazada temporalmente, no permanentemente. Observa: el mensaje era "Moved Temporarily" en HTTP 1.0, y la constante en HttpServletResponse es SC_MOVED_TEMPORARILY, no SC_FOUND. Cabecera muy útil, ya que los navegadores siguen automáticamente el enlace a la nueva URL. Este código de estado es tan útil que hay un método especial para ella, sendRedirect. Usar response.sendRedirect(url) tiene unpar de ventajas sobre hacer response.setStatus(response.SC_MOVED_TEMPORARILY) y response.setHeader("Location", url). Primero, es más fácil. Segundo, con sendRedirect, el servlet automáticamente construye una página que contiene el enlace (para mostrar a los viejos navegadores que no siguen las redirecciones automáticamente). Finalmente, sendRedirect puede manejar URLs relativas, automáticamentes las traducen a absolutas. Observa que este código de estado es usado algunas veces de forma intercambiada con 301. Por ejemplo, si erróneamente pedimos http://host/~user (olvidando la última barra), algunos servidores enviarán 301 y otros 302. Técnicamente, se supone que los navegadores siguen automáticamente la redirección su la petición original era GET. Puedes ver la cabecera 307 para más detalles.
303 | See Other | Igual que 301/302, excepto que si la petición original era POST, el documento redirigido (dado en la cabecera Location) debería ser recuperado mediante GET. (Nuevo en HTTP 1.1)
304 | Not Modified | El cliente tiene un documento en el caché y realiza una petición condicional (normalmente suministrando una cabecera If-Modified-Since indicando que sólo quiere documentos más nuevos que la fecha especificada). El servidor quiere decirle al cliente que el viejo documento del caché todavía está en uso.
305 | Use Proxy | El documento pedido debería recuperarse mediante el proxy listado en la cabecera Location. (Nuevo en HTTP 1.1)
307 | Temporary Redirect | Es idéntica a 302 ("Found" o "Temporarily Moved"). Fue añádido a HTTP 1.1 ya que muchos navegadores siguen erróneamente la redirección de una respuesta 302 incluso si el mensaje original fue un POST, y sólo se debe seguir la redirección de una petición POST en respuestas 303. Esta respuesta es algo ambígua: sigue el redireccionamiento para peticiones GET y POST en el caso de respuestas 303, y en el caso de respuesta 307 sólo sigue la redirección de peticiones GET. Nota: por alguna razón no existe una constante en HttpServletResponse que corresponda con este código de estado. (Nuevo en HTTP 1.1)
400 | Bad Request | Mala Síntaxis de la petición.
401 | Unauthorized | El cliente intenta acceder a una página protegida por password sin las autorización apropiada. La respuesta debería incluir una cabecera WWW-Authenticate que el navegador debería usar para mostrar la caja de diálogo usuario/password, que viene de vuelta con la cabecera Authorization.
403 | Forbidden | El recurso no está disponible, si importar la autorización. Normalmente indica la falta permisos de fichero o directorios en el servidor.
404 | Not Found | No se pudo encontrar el recurso en esa dirección. Esta la respuesta estándard "no such page". Es tan cómún y útil esta respuesta que hay un método especial para ella en HttpServletResponse: sendError(message). La ventaja de sendError sobre setStatus es que, con sendErr, el servidor genera automáticamente una página que muestra un mensaje de error.
405 | Method Not Allowed | El método de la petición (GET, POST, HEAD, DELETE, PUT, TRACE, etc.) no estaba permitido para este recurso particular. (Nuevo en HTTP 1.1)
406 | Not Acceptable | El recurso indicado genera un tipo MIME incompatible con el especificado por el cliente mediante su cabecera Accept. (Nuevo en HTTP 1.1)
407 | Proxy Authentication Required | Similar a 401, pero el servidor proxy debería devolver una cabecera Proxy-Authenticate. (Nuevo en HTTP 1.1)
408 | Request Timeout | El cliente tarda demasiado en envíar la petición. (Nuevo en HTTP 1.1)
409 | Conflict | Usualmente asociado con peticiones PUT; usado para situaciones como la carga de una versión incorrecta de un fichero. (Nuevo en HTTP 1.1)
410 | Gone | El documento se ha ido; no se conoce la dirección de reenvio. Difiere de la 404 en que se sabe que el documento se ha ido permanentemente, no sólo está indisponible por alguna razón desconocida como con 404. (Nuevo en HTTP 1.1)
411 | Length Required | El servidor no puede procesar la petición a menos que el cliente envíe una cabecera Content-Length. (Nuevo en HTTP 1.1)
412 | Precondition Failed | Alguna condición prévia especificada en la petición era falsa (Nuevo en HTTP 1.1)
413 | Request Entity Too Large | El documento pedido es mayor que lo que el servidor quiere manejar ahora. Si el servidor cree que puede manejarlo más tarde, debería incluir una cabecera Retry-After. (Nuevo en HTTP 1.1)
414 | Request URI Too Long | La URI es demsiado larga. (Nuevo en HTTP 1.1)
415 | Unsupported Media Type | La petición está en un formato desconocido. (Nuevo en HTTP 1.1)
416 | Requested Range Not Satisfiable | El cliente incluyó una cabecera Range no satisfactoria en la petición. (Nuevo en HTTP 1.1)
417 | Expectation Failed | No se puede conseguir el valor de la cabecera Expect. (Nuevo en HTTP 1.1)
500 | Internal Server Error | Mensaje genérico "server is confused". Normalmente es el resultado de programas CGI o servlets que se quedan colgados o retornan cabeceras mal formateadas.
501 | Not Implemented | El servidor no soporta la funcionalidad de rellenar peticiones. Usado, por ejemplo, cuando el cliente envía comandos como PUT que el cliente no soporta.
502 | Bad Gateway | Usado por servidores que actúan como proxies o gateways; indica que el servidor inicial obtuvo una mala respuesta desde el servidor remoto.
503 | Service Unavailable | El servidor no puede responder debido a mentenimiento o sobrecarga. Por ejemplo, un servlet podría devolver esta cabecera si algún almacen de threads o de conexiones con bases de datos están llenos. El servidor puede suministrar una cabecera Retry-After.
504 | Gateway Timeout | Usado por servidores que actúan como proxies o gateways; indica que el servidor inicial no obtuvo una respuesta a tiempo del servidor remoto. (Nuevo en HTTP 1.1)
505 | HTTP Version Not Supported | El servidor no soporta la versión de HTTP indicada en la línea de petición. (Nuevo en HTTP 1.1)

## 4. Ejemplo: Motor de Búsqueda

Aquí tenemos un ejemplo que hace uso de los dos códigos de estado más comunes distintos de 200: 302 y 404. El código 302 se selecciona mediante el método sendRedirect, y 404 se selecciona mediante sendError.

En esta aplicación, primero un formulario HTML muestra una página que permite al usuario elegir una cadena de búsqueda, el número de los resultados por página, y el motor de búsqueda a utilizar. Cuando se envía el formulario, el servlet extrae estos tres parámetros, construye una URL con los parámetros embebidos en una forma apropiada para el motor de búsqueda seleccionado, y redirige al usuario a esa dirección. Si el usuario falla al elegir el motor de búsqueda o envía un nombre de motor de búsqueda no conocido, se devuelve una página de error 404 diciendo que no hay motor de búsqueda o que no se conoce.

### 4.1 SearchEngines.java (Descarga el código fuente)

Nota: hace uso de la clase SearchSpec, mostrada abajo, que incorpora información sobre como construir URLs para realizar búsquedas en varios buscadores.

>     package hall;

>     import java.io.*;
>     import javax.servlet.*;
>     import javax.servlet.http.*;
>     import java.net.*;

>     public class SearchEngines extends HttpServlet {
>       public void doGet(HttpServletRequest request,
>                         HttpServletResponse response)
>           throws ServletException, IOException {
>         // The URLEncoder changes spaces to "+" signs and other
>         // non-alphanumeric characters to "%XY", where XY is the
>         // hex value of the ASCII (or ISO Latin-1) character.
>         // The getParameter method decodes automatically, but since
>         // we're just passing this on to another server, we need to
>         // re-encode it.
>         String searchString =
>           URLEncoder.encode(request.getParameter("searchString"));
>         String numResults =
>           request.getParameter("numResults");
>         String searchEngine =
>           request.getParameter("searchEngine");
>         SearchSpec[] commonSpecs = SearchSpec.getCommonSpecs();
>         for(int i=0; i<commonSpecs.length; i++) {
>           SearchSpec searchSpec = commonSpecs[i];
>           if (searchSpec.getName().equals(searchEngine)) {
>             // encodeURL is just planning ahead in case this servlet
>             // is ever used in an application that does session tracking.
>             // If cookies are turned off, session tracking is usually
>             // accomplished by URL rewriting, so all URLs returned
>             // by servlets should be sent through encodeURL.
>             String url =
>               response.encodeURL(searchSpec.makeURL(searchString,
>                                                      numResults));
>             response.sendRedirect(url);
>             return;
>           }
>         }
>         response.sendError(response.SC_NOT_FOUND,
>                            "No recognized search engine specified.");
>       }

>       public void doPost(HttpServletRequest request,
>                          HttpServletResponse response)
>           throws ServletException, IOException {
>         doGet(request, response);
>       }
>     }

### 4.2 SearchSpec.java

>     package hall;

>     class SearchSpec {
>       private String name, baseURL, numResultsSuffix;

>       private static SearchSpec[] commonSpecs =
>         { new SearchSpec("google",
>                          "http://www.google.com/search?q=",
>                          "&num="),
>           new SearchSpec("infoseek",
>                          "http://infoseek.go.com/Titles?qt=",
>                          "&nh="),
>           new SearchSpec("lycos",
>                          "http://lycospro.lycos.com/cgi-bin/pursuit?query=",
>                          "&maxhits="),
>           new SearchSpec("hotbot",
>                          "http://www.hotbot.com/?MT=",
>                          "&DC=")
>         };

>       public SearchSpec(String name,
>                         String baseURL,
>                         String numResultsSuffix) {
>         this.name = name;
>         this.baseURL = baseURL;
>         this.numResultsSuffix = numResultsSuffix;
>       }

>       public String makeURL(String searchString, String numResults) {
>         return(baseURL + searchString + numResultsSuffix + numResults);
>       }

>       public String getName() {
>         return(name);
>       }

>       public static SearchSpec[] getCommonSpecs() {
>         return(commonSpecs);
>       }
>     }

### 4.3 SearchEngines.html

Pulsa con el botón derecho sobre el enlace al código fuente para descargar el fichero fuente.

>     <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
>     <HTML>
>     <HEAD>
>       <TITLE>Searching the Web</TITLE>
>     </HEAD>

>     <BODY BGCOLOR="#FDF5E6">
>     <H1 ALIGN="CENTER">Searching the Web</H1>

>     <FORM ACTION="/servlet/hall.SearchEngines">
>       <CENTER>
>         Search String:
>         <INPUT TYPE="TEXT" NAME="searchString"><BR>
>         Results to Show Per Page:
>         <INPUT TYPE="TEXT" NAME="numResults"
>                            VALUE=10 SIZE=3><BR>
>         <INPUT TYPE="RADIO" NAME="searchEngine"
>                             VALUE="google">
>         Google |
>         <INPUT TYPE="RADIO" NAME="searchEngine"
>                             VALUE="infoseek">
>         Infoseek |
>         <INPUT TYPE="RADIO" NAME="searchEngine"
>                             VALUE="lycos">
>         Lycos |
>         <INPUT TYPE="RADIO" NAME="searchEngine"
>                             VALUE="hotbot">
>         HotBot
>         <BR>
>         <INPUT TYPE="SUBMIT" VALUE="Search">
>       </CENTER>
>     </FORM>

>     </BODY>
>     </HTML>

### 4.4 Pantalla inicial

### 4.5 Resultados de la Busqueda

Ozito