REST
De Energía y Red
Introducción
La palabra REST es el acrónimo de 'Representational State Transfer' ('transferencia de la representación del estado'). El concepto fue introducido por Roy Fielding en el año 2000 en su famosa tesis doctoral 'Architectural Styles and the Design of Network-based Software Architectures' ('Estilos de arquitectura y diseño de arquitecturas de software basadas en red'), en la que analiza una serie de principios para utilizar la web como plataforma de computación distribuida.
El concepto es, hagamos que los ordenadores utilicen la web de la forma en la que esta fue ideada siguiendo un pequeño conjunto de reglas de diseño y todos saldremos ganando con ello. REST no es un protocolo concreto o un estándar, es una forma de pensar, las aplicaciones se diseñan pensando en accesos a recursos.
Características de las arquitecturas REST:
- Arquitectura cliente-servidor en la que los datos y la funcionalidad se consideran recursos. En esencia REST es una arquitectura orientada a recursos.
- Los recursos se identifican y pueden ser accedidos mediante URIs (Identificadores de Recursos Uniformes).
- La comunicación se hace aprovechando al máximo los mecanismos que ofrece el protocolo HTTP (protocolo de comunicación sin estado).
- Los mensajes intercambiados entre cliente y servidor son representaciones de recursos.
- Cada recurso pueden tener una o varias representaciones (variantes) que pueden ser variables en el tiempo (p.e. el nivel de un depósito)
- Los recursos pueden tratar invocaciones de métodos.
- Los servicios REST ofrecen una interfaz uniforme, todas las URIs de una aplicación REST ofrecen la misma interfaz, de forma similar al navegador web que independientemente de la URI introducida cuando solicita una página (representación de un recurso) utiliza el método HTTP GET para obtenerla.
- Las relaciones entre los recursos se resuelven mediante enlaces en las representaciones.
El estilo de arquitectura REST es óptimo para la creación, mantenimiento, obtención y borrado de recursos. Por recurso se entiende cualquier concepto de interés al que se quiere proporcionar acceso y que puede serializarse de alguna forma, por ejemplo una consulta a una base de datos, un archivo, el resultado de un cálculo, ...,esa forma serializada se denomina representación y son esas representaciones el contenido de los mensajes que se intercambian cliente el servidor.
Por ejemplo, si se quisiera modelizar un sistema de gestión de almacenamiento de libros con una arquitectura REST, los recursos podrían ser los libros. Para ver una representación de todos los libros del almacén se podría visitar la URL:
http://www.gruposp2p.org/almacenlibros/libros
Para ver una representación de todos los libros de historia se podría visitar la URL:
http://www.gruposp2p.org/almacenlibros/libros/historia
Para ver los libros de la cesta de compra:
http://www.gruposp2p.org/almacenlibros/cesta
Los recursos pueden tener formato XML, XHTML; JSON, binario, texto-plano ...
¿Debo utilizar REST ó SOAP?
Sobre esto se ha discutido mucho, REST es una tecnología que compite con SOAP como estrategia para la creación de aplicaciones distribuidas, lo ideal es utilizar la tecnología más apropiada al contexto en el que se quiera implantar la solución.
Argumentos que pueden ayudar a tomar una decisión en caso de duda:
- SOAP es apropiada para la invocación de comportamiento, mientras que REST lo es para la gestión de información.
- REST está mejor pensado que SOAP para ofrecer funcionalidad a través de cortafuegos.
- Los sistemas SOAP atan a un contrato sobre el cliente y el tipo de información que se desea intercambiar qué es difícil modificar sin afectar a los clientes del servicio.
- REST sobreutilizado puede hacer cosas que se pueden hacer con SOAP y viceversa.
Una de las ventajas de REST sobre SOAP radica en la flexibilidad que ofrece REST en el formato de los mensajes intercambiados frente al contrato extricto al que obliga SOAP. REST está abierto a poder ofrecer los contenidos en función de las necesidades del cliente concreto que invoca el servicio. Por ejemplo, para un API que tenga que interactuar con el motor JavaScript de un navegador es más apropiado intercambiar mensajes en formato JSON (JavaScript Object Notation) que mensajes en formato XML, jugando con los tipos MIME el servicio puede decidir cambiar el formato de las representaciones que envía.
Mapeado de los métodos HTTP
Los servicios web REST mapean los cuatro principales métodos HTTP a las operaciones que realiza sobre el recurso (crear, obtener, actualizar y borrar). Los desarrolladores deben tener en cuenta la semántica de cada método para determinar qué métodos son apropiados para cada recurso:
| Método HTTP | Operación realizada |
|---|---|
| GET | Obtener un recurso. Las invocaciones repetidas de GET debe ser seguras, lo único que deben devolver son representaciones de recursos. |
| POST | Al no tener semántica definida puede servir para crear recursos u operaciones diversas (invocar instrucciones que se aplican al estado de un recurso) |
| PUT | Actualizar/cambiar el estado de un recurso |
| DELETE | Borrar un recurso |
| HEAD | Metainformación del recurso |
| OPTIONS | Métodos soportados por el recurso |
GET, PUT y DELETE deben ser idempotentes (repetidas llamadas deben tener el mismo efecto que una sola llamada). POST no tiene por qué ser idempotente, si se cuentan con los privilegios adecuados las invocaciones pueden tener efectos colaterales, por ejemplo añadir nuevos recursos, invocar un comportamiento ... Para añadir un nuevo recurso el cliente puede invocar el método POST pasando los detalles del nuevo recurso y si la operación acaba con éxito se puede devolver en la respuesta la URI del recurso creado además de información contextual.
Las aplicaciones cliente esperan códigos de respuesta HTTP acorde al resultado de la operación (RFC 2616 www.w3.org/Protocols/rfc2616/rfc2616.html). Por ejemplo, un servicio podría tener estas características:
* GET: obtiene contenido en formato XML, devuelve 200 si la petición ha tenido éxito y 404 si no se ha encontrado el recurso. * POST: crea/actualiza contenidos, devuelve 201 (Creado) en caso de éxito y 200 si el recurso no se ha podido crear. * DELETE: borra contenido, devuelve 204 (Sin contenido) en caso de éxito y 400 (Mala petición) en caso de fallo.
Un recurso no tiene por qué soportar todos los métodos, para determinar qué métodos puede tratar un determinado recurso se puede invocar el método OPTIONS (siempre y cuando el proveedor del servicio haya decidido implementarlo). La respuesta contendrá un encabezado Allow con la lista de los métodos soportados. Si un recurso recibe una petición para un método que no soporta debería devolver un código de estado 405 ('método no permitido').
HTTP es eficiente en aplicaciones web debido a que los servidores están acostumbrados a cachear y distribuir peticiones. En determinadas circustancias pueden incluir información en sus encabezados. Una práctica aconsejable en los desarrollos consiste en devolver la fecha y hora del último cambio de un recurso en su encabezado 'Last-modified', el cliente puede enviar este mismo encabezado la próxima vez en el encabezado 'If-modified-since', el servidor puede entonces utilizar este encabezado para comprobar si el recurso ha sido modificado, si no hubiera sido modificado puede devolver un código de respuesta '304' que significa no modificado.
Descripción de los servicios
Los servicios REST no disponen de un contrato extricto como los servicios SOAP, el contracto existe, pero es de diferente naturaleza, es necesario saber lo que se busca y donde se busca.
La forma más común de publicación de servicios REST consiste en documentar todas las URIs de los recursos, todos los métodos HTTP soportados y las estructuras de las representaciones de los recursos (normalmente XML y JSON).
Los servicios REST no disponen de un lenguaje estandar para la descripción de servicios, algunas herramientas disponen de soporte para archivos WADL (el equivalente a los WSDL de SOAP).
Direccionamiento de recursos
Un recurso es una entidad que puede ser identificada o nombrada. En REST todo recurso debe tener al menos una dirección (URI) que pueda ser invocada. Una aplicación está compuesta de varias URIs (recursos) interrelacionadas entre si. Los desarrolladores de servicios REST deben dar nombres adecuados a los recursos y decidir la forma en la que el servidor redireccionará las peticiones de recursos recibidas.
En una aplicación REST debería bastar con pasar a los usuarios del API la URI de inicio de la aplicación para que, a partir de ella, pudiera extraer toda la información necesaria. Si la consulta se hace desde un navegador se podría devolver documentación HTML sobre cómo invocar el servicio, si se accede desde una librería como Restlet o Apache HTTP client, una representación XML de las opciones del próximo nivel. REST no impone ningún requerimiento estricto con respecto a los patrones que se deben seguir.
Por ejemplo, para la modelización de un sistema de gestión de libros la consulta recibida invocando la URI:
http://www.gruposp2p.org/almacenlibros/libros
Podría mapear a un servicio RESTful que interpreta la petición devolviendo, paginados, todos los libros disponibles en la base de datos. También se podría obtener un documento indicando las posibles clasificaciones de libros, o una descripción de cómo invocar la librería. El servicio puede ofrecer una respuesta en función del tipo de cliente que hace la petición.
Las URIs suelen diseñarse como rutas lógicas, cada paso en la ruta puede significar algo sobre un determinado recurso, al resolver la ruta en cada nivel se puede esperar algún tipo de información. Conforme se va avanzando en la ruta se va de una información más general a una más específica.
http://www.gruposp2p.org/almacenlibros/libros/historia/romana/13587951
Consejos útiles a la hora de diseñar URIs:
- Las URIs se deben crear a partir de nombres, no de verbos:
Mal - http://www.gruposp2p.org/almacenlibros/getLibro&id=12345677 Bien - http://www.gruposp2p.org/almacenlibros/libro/12345677
- No utilizar extensiones de archivo para especificar el tipo MIME solicitado:
Bien - http://www.gruposp2p.org/almacenlibros/libro/12345677 + tipo MIME Mal - http://www.gruposp2p.org/almacenlibros/libro/12345677.html Mal - http://www.gruposp2p.org/almacenlibros/libro/12345677.xml Mal - http://www.gruposp2p.org/almacenlibros/libro/12345677.json Mal - http://www.gruposp2p.org/almacenlibros/libro/12345677.png
- No utilizar las URIs como mecanismo para distribuir los contenidos en función del tipo de cliente (user agent):
Bien - http://www.gruposp2p.org/almacenlibros/libro/12345677 + user agent Mal - http://firefox.gruposp2p.org/almacenlibros/libro/12345677 Mal - http://www.gruposp2p.org/almacenlibros/libro/12345677 Mal - http://iphone.gruposp2p.org/almacenlibros/libro/12345677
- Utilizar el caracter de puntuación para separar datos en el mismo nivel y comas cuando importe el orden de los datos, por ejemplo a la hora de especificar la latitud y longitud de una coordenada:
/tierra/38.0,-99.2
- Usar punto y coma cuando no importe el orden de los parámetros
/libros/historia;arte
- Utilizar consultas con variables sólo para pasar argumentos a un algoritmo:
http://www.gruposp2p.org/karma/calculator?param1=12345677¶m2=987765¶m3=4546776
Hypermedia como motor del estado de la aplicación
Una de las restricciones más importantes de REST consiste en la utilización de hipermedia como motor del estado de la aplicación, los servicios REST no deben ser responsables de mantener el estado de conversación con el cliente, no existe el concepto de sesiones HTTP. El servicio se encarga de mantener los recursos y proporcionar una interfaz uniforme a los mismos, una reinicialización del servidor no debería afectar a los clientes. Donde sea necesario, el cliente será el responsable de gestionar la sesión.
La restricción hipermedia señala que los servidores se comunican con las aplicaciones cliente haciéndolas pasar por estados lógicos de conversación representados mediante hiperenlaces.
Las relaciones entre recursos se pueden representar con hiperenlaces, siempre que tenga sentido, deben mostrarse los hiperenlaces con los recursos relacionados.
Una ayuda para implementar la restricción hipermedia en un sistema puede consistir en pensar en los servicios con un único punto de entrada. De esa forma si se quiere permitir que las aplicaciones cliente puedan acceder desde ahí a otros recursos hay que decidir las URIs que se le deben proporcionar. Esta es la forma en la que esta gestionada la navegación interactiva en muchos sitios web.
Los diseñadores de servicios deben elegir los tipos MIME más apropiados para sus recursos y clientes, deben asegurarse que las implementaciones de servicios devuelvan el código de estado HTTP 406 ("no aceptable") siempre que un cliente solicite un tipo MIME no soportado.
Relaciones entre recursos
Para describir las relaciones entre recursos se pueden utilizar elementos 'link' similares a los utilizados en el protocolo Atom. Por ejemplo:
<link href="http://www.gruposp2p.org/usuario/1233454/depositos" rel="http://schemas.gruposp2p.org/deposito" title="depositos"/>
Donde:
- El atributo href contiene la URL del recurso enlazado.
- El atributo rel indica el tipo de relación que existe entre los recursos.
- El atributo title es una etiqueta de la relación
Etiquetas HTTP de entidad (ETags)
Este tipo de etiquetas se devuelven en los encabezados HTTP de las respuestas y se denominan ETags.
El valor de la etiqueta ETag indica el estado del recurso asociado haciendo posible el cacheado y el control de concurrencia del mismo.
Para usar ETags como mecanismo de control de cache se tiene que hacer una consulta al servidor para ver si el recurso previamente enviado coincide con el que se encuentra en ese momento en le servidor. Para ello se incluye un encabezado 'If-None-Match' y se le pasa el valor ETag previamente recibido:
If-None-Match: "valor_de_la_etiqueta_etag"
Si la etiqueta tuviera el valor '2342542' quedaría
If-None-Match: "2342542"
Si el valor de la etiqueta coincide con el valor de la etiqueta del servidor se obtiene un código de respuesta HTTP 304 (No modificado), si no coincide el servidor devolverá el recurso solicitado con la nueva etiqueta ETag.
También se pueden utilizar las etiquetas ETags para el control de concurrencia sobre recursos que soportan peticiones POST y PUT incluyendo el encabezado 'If-Match' y pasándole el valor ETag de la anterior respuesta:
If-Match: "valor_de_la_etiqueta_etag"
Al recibir la petición el servidor comprueba si el valor de la etiqueta coincide con la que tiene el recurso, si coinciden acepta la petición, si no coinciden envía un código de respuesta HTTP 412 (Precondición fallida).
Autenticación
En aplicaciones REST es preferible la autentificación HTTP antes que la basada en cookies o en reescritura de URL por varias razones:
- Es más segura en caso de no disponer SSL. Los servidores disponen de mecanismos para proteger recursos (ver sección 4.5 de la RFC2617).
- Puede prescindirse totálmente de la sesión, en el caso de un sitio web mantenido por varios servidores no es necesario que compartan sesión si se utiliza 'Basic'.
- Simplifica el cacheado de la aplicación, los recursos no auténticados se cachean con normalidad, los autenticados no se cachean.
- El servidor puede informar sobre los pasos a seguir para obtener las credenciales enviando información en sus respuestas 401.
Código en el cliente:
final Client client = new Client(Protocol.HTTP);
Request request = new Request(Method.GET,
“http://localhost:8888/ping”);
request.setChallengeResponse(new ChallengeResponse(
ChallengeScheme.HTTP_BASIC, “scott”, “tiger”
.toCharArray()));
client.handle(request, new Callback() {
@Override
public void onEvent(Request request, Response response) {
button.setText(response.getEntity().getText());
}
});
Autentificación HTTP
Preemptive HTTP authentication
Las credenciales se proporcionan al principio en vez de responder a un mensaje 401 Respuesta no autorizada. Se puede encontrar una posible aproximación tocando en encabezado de autentificación HTTP usando codificación Base64 en el capítulo 17 del código fuente AndTutorials (el autor recomienda usar URLConnection para este tipo de autentificación, es lo que usa JTwitter JAR).
¿Cómo saber si un servicio es REST?
Para saber el grado con el que un servicio puede considerarse REST se pueden analizar los siguientes puntos:
- ¿Las URIs identifican recursos u operaciones?
- ¿Se utilizan las operaciones HTTP - GET, PUT, POST y DELETE de acuerdo a su nombre?
- ¿Se utiliza hipermedia, esto es, hay enlaces que un cliente pueda seguir en las representaciones?
- ¿Se utilizan MIME types para diferenciar tipos de datos en las representaciones?
- ¿Se utiliza el cacheado y el GET condicional haciendo uso de encabezados de control y ETags?
Servicios REST con Java
Jersey
El proyecto Jersey es la implementación de fuente abierta de referencia de la JSR 311 - API Java para servicios web REST (JAX-RS). JAX-RS proporciona un API para la construcción de servicios web REST. El API consiste en una serie de anotaciones, interfaces y clases asociadas. Aplicando las anotaciones a POJOs (Plain Old Java Objects) se pueden exponer servicios REST.
RESTLET
Framework Java que sirve para implementar sistemas con arquitecturas REST capaz de ejecutarse desde aplicaciones java o desde contenedores de servlets, el proyecto está liderado por Jérome Louvel.
Arquitecturas REST
Enlaces de interés
Arranque de un proyecto con Rest, JPA y Maven
Roy Fielding "Architectural Styles and the design of Network-based Software Architectures."
RESTful Web services: The basics
Restwiki, web dedicada al avance de la arquitectura REST
Arranque de proyecto RESTful con Glassfish
Arranque de proyecto RESTful con Tomcat
Creating a simple web service with Restlet
The Distributed Observer Pattern | The REST Dialogues
Jersey
Configuración de JSON (JavaScript Object Notation) para servicios web RESTful en Jersey 1.0
Consuming RESTful Web Services With the Jersey Client API
Implementing RESTful Web Services en Java
Guía para el desarrollo de aplicaciones REST con Jersey.
Overview of JAX-RS 1.0 Features
Android
How-to: Android as a RESTful Client
Herramientas
RESTClient, aplicación/framework Java para el testeo de servicios web RESTful y comunicaciones HTTP.
SoapUI sirve para testear servicios web SOAP y RESTful.

