Introducción al diseño de una API HTTP (Parte 1 de 4) : HTTP Requests

Este primer artículo abarca una breve introducción sobre las solicitudes HTTP (HTTP Requests).

¿Qué es una Solicitud HTTP?

Creo que primero habría que definir que es HTTP (Hipertext Transfer Protocol). El protocolo HTTP no le debe ser muy indiferente. Si leíste sobre el Modelo OSI, recordarás que este protocolo de comunicación pertenece al nivel de aplicación, que a su vez, esta por encima de otro famoso protocolo, el protocolo TCP (Transmission Control Protocol) que se sitúa en la capa transporte de este modelo. Como todo protocolo de comunicación, el protocolo HTTP define unas normas que debe seguir el emisor que desea transmitir información a un receptor. HTTP utiliza el patrón de request / response (petición / respuesta), lo cual quiere decir, que un emisor (sistema X) realiza una solicitud (request) y un servidor (Sistema Y)  responde (response) a dicha solicitud.

En la siguiente imagen se puede apreciar como un computador (emisor) realiza una solicitud HTTP (HTTP Request) a un servidor (receptor) y este último le responde (HTTP Response) el pedido.

A continuación un ejemplo de las reglas que debe seguir el cliente para que el servidor comprenda su petición HTTP.

La primera línea se llama Línea de Solicitud y contiene tres elementos;

1. El método HTTP (para este ejemplo es POST).

2. Una ruta de acceso (también denominada como endpoint en una API).

3. La versión HTTP (para este ejemplo es HTTP/1.1)

Existen otros métodos HTTP, más adelante se mencionarán.

El contenido que le sigue a la “Línea de Solicitud” se denomina Headers (en español encabezados). Los headers son pares de key – value (clave – valor), donde la clave es la primera palabra, seguido de dos puntos y un espacio y, a continuación, el valor. Los headers están separados por saltos de línea. Es recomendable que las claves de los headers inicien con su primera letra en mayúscula. Los headers pueden repetirse en situaciones en las que es necesario enviar valores duplicados.

Una solicitud HTTP (HTTP Request) solo necesita tener una Línea de Solicitud y algunos headers para ser válido. Esto se aplica principalmente a las solicitudes que utilizan los métodos HTTP GET, DELETE, HEAD y OPTIONS. Sin embargo, también podemos proporcionar un cuerpo de solicitud (request body), que requiere dos líneas nuevas después del último header antes del contenido del cuerpo. Los cuerpos se utilizan principalmente con los métodos HTTP POST, PUT y PATCH.

Hablemos de los Endpoints

Al diseñar una API HTTP RESTful, es importante poder abstraer la funcionalidad de su servicio de tal manera que todas las operaciones puedan representarse realizando operaciones CRUD (Create, Read, Update, Delete) para los diferentes recursos (entidades). Las acciones (verbos HTTP ó métodos HTTP) que se realizan nunca deben ser parte del endpoint.

El enfoque más utilizado es exponer diferentes colecciones de recursos relacionados. Por ejemplo, si su servicio contiene información sobre diferentes empresas y empleados, podría tener una colección llamada empresas y otra colección llamada empleados. Podemos obtener información más específica y hacer referencia a una empresa individual o a sus empleados dentro de cada una de estas colecciones. Como por ejemplo, un empleado puede ser empleado en una empresa. Lo siguiente es cómo podemos representar estos datos y sus relaciones:

Por lo tanto, podemos decir que si queremos obtener la lista de empresas debemos solicitar el endpoint /companies o si queremos obtener información de solo una empresa debemos solicitar el endpoint /companies/{company_id}

Headers HTTP

Habíamos dicho que los headers son un conjunto de pares de clave-valor. Hay muchos headers diferentes que podemos utilizar. Los navegadores web, por lo general, envían varios headers en sus solicitudes HTTP (requests) y los nuevos navegadores están siendo estandarizados todo el tiempo. A continuación una lista de los headers más comunes y su significado, que además debe tener en cuenta para que sean compatibles con el API HTTP que construyas.

Accept: Puede contener una lista de “Tipos de Contenido” (Content-Types) que son aceptados por el cliente (navegador web por ejemplo). Un tipo de contenido muy usado en las APIs  HTTP es application/json. Es decir, el cliente acepta recibir información del servidor en formato JSON.

