1 Followers
26 Following
julyfrog4

julyfrog4

SPOILER ALERT!

Servicios Web de RESTful

REST define un conjunto de principios arquitectónicos por los que se pueden diseñar servicios Web que se centran en los recursos de un sistema, lo que incluye la forma en que los estados de los recursos se dirigen y trasfieren a través de HTTP por un amplio rango de clientes del servicio que están escritos en diferentes lenguajes. Si lo medimos por el número de servicios Web que lo usan, en los últimos años REST ha emergido como un modelo de diseño predominante para los servicios Web. De hecho, REST ha tenido tanto impacto en la Web que ha apartado enormemente al diseño de interfaces basado en SOAP y WSDL, pues es un estilo sensiblemente más fácil de emplear.


REST no consiguió mucha atención la primera vez que fue presentado en el por Roy Fielding en la Universidad de California, Irvine, en su disertación académica, "Architectural Styles and the Design of Network-based Software Architectures", que examina un conjunto de principios arquitectónicos de software que emplean la Web como una plataforma para la computación distribuida. Ahora, años después de su presentación, han comenzado aparecer las principales infraestructuras para REST, y se están desarrollando otras porque, por servirnos de un ejemplo, se ha anunciado que se va a convertir en una parte integral de Java™ seis en JSR-311.


Este artículo sugiere que, en su forma actual más pura, cuando atrae toda esta atención, las implementaciones concretas prosiguen cuatro principios básicos de diseño de servicios Web de REST:


  • Utilice métodos HTTP de forma explícita.
  • Sea sin estados.
  • Exponga los URIS como estructuras de directorios.
  • Transfiera XML, JavaScript Object Notation (JSON), o bien ambos.

Las siguientes secciones amplían esos cuatro principios y plantean una razón técnica de por qué deberían ser importantes para los diseñadores de servicios Web de REST.


Utilice métodos HTTP de forma explícita


Una de las primordiales características de un servicio Web de RESTful es el uso explícito de métodos HTTP de una forma que siga el protocolo tal como está definido por RFC dos mil seiscientos dieciseis. HTTP GET, por poner un ejemplo, se define como un método para producir datos, que está destinado a ser utilizado por una aplicación del cliente para recobrar un recurso, para traer datos desde un servidor Web o para ejecutar una consulta con la expectativa de que el servidor Web la busque y responda con un conjunto de recursos que coincidan.


REST solicita a los desarrolladores que utilicen HTTP de forma explícita y de una forma que sea congruente con la definición del protocolo. Este principio básico del diseño de REST establece una correlación individual entre las operaciones de crear, leer, actualizar y borrar (CRUD) y los métodos HTTP. Según esta correlación:


  • Para crear un recurso en el servidor hay que utilizar un POST.
  • Para recuperar un recurso hay que usar un GET.
  • Para cambiar el estado de un recurso, o para actualizarlo, hay que usar un PUT.
  • Para suprimir o bien borrar un recurso hay que usar un DELETE.

Una poco afortunada falla de diseño inherente de muchas APIs Web es la utilización de métodos HTTP para fines no deseados. Por servirnos de un ejemplo, el URI de la solicitud en una petición HTTP GET, en general identifica un recurso específico. O la cadena de caracteres de una consulta de un URI de la solicitud incluye un conjunto de parámetros que define los criterios de búsqueda que el servidor usa para encontrar un conjunto de recursos que coinciden. Por lo menos, así es cómo HTTP/1.1 RFC describe el GET. Pero, hay muchos casos de APIs Web no atractivas que emplean HTTP GET para desencadenar algo transaccional en el servidor—por ejemplo, para añadir registros a una base de datos. En esos casos, GET para pedir el URI no se utiliza adecuadamente, al menos, no se usa de la manera RESTful. Si la API Web usa GET para invocar procedimientos remotos, se parecerá a esto:


GET /adduser?name=Robert HTTP/1.1


No es un diseño atractivísimo, por el hecho de que el método Web precedente aguanta una operación de cambio de estado sobre HTTP GET. Por ponerlo de otra manera, la petición HTTP GET precedente tiene efectos colaterales. Si se procesa apropiadamente, el resultado de la solicitud será añadir un usuario nuevo—en este ejemplo, Robert—para el almacén de datos latente. El inconveniente aquí es eminentemente semántico. Los servidores Web están diseñados para contestar a las solicitudes HTTP GET recuperando los recursos que coinciden con la senda (o bien los criterios de la consulta) del URI de la solicitud, y devuelven exactamente los mismos, o una representación de ellos, en una respuesta; no para añadir un registro a una base de datos. Utilizar GET de esta forma es inconsistente desde la perspectiva del uso previsto del método del protocolo, y desde el punto de vista de los servidores Web conformes con HTTP/1.1.


