Servicios web RESTful con HTTP. Parte I: Introducción y bases téoricas

En esta serie de entradas voy a intentar introducir y profundizar relativamente en el concepto de servicios web RESTful, cómo funciona esta arquitectura y como podemos usarla para diseñar e implementar nuestros proyectos de manera más organizada y eficiente.

HTTP

El artículo estará dividido en tres partes: esta primera parte introductoria versará sobre los conceptos básicos teóricos que definen esta arquitectura, conceptos que podemos encontrar en un sinfín de sitios web, y que intentaré poner en relación con las siguientes entregas. En la segunda parte hablaré sobre consideraciones de implementación, sin un lenguaje de programación definido, así como casos de estudio, usos en la industria, etc. Por último, en la tercera parte presentaré un caso práctico con implementación en PHP, usando el framework Symfony.

Representational State Transfer

Según la definición puramente teórica, REST es un estilo de arquitectura que abstrae los elementos de dicha arquitectura dentro de un sistema hypermedia distribuido [1]. Pero esto de por sí no nos dice demasiado a no ser que nos dediquemos al estudio teórico de este tipo de cosas. Así que, de nuevo, ¿qué es REST? Utilizando palabras llanas, podríamos decir que REST es un conjunto de principios, o maneras de hacer las cosas, que define la interacción entre distintos componentes, es decir, las reglas que dichos componentes tienen que seguir. El protocolo más usado que cumple esta definición, es el protocolo HTTP.

Esto quiere decir, por extensión, que toda aplicación web bajo el protocolo HTTP es a su vez una aplicación REST. Sin embargo, como veremos más abajo, eso no implica en absoluto que todas las aplicaciones web sean servicios web RESTful, ya que estas tienen que cumplir una serie de requisitos para ser consideradas tales. Existen, además, otros tipos de métodos para implementar servicios web, que seguramente te suenen, como RPC, SOAP o WSDL. Sin embargo, el uso de dichos mecanismos no se suele recomendar en favor de RESTful, ya que RESTful es mucho más fácil de entender e implementar. No obstante, como siempre, la decisión sobre implementar una tecnología u otra depende en gran medida de las características del proyecto en el que estemos implicados, por lo que es recomendable siempre hacer un análisis concienzudo del proyecto y las tecnologías disponibles para decantarnos por una o por otra. A continuación continuo con más detalles sobre REST que te pueden ayudar a elegir esta metodología por encima de otras.

Reglas de la arquitectura REST

REST define una serie de reglas que toda aplicación que pretenda llamarse REST debe cumplir. Como veremos, estas reglas se nos dan ya dadas si vamos a usar el protocolo HTTP, en cualquiera de sus implementaciones (por ejemplo, Apache). No obstante, conviene repasar estos conceptos para tener una visión más profunda, y veremos más adelante que nos ayudará bastante a la hora de implementar nuestros programas:

  • Arquitectura cliente-servidor: consiste en una separación clara y concisa entre los 2 agentes básicos en un intercambio de información: el cliente y el servidor. Estos 2 agentes deben ser independientes entre sí, lo que permite una flexibilidad muy alta en todos los sentidos.
  • Stateless: esto significa que nuestro servidor no tiene porqué almacenar datos del cliente para mantener un estado del mismo. Esta limitación es sujeto de mucho debate en la industria, incluso ya empiezan a usarse tecnologías relacionadas que implementan el estado dentro de la arquitectura, como WebSockets. Como sabemos, HTTP también cumple esta norma, por lo que estamos acostumbrados ya a hacer uso de protocolos stateless.
  • Cacheable: esta norma implica que el servidor que sirve las peticiones del cliente debe definir algún modo de cachear dichas peticiones, para aumentar el rendimiento, escalabilidad, etc. Una vez más, HTTP implementa esto con la cabecera «Cache-control», que dispone de varios parámetros para controlar la cacheabilidad de las respuestas.
  • Sistema por capas: nuestro sistema no debe forzar al cliente a saber por qué capas se tramita la información, lo que permite que el cliente conserve su independencia con respecto a dichas capas.
  • Interfaz uniforme: esta regla simplifica el protocolo y aumenta la escabilidad y rendimiento del sistema. No queremos que la interfaz de comunicación entre un cliente y el servidor dependa del servidor al que estamos haciendo las peticiones, ni mucho menos del cliente, por lo que esta regla nos garantiza que no importa quien haga las peticiones ni quien las reciba, siempre y cuando ambos cumplan una interfaz definida de antemano.

Diagrama de la arquitectura REST

REST y HTTP

