👉 Ver todas las notas
- API
- REST
- CRUD
- API Key
- Endpoint
- Verbos HTTP
- HTTP Status Codes
path params
vsquery params
en una API REST- Ejercicio
Application Programming Interface), define una interfaz con ciertas operaciones, que nos permiten interactuar con una aplicación hosteada en un servidor.
Nos permite agregar una barrera de seguridad: el cliente no puede acceder directamente a la DB sino a través de la API.
Una API expone datos y diferentes tipos de acciones que podemos realizar, a través de los endpoints, por ejemplo
- Información disponible
- Servicios
- Parámetros
- Formato de la respuesta
Una API forma parte del backend de una aplicación y es independiente de los lenguajes y plataformas que utilicemos.
REST (Representational State Transfer) es una convención para desarrollar servicios web (APIs), basados en el protocolo HTTP. Vamos a llamar APIs REST a las APIs que desarrollemos siguiendo estas convenciones.
- Utilizamos URLs para definir recursos
JSON
como formato de intercambio- Acciones basadas en los verbos HTTP (utilizamos el protocolo HTTP para transferir datos)
- Uso de los status HTTP (
200 - ok
,404 - resource not found
,500 - server error
, etc) - Stateless: los datos del cliente no se almacenan en el servidor entre requests. Cada request contiene toda la info necesaria para ser ejecutada, por lo que que ni el cliente ni el servidor necesitan recordar ningún estado previo.
- Arquitectura cliente<->servidor: hay una separación de responsabilidades entre el frontend (cliente) y el backend (server). Operan de forma independiente entre sí y ambos pueden ser reemplazados.
- Cache: la data que proviene del server puede ser cacheada en el cliente, lo cual nos permite obtener mejoras de performance.
- Sistema de capas: el cliente no necesita saber si está interactuando directamente con un servidor, proxy, load balancer, etc.
- Interfaz uniforme cada recurso del servicio REST debe tener una única dirección, "URI", que simplifica la interacción entre el cliente y el servidor.
👉 Ver más detalles en Core Principles of RESTful API
Una API REST nos permite desarrollar servicios para crear, leer, actualizar o eliminar datos, conocidos como CRUD operations por sus siglas en inglés (Create, Read, Update, Delete).
Sirve para identificar al usuario/cliente que está realizando el request. Generalmente se utiliza para aplicar rate limiting (limitar los recursos del servidor que podemos consumir de forma gratuita, por ejemplo bloqueando los requests después de cierta cantidad).
Para más info, ver Use Web APIs.
Un endpoint de una API REST expone un recurso o una colección de recursos para que sean consumidos. Un endpoint incluye el tipo de acción (request) a realizar con el recurso (o la colección), la ruta y los parámetros necesarios. El tipo de acción está basado en los verbos HTTP (GET
, POST
, PUT
, DELETE
, etc). Por ejemplo
Los endpoints que definamos tienen que resolver el siguiente problema: proveer una forma uniforme de identificar los recursos disponibles (interfaz uniforme)
Request 1
GET /api/customers
Response 1
[
{ "id": 1, "name": ...},
{ "id": 2, "name": ...},
...
]
Request 2
GET /api/customers/7
Response 2
{ "id": 7, "name": ...}
Endpoints
GET /api/customers
GET /api/customers/7
POST /api/customers
PUT /api/customers/1
DELETE /api/customers/2
GET
: Leer data de un recurso existente, sin modificarlo.POST
: Crear un nuevo recurso en el server, usando la info enviada en el payload del request. Por convención, cuando creamos un nuevo recurso, debemos retornar el objeto que lo representa en elresponse
.PUT
: Actualizar un recurso existente, usando la info enviada en el payload del request. En el caso de que el recurso no exista, lo crea.DELETE
: Eliminar un recurso existente.
Ver httpstatuses.com
Ver When do I use path params vs. query params in a RESTful API?
Vamos a crear una API REST con Express
. La misma tendrá información sobre películas, almacenada en un array.
El formato de las películas será el siguiente:
movie = {
"id": 1,
"title": "Back to the Future",
"year": 1985,
"genre": "Science Fiction"
}
- Acá hay ejemplos de películas para usar y acá tenés un JSON con muchas más.
- El array de películas estará inicialmente vacío. Se recomienda utilizar un módulo aparte para el array (importarlo donde sea necesario) y definirle una API para interactuar con el mismo (ejemplo, si el array se llama
movies
, definir la operaciónmovies.add
para agregar una nueva película, etc) - El
id
se calcula al agregar una nueva película (no forma parte del payload del request), según el orden (la primera tendráid=1
, la segundaid=2
, etc). - Utilizar el
Router
deExpress
para definir la lógica de routing en un módulo aparte, y setear/api
como prefijo de todas las rutas. Utilizar el métodoroute()
, para definir las rutas de una forma más declarativa. - Utilizar
nodemon
para desarrollar. - En caso de necesitar debuggear la aplicación, utilizar esta guía.
GET /api/movies
: retorna el array de películas, en formatoJSON
.GET /api/movies/:id
: retorna la película con elid
correspondiente, en formatoJSON
. En el caso de que no exista, generar el error"404 - The movie with the id {ID} was not found"
(donde ID es el parámetro utilizado) constatus code
404 y pasarle el objetoerr
anext
.POST /api/movies
: agrega una nueva película, con la info especificada más arriba. Validar elbody
del request como se indica más abajo. Si es inválido, generar el error"400 - Bad Request"
y pasarle el objetoerr
anext
, sino, agregar la película correspondiente y retornar la info de la misma en elresponse
.PUT /api/movies/:id
: actualiza la info de una película (title
óyear
, elid
no puede editarse). Para esto, primero debe buscarla por elid
y si no existe, debe agregar la nueva película, con elid
correspondiente.DELETE /api/movies/:id
: elimina la película con elid
correspondiente. Para esto, primero debe buscarla por elid
, si no existe, generar el error"404 - The movie with the id {ID} was not found"
(donde ID es el parámetro utilizado), y unstatus code
404 y pasarle el objetoerr
anext
.GET /api/movies/genres
: retorna la lista de géneros (sin repetir), correspondientes a las películas que tengamosGET /api/movies/years
: retorna la lista de años (sin repetir), correspondientes a las películas que tengamos
- Si se utiliza el query string
?year=
conGET /api/movies
, debe retornarse la lista de películas correspondientes a ese año, en formatoJSON
. - Si se utiliza el query string
?genre=
conGET /api/movies
, debe retornarse la lista de películas correspondientes a ese género, en formatoJSON
. - Si se utilizan los query strings
?sortBy=title
ó?sortBy=year
con el endpointGET /api/movies
, debe retornarse la lista de películas ordenada por año ó nombre de forma ascendente, respectivamente.
En ambos casos, si no hay películas para mostrar, debe retornarse el array vacío []
(siempre como JSON
).
Utilizar el middleware express-validator
para realizar las siguientes validaciones sobre el input (body
del request)
title
: debe existir y tener al menos 2 caracteres, sino generar el errormovie title is required and should have minimum 2 characters.
, constatus code
400 y pasarle el objetoerr
anext
.year
: debe ser un valor numérico entre 1800 y 2020, sino generar el errormovie year is required and should be a number between 1800 and 2020.
, constatus code
400 y pasarle el objetoerr
anext
.
Router
deExpress
- Error-handling middleware (ver detalles en helpful-express-middleware)
express-validator
, para realizar las validaciones correspondientesmorgan
, para loguear en la terminal todos los requests y responses generados