Accept-Language: Puede contener una lista de idiomas que son aceptados por el cliente. Por ejemplo podemos indicar que el cliente acepta recibir información del servidor en idioma ingles en-US, o en español es-pe.

Content-Length: Es la longitud en bytes del cuerpo de la solicitud. Si se conoce el tamaño del cuerpo de la solicitud, se debe enviar este valor.

Content-Type: Representa al tipo de contenido proporcionado en el cuerpo de la solicitud. Sólo enviar si la solicitud contiene un cuerpo. Por ejemplo podemos indicar en nuestra solicitud HTTP que la información que vamos a enviar al servidor estará en formato JSON.

Host: Este header siempre se debe enviar en las solicitudes HTTP. Representa al Host HTTP del servidor. Las aplicaciones probablemente ignorarán esto, sin embargo, es sobre todo útil para los hosts virtuales y el enrutamiento de solicitudes.

User-Agent: Este header incluye información de identificación del cliente, como por ejemplo el nombre del navegador web de donde se envía la solicitud HTTP.

Estos son solo algunos de los headers estandarizados que existen, pero también hay un montón de headers que puedes agregar de manera ad-hoc. Como regla general, al inventar sus propios headers, el patrón común es prefijarlo con una X por adelante, como por ejemplo X-API-Version para representar la versión del API.

Método GET

El método GET hace referencia a la acción de Leer (Read) del CRUD. Las solicitudes GET (GET requests) se consideran seguras, lo que significa que no deben alterar el estado del servidor. Las solicitudes GET se consideran idempotentes, lo que significa que deben ser repetibles sin causar efectos secundarios. Las solicitudes GET no deben tener un cuerpo (body request).

Cuando se usa el método GET contra una colección (por ejemplo /empresas) significa que deseas recuperar una lista de recursos dentro de esa colección (es decir una lista de empresas). Podemos recuperar todos los recursos o filtrar recursos específicos según los criterios definidos. El siguiente ejemplo es para obtener obtener una lista de empleados:

La solicitud anterior podría traducirse en “Obtener una lista de 10 empleados que trabajan en Twitter que estén en el rango salarial entre 3000 y 8000 (dólares por ejemplo), omitiendo los primeros 20“. El endpoint contiene parámetros de consulta (filtros) que inician luego del símbolo ? (? Key1 = Value1 & Key2 = Value2). Si no se especifican las propiedades de filtrado (parámetros de consulta), el servidor debe responder con todos los recursos coincidentes. Es común que los servidores tengan límites por defecto en los datos devueltos, de lo contrario sería muy abrumador devolver todos los datos de una colección, imagina que hubiesen millones de registros :0.

Método POST

El método POST hace referencia a la acción de Crear (Create) del CRUD. Las solicitudes POST (POST requests) se consideran Inseguras ya que alteran el estado del servidor. Se consideran no idempotentes ya que las solicitudes repetidas darán como resultado la creación de varios recursos. Las solicitudes POST deben tener un cuerpo (body request).

Cuando se usa el método POST contra una colección, el servidor debe crear un nuevo recurso dentro de esa colección.

La primera Linea de Solicitud podemos usarla para agregar una nueva empresa a nuestro servicio.

La segunda Linea de Solicitud podemos usarla para agregar un nuevo empleado a la empresa Twitter.

El cuerpo de la solicitud POST (body request) contendría información sobre el recurso que estamos agregado. Por ejemplo:

Método DELETE

El método DELETE hace referencia a la acción de Eliminar (Delete) del CRUD. Las solicitudes DELETE (DELETE requests) se consideran Inseguras ya que alteran el estado del servidor. Sin embargo, se consideran idempotentes, ya que al repetir esta acción DELETE, no debe tener ningún efecto secundario (es decir si por casualidad vuelves a invocar al endpoint con el verbo DELETE, no va eliminar un recurso que ya fue eliminado). Una solicitud DELETE no debe tener un cuerpo (body request).

La primera Linea de Solicitud es cómo podemos eliminar a un empleado (gchacaltana) de la empresa Twitter.

La segunda Linea de Solicitud es como podemos eliminar a un empleado con identificador gchacaltana.

Métodos PUT/PATCH