Más allá de la semántica, el otro inconveniente con GET es que, para desencadenar el borrado, modificación o bien incorporación de un registro en una base de datos, o para mudar el estado por el lado del servidor de alguna manera, invita a herramientas para apresar las memorias caché de la Web (crawlers) y a motores de búsqueda para hacer cambios por el lado del servidor sin intención, solo rastreando un enlace. Una forma fácil de superar este problema frecuente es desplazar a etiquetas XML los nombres y los valores de los parámetros del URI de la solicitud. Las etiquetas resultantes, una representación XML de la entidad a crear, se pueden enviar en el cuerpo de una HTTP POST cuyo URI de la solicitud es el objeto primario de la entidad (vea los Listados 1 y dos).


El método precedente es un caso de una solicitud RESTful: empleo conveniente de HTTP POST e inclusión de la carga útil en el cuerpo de la petición. En la parte receptora, la petición se puede procesar añadiendo el recurso que está contenido en el cuerpo como un subordinado del recurso que está identificado en el URI de la solicitud; en este caso, el recurso nuevo se debería añadir como objeto secundario de /users. Esta relación de contención entre la entidad nueva y su objeto primario, como se detalla en la solicitud POST, es análoga a la forma en la que un fichero es subordinado a su directorio primario. El cliente del servicio establece la relación entre la entidad y su objeto primario, y define el URI de la nueva entidad en la solicitud POST.


Posteriormente, una aplicación del usuario podrá obtener una representación del recurso usando el nuevo URI, observando que el recurso está ubicado, al menos lógicamente, bajo /users, como se muestra en el Listado 3.


La utilización de GET de este modo es explícita, por el hecho de que GET sólo se usa para la recuperación de datos. GET es una operación que no debería tener efectos colaterales, una propiedad también conocida como idempotence.


En los casos en los que una operación de actualización sea soportada a través de HTTP GET, también se deberá aplicar una refactorización afín de un método web, tal y como se muestra en el Listado cuatro.


Esto cambia el atributo (o bien propiedad) name del recurso. Aunque, para dicha operación se puede emplear una cadena de consulta, y el Listado 4 es una operación operación simple, este patrón cadena-de-consulta-como-método-de-firma tiende a estropearse cuando se utiliza para operaciones más complejas. Ya que su meta es emplear los métodos HTTP de forma explícita, un enfoque más RESTful es enviar una solicitud HTTP PUT para actualizar el recurso, en lugar de HTTP GET, por exactamente las mismas razones precedentes (vea el Listado cinco).


Utilizar PUT para reemplazar el recurso original da una interfaz más limpia, que es coherente con los principios de REST y con la definición de los métodos HTTP. La petición PUT del Listado 5 es explícita en el sentido de que apunta al recurso que ha de ser actualizado identificándolo en la petición de URI, y en el sentido de que transfiere una nueva representación del recurso desde el cliente del servicio cara el servidor en el cuerpo de una solicitud PUT, en lugar de transferir los atributos del recurso como un conjunto suelto de nombres y valores de parámetros sobre el URI de la petición. El Listado cinco también renombra el recurso de Robert a Bob, y, al hacerlo, cambia su URI a /users/Bob. En un servicio Web de REST, las solicitudes siguientes para el recurso que utiliza el URI viejo generarían un fallo estándar 404 No Encontrado.


Como gestor de contenidos web ño, ayuda a proseguir las indicaciones de REST para emplear métodos HTTP de forma explícita usando nombres en los URIs, en vez de verbos. En un servicio Web de RESTful, los verbos—POST, GET, PUT y DELETE—ya están definidos por el protocolo. También, idealmente, el servicio Web no debería delimitar más verbos o procedimientos recónditos, como /adduser o /updateuser, para sostener la interfaz extendida y para dejar que los clientes sean explícitos acerca de las operaciones que invocan. Este principio general del diseño también se aplica al cuerpo de una solicitud HTTP, que está destinado a ser utilizado para transferir el estado del recurso, no para llevar el nombre de un método recóndito o de un procedimiento recóndito a invocar.


Sea sin estado


