En el primer artículo de la serie vimos que es un API y cuales son los tipos que hay.
En el presente, vamos a enfocarnos sobre que es un API REST y como podemos diseñarlas.
API REST
Durante la última década (y mucho más también) las API REST fueron el estándar de facto para desarrollar APIs.
REST (REpresentational State Transfer) es un estilo de arquitectura de sistemas distribuidos y no un estándar como lo es SOAP. Esta es la razón por la que no existe una guía estandarizada para su implementación; lo que si hay son principios o limitaciones que definen si un API es REST o no.
Roy Fielding fue la persona que introdujo este concepto por primera vez en su tesis “Architectural Styles and the Design of Network-based Software Architectures” donde define las siguientes restricciones que se deben cumplir para que una arquitectura sea considerada REST:
- Arquitectura cliente-servidor (client-server architecture): dos aplicaciones actuando una como cliente la cual solicita recursos a un servidor el cual devuelve una respuesta ante la solicitud del cliente.
- Sin estado (stateless): El servidor no guarda un estado entre diferentes solicitudes (request) de un cliente, o sea, cada solicitud es independiente del resto y debe auto-contener la información suficiente para regenerar el estado en cada request.
- Cache: debe ser posible almacenar en un caché la respuesta del servidor y poder devolverla en las subsiguientes peticiones (que requieran el mismo recurso) sin necesidad de que llegue el request al servidor nuevamente.
- Interfaz uniforme (uniform interface): Incluye cuatro aspectos, identificación de recursos, gestión de recursos a través de representaciones, comunicaciones auto-descriptivas e hipermedia como el motor del estado de la aplicación (HATEOAS).
- Sistema de capas (layered system): La solicitud al server puede pasar por diferentes capas donde se puede agregar funcionalidades adicionales como caché, seguridad, balanceo de carga, auditoría, logging, etc.
- Código bajo demanda (code on demand): Es un feature opcional y no es necesario que las APIs lo implementen. Esta funcionalidad permite que el server devuelva al cliente código ejecutable
Las APIs que implementan REST se las conoce como API RESTful.
En el último tiempo surgieron especificaciones que intentan darle un marco estandarizado a las API REST. Entre ellas OpenAPI es la más popular. Otra especificación en auge es el RAML.
Diseño de un API REST
Cuando diseñamos un API REST, más allá de la implementación propia del lenguaje de programación que utilicemos, debemos tener en cuenta lo siguiente:
- Los principios analizados anteriormente
- Las API REST trabajan con "recursos" y no con "servicios/funciones" como en RPC/SOAP y que cada recurso debe poder accederse por un URI en propio (endpoint)
- Debemos hacer uso correcto de las bondades del protocolo HTTP, tales como los verbos (GET, POST, PUT, etc), los códigos de estado (404, 500, 200, etc) y las cabeceras (headers).
Por ejemplo, tomemos el recurso Usuario llamado Andres, debe tener asociada una URI http://domain.com/users/andres y para su obtención se utiliza el método GET, para su creación POST.
Otro ejemplo es la información de una reunión http://domain.com/meetings/2354.
Tanto el recurso “andres” como el recurso “meeting 2354” siempre refieren al mismo recurso y es esperable que ante subsecuentes solicitudes siempre devuelva la misma información (la cual se puede cachear).
Ejemplos no validos:
- http://domain.com/users/getUserByName/andres
- http://domain.com/users/updateUser/andres
- http://domain.com/users/createUserUser/andres
Verbos HTTP (HTTP verbs)
El protocolo HTTP define un conjunto de acciones a realizar sobre un recurso tales como su creación, su borrado o actualización.
Estas acciones (HTTP verbs) juegan un rol importante en el constraint de Uniform Interface que vimos anteriormente.
Verbo HTTP | Operación | Descripción |
---|---|---|
GET | Read | Solicita uno o una colección de recursos |
POST | Create | Crea un recurso con la información enviada en el cuerpo (body) del request |
PUT | Update/Replace | Actualiza un recurso preexistente o lo reemplaza. Podría también crearlo |
PATCH | Update/Modify | Similar a PUT, se utiliza para actualizar de manera parcial un recurso |
DELETE | Delete | Elimina un recurso |
HEAD | Read | Similar a GET, pero el server solo retorna los encabezados (headers) y no el cuerpo (body) de la respuesta |
OPTIONS | ASK | El servidor retorna el listado de verbos HTTP permitidos para el recurso |
TRACE | ALL | Solicita al servidor que agregue en la respuesta los datos recibidos para depuración |
Los verbos GET, HEAD, OPTIONS y TRACE son considerados seguros por definición por lo que no deben generar un impacto en el/los recursos indicados en la petición (ni generar por ejemplo transacciones que generen un cambio de estado en el servidor) más allá de agregar logging, update de caché, entre otros recursos aledaños pero nunca sobre el recurso indicado en el URI.
Por otro lado, muchos de estos verbos HTTP tienden a ser idempotentes (aunque no es una restricción si es esperable). Los verbos PUT, DELETE, GET, HEAD, OPTIONS y TRACE deben devolver siempre la misma información ante subsecuentes requests. No así para el verbo POST donde cada request igual puede generar efectos secundarios tal vez no deseados.
Código de estados (HTTP Status codes)
Los datos que retorna el servidor a partir de un request siempre son acompañados por un código de estado de HTTP que indica el resultado del request.
HTTP define un conjunto predefinidos que se agrupan en:
- 1xx: los códigos dentro de este rango son informativos
- 2xx: los encontrados en este rango indican que la solicitud fue exitosa
- 3xx: este grupo de códigos indican que se debe hacer o hubo una redirección
- 4xx: los códigos dentro de este grupo indican diferentes errores del cliente
- 5xx: estos códigos indican que se produjo un error en el servidor
Muchos de estos códigos son devueltos por la infraestructura o por el framework que utilicemos para crear nuestra API, mientras que nosotros como devs vamos a utilizar otros (y en algunos casos los mismos) para indicar que sucedió con la solicitud que estamos tratando.
Los códigos más utilizados son:
- 200 (OK): solicitud exitosa y retorno del recurso
- 201 (Created): recurso creado exitosamente y retorna el URI al recurso
- 401 (Unauthorized): sin autorización para el recurso
- 403 (Forbidden):
- 404 (Not Found): recurso no encontrado/inexistente
- 409 (Conflict): conflicto en la creación/update del recurso
- 500 (Internal Server Error): error no manejado en el código de la aplicación, por ejemplo una excepción sin un catch.
No comments sobre esta imagen 🤣
Encabezados (HTTP Headers)
Los Headers es información adicional que se intercambia entre el cliente y el servidor (Request/Response). Por ejemplo:
- Información sobre los datos enviados en el Request/Response
- Información de Autenticación
- Información sobre Caching
- Información sobre Cookies
Algunos Headers tienen dirección cliente al servidor (ej: Authentication), otros tienen significado del servidor al cliente (ej: Location) y por último algunos se utilizan indistintamente (ej: _Content-Length).
Entre los mas comunes podemos mencionar
Header | Descripción |
---|---|
Authorization | Método e información para la autenticación en el servidor del recurso |
Cache-Control | Método de cache para el recurso |
Accept | Informa sobre el formato aceptado por el cliente |
Accept-Language | Lenguaje esperado por el cliente para los datos que recibe del server |
Cookie | Cookies recibidas por el server |
Origin | Indica desde donde se origino el request |
Content-Length | Tamaño del payload |
Content-Type | Indica el Media Type del payload |
Bien ya aprendimos algo sobre las API REST es hora de comenzar a meter mano un algo de código, somos devs, no?
Bueno, preparate un 🧉/☕ + 🥐🍩 que en el próximo vamos directo a tirar magia 💪
Top comments (0)