Los métodos PUT y PATCH hacen referencia a la acción de Actualizar (Update) del CRUD. Ambos se consideran Inseguros ya que alteran el estado del servidor. Por lo general se consideran Idempotent, es decir si invocamos a la misma solicitud varias veces debe tener el mismo resultado. Esto es cierto en la situación en la que está proporcionando propiedades de recursos y valores que se reemplazarán en un mismo recurso. Sin embargo, si su servicio tiene la capacidad de modificar una propiedad, como incrementar una propiedad, estas solicitudes se convertirían en no idempotentes. Los métodos PUT y PATCH deben tener un cuerpo.

¿Cuál es la diferencia entre PUT y PATCH?

Generalmente, una solicitud PUT realiza una actualización completa, las propiedades faltantes se actualizarán con valores nulos. Por ejemplo, un recurso de empleado podría tener como propiedades un nombre y un rol, pero realizar un PUT y sólo proporcionar un nombre, tendríamos un rol que falta. A diferencia de una solicitud PATCH, estas solicitudes se usan para realizar actualizaciones parciales. Sólo se establecerán las propiedades proporcionadas en el cuerpo de solicitud, las propiedades no listadas conservarán su valor existente. Algunas API sólo admiten PUT o PATCH para realizar cualquier actualización.

Métodos HEAD y OPTIONS

Los métodos HEAD y OPTIONS son un poco especiales. Se podría decir que hacen referencia a la acción Leer (Read) del CRUD pero en realidad no recuperan recursos. Se consideran seguros ya que no alteran el estado de la colección y además son idempotentes, ya que pueden volver a invocarse sin producir malos efectos. Tampoco deben tener un cuerpo de solicitud (body request).

La solicitud HEAD se utiliza para obtener sólo los headers (encabezados) de un recurso. Estos headers pueden contener metadatos útiles como cuando el recurso debe haber caducado. Si el costo de recuperar un recurso es alto (tal vez es un documento grande que es lento para transmitir o tal vez es una costosa llamada de base de datos), entonces podría tener sentido usar una solicitud HEAD en lugar de un GET.

La respuesta (response) del servidor sería:

En una siguiente publicación, hablaremos más a detalle de los HTTP Response.

La solicitud OPTIONS es útil para servicios expuestos a un navegador, por ejemplo, un navegador cliente puede enviar una solicitud OPTIONS y el servidor responde con headers que especifican que métodos HTTP puede utilizar el navegador y que otras funciones son soportadas por el servidor web. Por ejemplo:

El servidor podría enviar una respuesta así (HTTP Response).

El segundo artículo trata sobre una introducción a los HTTP Responses.

Para conocer la lista completa de artículos, dirigirse a Introducción al diseño de una API HTTP.

El poder de las bases de datos NoSQL

Las base de datos NoSQL han tenido un crecimiento exponencial en los últimos años, el uso acelerado por grandes empresas para escalar sus aplicaciones transaccionales demuestran que este tipo de tecnología se esta convirtiendo en una excelente alternativa para almacenar información. Por citar algunos ejemplos:

Tesco, uno de los más grandes supermercados del mundo, utiliza base de datos NoSQL para soportar su catálogo de productos, precios, inventarios y sistemas de cupones.

McGraw-Hill, una reconocida firma editorial de presencia mundial, líder en la enseñanza digital, utiliza base de datos NoSQL para impulsar el aprendizaje en linea de su plataforma e-learning.

Sky TV, una importante cadena de televisión satelital, utiliza base de datos NoSQL para administrar los perfiles de usuario de sus más de 20 millones de suscriptores.

Neiman Marcus, una lujosa tienda por departamento de presencia global , utiliza base de datos NoSQL para almacenar los intereses personalizados de sus clientes a través de todos sus canales de venta.

Sabre, uno de los más grandes sistemas de servicio de datos de vuelos del mundo (desarrollada por American Airlines), utiliza base de datos NoSQL para almacenar información de vuelos, pasajeros, rutas, entre otras muchas cosas.

KDDI Corporation, la segunda más grande compañía de telecomunicaciones de Japón, utiliza base de datos NoSQL para administrar las plataformas de sus servicios cloud.

El Ministerio de Salud de Turquía utiliza base de datos NoSQL para almacenar el historial clínico de sus más de 77 millones de ciudadanos.