Los servicios Web de REST deben escalar para satisfacer las cada vez mayores demandas de alto rendimiento. Los clústeres de los servidores que tienen capacidades de balanceo de carga y de recuperación por fallo, los proxys y las puertas de link, por norma general, se disponen de una forma que forma la topología de un servicio, lo que deja reenviar las solicitudes de un servidor a otro según se necesite, para reducir el tiempo de contestación general de una llamada a un servicio web. Para emplear servidores intermediarios para prosperar la escala, los clientes de servicios Web de REST deben enviar solicitudes completas e independientes; o sea, mandar solicitudes que incluyan todos los datos que se tienen que completar, para que los componentes de los servidores intercesores puedan reenviar, redirigir y balancear la carga para no tener que sostener de forma local ningún estado entre las solicitudes.


Una petición completa e independiente no requiere que el servidor recupere ningún tipo de contexto o bien estado de la aplicación, mientras que procesa la solicitud. Las aplicaciones (o bien clientes del servicio) de los servicios web de REST incluyen, dentro de las cabeceras y cuerpos HTTP de una solicitud, todos y cada uno de los parámetros, contexto y datos que el componente por el lado del servidor necesita para producir una respuesta. El no tener estado en este sentido mejora el desempeño del servicio Web y simplifica el diseño y la implementación de los componentes por el lado del servidor, debido a que la ausencia de estado en el servidor elimina la necesidad de acompasar los datos de la sesión con una aplicación externa.


La imagen 1 ilustra un servicio sin estado desde el que una aplicación puede pedir la siguiente página de un conjunto de resultados de múltiples páginas, asumiendo que el servicio realice el seguimiento de dónde lo deja la aplicación mientras navega por el conjunto. En este diseño sin estado, el servicio acrecienta y guarda, en algún sitio, una variable previousPage para ser capaz de responder a las peticiones de la siguiente.



Los servicios con estado como este se vuelven complicados. En una Plataforma de Java, los servicios con estado de los entornos Enterprise Edition (Java EE) requieren de muchas consideraciones anteriores para guardar eficazmente y para permitir la sincronización de los datos de la sesión durante un clúster de contenedores de Java. En esta clase de ambientes, hay un inconveniente con el que los desarrolladores de servlet/JavaServer Pages (JSP) y Enterprise JavaBeans (EJB) están familiarizados, con frecuencia tienen problemas para encontrar la raíz de la causa de una excepciónjava.io.NotSerializableException durante la replicación de la sesión. Este problema, tanto si es lanzado por el contenedor del servlet durante una replicación HttpSession como si es lanzado por el contenedor de EJB a lo largo de una replicación de EJB sin estado, es un inconveniente que puede costar a los desarrolladores días de trabajo intentando identificar un objeto que no implementa Serializable en un, a veces, complejo gráfico de objetos que constituyen el estado del servidor. Además, la sincronización de la sesión añade una sobrecarga, que afecta al desempeño del servidor.


Los componentes sin estado por el lado del servidor, por otra parte, son más fáciles de diseñar, redactar y distribuir durante los servidores que tienen la carga equilibrada. Un servicio sin estado no sólo tiene mejor rendimiento, traspasa la mayoría de la responsabilidad de mantener el estado a la aplicación del cliente del servicio. En un servicio web de RESTful, el servidor es responsable de generar contestaciones y de suministrar una interfaz que deje que el cliente sostenga por sí sólo el estado de la aplicación. Por servirnos de un ejemplo, en la petición de un conjunto de resultados de múltiples páginas, el usuario debería incluir el número actual de la página a recuperar en vez de sencillamente pedir la siguiente (vea la Imagen 2).



Un servicio web sin estado genera una contestación que enlaza al número de la próxima página del conjunto y deja que el usuario haga lo que tenga que hacer para preservar ese valor. Este aspecto del diseño de servicios web de RESTful Web se puede separar en 2 puntos de responsabilidades, como una separación de alto nivel que aclara cómo se puede sostener un servicio sin estado:


Servidor


  • Genera contestaciones que incluyen links a otros recursos, para permitir que otras aplicaciones naveguen entre los recursos relacionados. Esta clase de contestación incorpora links. De forma afín, si la petición se efectúa para un objeto secundario o bien un recurso contenedor, la contestación típica de RESTful también podría incluir enlaces a los objetos secundarios del primario o bien a recursos subordinados, para que éstos continúen conectados.
  • Genera respuestas que indican si se pueden guardar en la memoria caché, para prosperar el rendimiento al reducir el número de solicitudes de recursos duplicados y al quitar totalmente ciertas peticiones. El servidor lo hace incluyendo una cabecera de contestación HTTP Cache-Control y Last-Modified (una fecha).

Aplicación del cliente


  • Utiliza la cabecera de la contestación Cache-Control para determinar si guarda el recurso en la memoria caché (hacer una copia local del mismo). El usuario también lee la cabecera de la contestación Last-Modified y envía de vuelta el valor de la fecha en una cabecera If-Modified-Since para consultar al servidor si el recurso ha alterado. Esto se denomina GET Condicional, y las 2 cabeceras van codo con codo en que la respuesta del servidor es un código trescientos cuatro estándar (No Cambiado), y omite el recurso actual pedido si no ha cambiado desde ese instante. Un código de contestación HTTP 304 quiere decir que el cliente puede emplear seguramente una copia local, guardada en la caché, de la representación del recurso como la más actualizada; de hecho, elude las posteriores peticiones GET hasta que el recurso cambie.
  • Envía solicitudes completas que se pueden atender de forma independiente con respecto a las otras peticiones. Esto requiere que el cliente del servicio utilice absolutamente las cabeceras HTTP tal y como lo especifica la interfaz del servicio Web, y que envíe representaciones completas de los recursos en el cuerpo de la petición. El cliente del servicio envía peticiones que hacen poquísimas suposiciones sobre las precedentes solicitudes, la existencia de una sesión en el servidor, la capacidad del servidor de añadir contexto a una solicitud, o bien sobre el estado de una aplicación que se sostiene entre las solicitudes.

Esta colaboración entre la aplicación y el servicio del cliente es esencial a fin de que un servicio web de RESTful sea sin estado. posicionamiento web asuncion el desempeño al ahorrar ancho de banda y al disminuir al mínimo el estado de la aplicación por el lado del servidor.


Exponga los URIs como estructuras de directorio.


Desde el punto de vista de las aplicaciones que se encargan de recursos, los URIs determinan lo intuitivo que será un servicio web de REST y si el servicio se va a utilizar de formas que los diseñadores puedan adelantar. La tercera característica web de RESTful va sobre los URIs.


Los URIs de los servicios web de REST deberían ser intuitivos hasta el punto en que sean fáciles de adivinar. Piense en un URI que tenga un género de interfaz autodocumentada que requiera poca, o bien ninguna, explicación o bien referencia a fin de que un desarrollador comprenda a que apunta y para derivar los recursos relacionados. Con este fin, la estructura de un URI debería ser bastante clara, predecible y fácil de comprender.


Una forma de conseguir este nivel de usabilidad es delimitar URIs de tipo estructura de directorio. Este tipo de URI es jerárquico, enraizado como una única senda y sus ramificaciones son subrutas que exponen las primordiales áreas del servicio. Según esta definición, un URI no es meramente una cadena de caracteres acotada por barras oblicuas, sino más bien un árbol con ramas subordinadas y superiores que se conectan en los nodos. Por servirnos de un ejemplo, en un servicio de hebras de discusiones que reúne temas que varían desde Java hasta el papel, usted puede acotar un conjunto estructurado de URIs de esta manera:


/discussion/topics/topic


La raíz, /discussion, tiene un nodo /topics bajo ella. Por debajo de eso hay una serie de nombres de temas, como cotilleos, tecnología, etc., y cada uno de ellos de ellos apunta a una hebra de una discusión. Dentro de esta estructura es fácil extraer hebras de discusiones sencillamente escribiendo algo después de /topics/.


En algunos casos, la ruta hacia un recurso se presta singularmente bien para una estructura tipo directorio. Por ejemplo, tome los recursos organizados por la fecha, lo que es buena combinación para usar la sintaxis jerárquica.


Este ejemplo es intuitivo porque se basa en reglas:


/discussion/2008/12/10/topic


El primer fragmento de la senda es un año de cuatro dígitos, el segundo fragmento de la ruta es un día de dos dígitos y el tercer fragmento es un mes de dos dígitos. Puede parecer un poco absurdo tener que explicarlo de este modo, pero es el nivel de simplicidad que estamos buscando. Los humanos y las máquinas pueden generar fácilmente URIs estructurados como estos, por el hecho de que se basan en reglas. Rellenar las partes de la senda en las ranuras de la sintaxis hace que sean buenos pues hay un patrón terminante desde el que componerlos:


/discussion/year/day/month/topic


Algunas indicaciones adicionales interesantes mientras se piensa sobre la estructura del URI para un servicio web de RESTful son:


  • Esconder las extensiones del archivo de la tecnología de los scripts por el lado del servidor (.jsp, .php, .asp), si las tuviese, para poder transportarlo a otro lugar sin mudar los URIs.
  • Mantenga todo en letra minúscula.
  • Sustituya los espacios con guiones o bien con subrayados (escoger un tipo).
  • Evite preguntar las cadenas de caracteres tanto como pueda.
  • Si el URI solicitado es para una ruta parcial, dé siempre y en toda circunstancia como contestación una página o bien recurso predeterminado, en vez de usar el código 404 No Encontrado.

Los URIs también deberían ser estáticos, para que cuando el recurso o bien la implementación del servicio cambien, el link siga siendo el mismo. Esto deja usar marcadores. También es esencial que la relación entre los recursos que está codificada en los URIs prosiga siendo independiente de la forma en la que se representan las relaciones dónde estás están guardadas.


Transfiera XML, JSON, o bien ambos


Una representación de recursos en general refleja el estado actual de un recurso y de sus atributos en el instante en el que una aplicación cliente la solicita. diseño de la página web , las presentaciones de recursos son puras instantáneas en el tiempo. Esto podría ser una cosa tan sencilla como la representación de un registro en una base de datos que está formada por una correlación entre nombres de columnas y etiquetas XML, dónde los valores de los elementos del XML contienen los valores de las filas. O, si el sistema tiene un modelo de datos, entonces, según esta definición, una representación de un recurso es una instantánea de los atributos de una de las cosas del modelo de datos de su sistema. Estas son las cosas que desea que su servicio web de REST presente.


El último conjunto de restricciones que va en el diseño de un servicio web de RESTful debe ver con el formato de los datos que la aplicación y el servicio intercambian en la carga útil de la solicitud/respuesta o bien en el cuerpo HTTP. Aquí es donde realmente compensa mantener las cosas sencillas, legibles por los humanos y conectadas.


Los objetos de su modelo de datos generalmente están relacionados de alguna manera, y las relaciones entre los objetos del modelo de datos (recursos) deberían estar reflejadas de manera que estén representadas para trasferirlas a una aplicación usuario. En el servicio de hebras de discusiones, un ejemplo de representaciones de recursos conectados podría incluir un tema de la discusión raíz, sus atributos y los enlaces incorporados a las contestaciones que se han proporcionado para ese tema.


Y, finalmente, para proporcionar a las aplicaciones del cliente la capacidad de solicitar un género de contenido específico que le venga mejor, edifique su servicio de manera que utilice la cabecera HTTP Accept incorporada, donde el valor de la cabecera es un tipo MIME. En la Tabla 1 se muestran algunos tipos MIME frecuentes que emplean los servicios de RESTful.


Esto deja que el servicio sea utilizado por diferentes clientes del servicio que están escritos en diferentes lenguajes y que se ejecutan en diferentes plataformas y dispositivos. La utilización de los tipos MIME y de la cabecera HTTP Accept es un mecanismo que se conoce como negociación de contenido, que deja de los clientes escojan cuál es el formato de datos que es adecuado para ellos y minimiza el acoplamiento de datos entre el servicio y las aplicaciones que lo usan.


Conclusión


REST no siempre y en todo momento es la elección conveniente. Fue impuesto como una forma de diseñar servicios Web con menos dependencia del middleware patentado (por poner un ejemplo, un servidor de aplicaciones) que la que tienen los del tipo SOAP y los basados en WSDL. Y, de alguna forma, REST es regresar a la Web de la forma en la que era antes de la era de los grandes servidores de aplicaciones, a través de su énfasis en los primeros estándares, URI y HTTP de Internet. Como hemos vistos en los autodenominados principios del diseño de la interfaz de RESTful, XML sobre HTTP es una potente interfaz que permite que aplicaciones internas, como el JavaScript Asincrónico + interfaces de usuario adaptadas basadas en XML (Ajax), se conecten, manejen y consuman recursos fácilmente. De hecho, el perfecto ajuste entre Ajax y REST ha incrementado la cantidad de atención que REST está consiguiendo estos días.


Exponer los recursos de un sistema a lo largo de una API de RESTful es una forma flexible de suministrar diferentes géneros de aplicaciones en las que los datos tengan un formato estándar. Ayuda a satisfacer los requisitos de la integración que son críticos para construir sistemas en los que los datos se puedan conjuntar fácilmente (mashups), y para extender o bien edificar un conjunto de servicios de RESTful básicos y crear algo mucho mayor. Este artículo tan sólo toca los aspectos básicos, pero, espero que le haya incitado a proseguir explotando el tema.