Vista esta pequeña introducción a los conceptos y reglas básicas de REST, podríamos implementar sin problemas un protocolo que hiciera uso de dicha arquitectura. A pesar de que podría ser un ejercicio más que interesante si lo que buscamos es aprender, no necesitamos hacerlo ya que afortunadamente contamos con uno que implementa REST y que además es la base de Internet. Como ya he ido avanzando anteriormente, este protocolo es HTTP. Empezaremos diciendo que para que una aplicación sea REST al 100%, tendrá que implementar 4 principios básicos, y pondremos esto en relación a cómo HTTP implementa dichos principios:

  • Identificación de recursos: toda aplicación REST debe poder identificar sus recursos de manera uniforme. HTTP implementa esto usando las llamadas URIs (Uniform resource identifier). Esta es la URL que usamos tradicionalmente, y aunque hay una diferencia sutil entre URLs y URIs [2], diremos que toda URL es una URI a su vez. Esta identificación del recurso no incluye la representación del mismo, cosa que veremos a continuación.
  • Recursos y representaciones: visto que todo recurso debe tener una identificación (URI), REST define también la manera en que podemos interactuar con la representación del mismo, ya sea para editarlo o borrarlo, directamente del servidor. Estas representaciones se dejan a instancias de la implementación final del programa, pero HTTP define distintas cabeceras de tipos, y un contenido en la respuesta, por lo que nuestras aplicaciones pueden enviar el contenido en el formato que quieran, siempre y cuando este contenido contenga la información necesaria para poder operar con el objeto en el caso de que tengamos permiso para hacerlo.
  • Mensajes autodescriptivos: cuando hacemos peticiones a un servidor, éste debería devolver una respuesta que nos permita entender sin lugar a duda cual ha sido el resultado de la operación, así como si dicha operación es cacheable, si ha habido algún error, etc. HTTP implementa esto a través del estado y una serie de cabeceras. El cómo se usan estos estados y cabeceras depende por entero de la implementación de nuestro programa, en otras palabras, REST no fuerza el contenido de dichos elementos, por lo que el programa que se ejecuta en el servidor, y que en última instancia accede a los recursos y opera con ellos, tiene la responsabilidad de devolver estados y cabeceras que se correspondan con el estado real de la operación realizada. Esto es importante tenerlo en cuenta, ya que, desgraciadamente, un gran número de aplicaciones y servicios web no respetan esta regla (por lo tanto no pueden ser considerados REST), lo que nos lleva a tener que realizar todo tipo de workarounds y cosas por el estilo. En la segunda parte de esta serie veremos un caso práctico de un servicio web que no respeta esta norma, y daremos varias soluciones posibles.
  • HATEOAS: por último, y algo que la mayoría de servicios web no cumplen, es la necesidad de incluir en las respuestas del servidor toda aquella información que necesita el cliente para seguir operando con este servicio web. En otras palabras, el cliente no tiene porqué saber que cuando obtenemos, por ejemplo, un objeto cualquiera, tenemos además las opciones de modificarlo, o eliminarlo. El servidor debe enlazar a estas operaciones en la respuesta a dicha petición. De esta manera, lo único que necesita saber un cliente sobre una aplicación REST, es el punto de entrada (endpoint). Además nos garantiza más independencia entre el cliente y el servidor. Desgraciadamente, este último principio no se implementa en la mayoría de APIs que usamos hoy en día, por lo que, siendo estrictos, podríamos decir que la mayoría de servicios web no son 100% RESTful. No obstante, esto es una limitación menor que en prácticamente ningún caso supone un problema.

Servicios web RESTful

Así pues, teniendo claros estos conceptos y cómo se relacionan con el protocolo HTTP, y sabiendo que un servicio web RESTful hace referencia a un servicio web que implementa la arquitectura REST, podemos ya dar una definición concisa, lo cual nos dejará claro cómo tenemos que implementarlo en nuestras aplicaciones. Un servicio web RESTful contiene lo siguiente:

  • URI del recurso. Por ejemplo: http://api.servicio.com/recursos/casas/1 (esto nos daría acceso al recurso «Casa» con el ID «1»)
  • El tipo de la representación de dicho recurso. Por ejemplo, podemos devolver en nuestra cabecera «Content-type: application/json», por lo que el cliente sabrá que el contenido de la respuesta es una cadena en formato JSON, y podrá procesarla como prefiera. El tipo es arbitrario, siendo los más comunes JSON, XML y TXT.
  • Operaciones soportadas: HTTP define varios tipos de operaciones (verbos) [3], que pueden ser GET, PUT, POST, DELETE, PURGE, entre otros. Es importante saber para que están pensados cada verbo, de modo que sean utilizados correctamente por los clientes.
  • Hipervínculos: por último, nuestra respuesta puede incluir hipervínculos hacia otras acciones que podamos realizar sobre los recursos. Normalmente se incluyen en el mismo contenido de la respuesta, así si por ejemplo, nuestra respuesta es un objeto en JSON, podemos añadir una propiedad más con los hipervínculos a las acciones que admite el objeto.

En la imagen se muestra un ejemplo de una petición al servicio web de GitHub. No se muestra, pero en el contenido de la respuesta no se incluían hipervínculos a otras acciones, por lo tanto no es una servicio web RESTful completo.

Ejemplo de llamada REST

Conclusiones

En este primera parte hemos introducido teóricamente la arquitectura REST y la hemos relacionado con el protocolo HTTP, que implementa esta arquitectura. A continuación hemos visto cómo tenemos que hacer uso de este protocolo para considerar un servicio web RESTful completo. Todo esto nos dará la base teórica que necesitamos para implementar y consumir servicios web RESTful. En el próximo capítulo veremos varios ejemplos prácticos de este tipo de servicios web e introduciremos a su vez buenas prácticas a tener en cuenta antes de implementar el nuestro propio.

[1] http://en.wikipedia.org/wiki/Representational_state_transfer
[2] http://www.ietf.org/rfc/rfc3986.txt (1.1.3)
[3] http://www.w3.org/Protocols/HTTP/1.1/draft-ietf-http-v11-spec-rev-06.txt (9 y siguientes)

WordPress › Error

Ha habido un error crítico en esta web.

Aprende más sobre el diagnóstico de WordPress.