Ryanair, la más grande aerolínea irlandesa de bajo coste, utiliza base de datos NoSQL en sus aplicaciones móviles para ofrecer una excelente experiencia de venta de pasajes a sus millones de usuarios.

Paypal, sistema de pagos en linea que opera en casi todo el mundo, utiliza base de datos NoSQL para monitorear en tiempo real el tráfico de visitas a su aplicación web.

La lista se hace extensa,muy extensa.

Pero ¿Cómo sucedió esto?

A mediados del 2009, el uso de las base de datos NoSQL eran limitados a empresas de internet como Google, Facebook, Amazon y LinkedIn. Hoy en día, las empresas de casi todas las industrias están implementando soluciones basadas en base de datos NoSQL. Están recurriendo a NoSQL para superar las limitaciones de las tradicionales tecnologías de base de datos relacionales. Y están eligiendo soluciones NoSQL open source sobre productos relacionales licenciados como Oracle, IBM y Microsoft por obvias razones económicas.

Muchas aplicaciones web utilizan una base de datos relacional como fuente principal de almacenamiento transaccional pero utilizan base de datos NoSQL para búsquedas distribuidas y almacenamiento en cache.

El Poder NoSQL

Hay varias razones posibles por las que las empresas están prefiriendo utilizar soluciones NoSQL, pero el escenario más común es probablemente cuando un servidor de base de datos relacional ya no es suficiente para manejar su alta carga transaccional. Las bases de datos NoSQL son mucho más adecuadas para distribuir la carga sobre los servidores de bases de datos.

Esto se debe a que las bases de datos relacionales tratan tradicionalmente el equilibrio de carga mediante la replicación. Esto significa que tiene varias bases de datos esclavos que observan a una base de datos maestra para los cambios y se replican a ellos mismos, el famoso modelo Master/slave. Las aplicaciones utilizan las bases de datos esclavo (Slave) para las lecturas de información, y las escrituras las hacen a la base de datos maestra (Master).

Esto funciona a un cierto nivel, pero tiene el efecto secundario que las base de datos esclavos siempre se quedan un poco atrás, por lo que hay un retraso entre el tiempo de escritura y el tiempo que los datos están disponibles para la lectura. Además, la única base de datos maestra eventualmente se convierte en un cuello de botella, no importa lo poderoso que sea el hardware, el riesgo siempre estará latente.

Las base de datos NoSQL generalmente resuelve este problema mediante el sharding, esto significa que los usuarios con IDUser de 1 a 1000000 están en el servidor A, y los usuarios con IDUser 1000001 a 2000000 están en el servidor B y así sucesivamente. Esto resuelve los problemas de replicación de las bases de datos relacional, pero el inconveniente es que las características tales como las consultas agregadas (SUM, AVG, MAX, MIN) y las transacciones tradicionales se sacrifican.

Casos de Negocio y NoSQL

Las principales soluciones tecnológicas adquiridas por grandes compañías que utilizan base de datos NoSQL son:

1. Administración de perfiles de cuentas de usuarios
2. Aplicaciones Real Time
3. Big Data
4. Gestión de contenidos
5. Administración de clientes 360°
6. Aplicaciones móviles
7. Internet de las cosas (IoT)
8. Comunicación Digital
9. Inteligencia Artificial (AI)
10. Sistemas de Anti-fraudes
11. Sistemas Centralizados de Eventos y Transacciones
12. Analítica Web

NoSQL ha captado claramente el interés e imaginación de los responsables de TI, como una solución escalable, flexible y segura en la que puedan confiar. El respaldo de grandes firmas tecnológicas como Google, Facebook y Amazon avalan que las base de datos NoSQL deban formar parte del stack tecnológico de muchas empresas.

Sistemas de Base de Datos NoSQL

Cada tecnología de base de datos NoSQL resuelve un problema diferente, por ejemplo, algunos están optimizados para ofrecer alta disponibilidad o alta escritura por segundo, distribuido, almacenado en memoria RAM, etc.

Entre las bases de datos NoSQL más destacadas, podemos encontrar a:

Si utilizas otra base de datos NoSQL, por favor compartirlo en un comentario.

Para conocer más de Redis, puedes ingresar a: