Resumen de API REST y RESTful
156 Visitas 15 minutos Enlace Permanente
API sencilla basada en HTTP y con datos en formato JSON
APIs
- Tipos de APIs:
- Sistema Operativo: acceder a los recursos del sistema (ej. Win32 API).
- Librería: acceder a módulos reutilizables dentro de un programa (ej. interfaz de una DLL).
- Remota: acceder a recursos de otro sistema, con la misma plataforma, a través de una red.
- Web: acceder a recursos de otro sistema a través de HTTP, aunque sea de otra plataforma.
- Tipos de APIs Web:
- SOAP: basado en XML con peticiones tipo RPC y orientado a la conexión (obsoleto).
- REST: basado en JSON con peticiones tipo HTTP y sin conexión.
- GraphQL: basado en JSON con peticiones tipo SQL y sin conexión (más potente pero más complejo).
- gRPC: basado en Protobuf con peticiones tipo HTTP2 (bidireccional, streaming).
API REST
Básico
- Programas: Postman, Beeceptor.
- Mensajes:
- Petición: <verbo-HTTP> <URI> <cabeceras-HTTP> [<cuerpo>]
- Respuesta: <código-respuesta> <cabeceras-HTTP> [<cuerpo-JSON>]
- Verbos HTTP:
- Más Importantes (CRUD):
- GET: obtener uno o varios recursos (nunca lleva <cuerpo>).
- POST: crear un nuevo recurso.
- DELETE: borrar un recurso (nunca lleva <cuerpo>, el identificativo va siempre en la URI).
- PUT: actualizar al completo un recurso existente.
- El identificativo del recurso puede ir en los datos del <cuerpo> o en la URI.
- Si el recurso no existe, puede crearlo (es una opción).
- Menos Usados:
- PATCH: actualizar parcialmente un recurso existente.
- HEAD: igual que GET pero sin <cuerpo-JSON> en la respuesta (saber si existe el recurso).
- OPTIONS: lista de verbos HTTP que admite el servidor.
- TRACE: probar si la petición llega al servidor (depuración).
- Idempotencia:
- Una acción se puede aplicar varias veces y el resultado debe ser siempre el mismo.
- Todos los verbos, salvo POST y PATCH, deben ser idempotentes.
- Estructura URI (Endpoint):
- Obligatorios: nunca se usan verbos, solo sustantivos.
- /api: siempre indicar que es una API (alternativa: usar subdominio, ej. api.dominio.com).
- /v1: versión de la API (usar números enteros).
- /entidad: la entidad con la que trabajar (se puede jerarquizar. ej. /categoria/entidad).
- Opcionales: si aparecen, debe ser en este orden.
- /{idEntidad}: el identificativo de la identidad a tratar.
- /subentidad: una entidad que hay dentro de otra (ej. /casa/1/cocina).
- /{idSubEntidad}: el identificativo de la subentidad a tratar.
- ?param1=valor¶m2=valor: parámetros pasados por “query string” (búsquedas GET).
- Uso de Plurales:
- En general, se usa el singular porque se trabaja con una única entidad.
- La excepción son las búsquedas o listas, ya que se devuelve un conjunto de entidades.
- El singular o plural debe indicar si se devuelve una única entidad o varias.
- Códigos de Respuesta:
- 1xx: informativos (no se usan).
- 2xx: éxito.
- 200 OK: GET y POST. Todo ha ido bien. Devuelve la entidad solicitada o creada.
- 201 Created: POST. La entidad se ha creado correctamente, devuelve la URI del nuevo recurso.
- 202 Accepted: POST y PUT. Petición aceptada pero pendiente de procesarse.
- 204 No Content: PUT, DELETE. Fue bien, pero no devuelve nada (ej. listas grandes).
- 3xx: redirecciones (no se usan).
- 4xx: errores de cliente.
- 400 Bad Request: TODOS. La petición está mal formada o con datos incorrectos (RFC 7807).
- 401 Unauthorized: TODOS. El usuario debe autenticarse para acceder al recurso.
- 403 Forbidden: TODOS. La autenticación falló y no se puede acceder al recurso.
- 404 Not Found: TODOS. El recurso solicitado no existe (no usar con “query strings”).
- 405 Method Not Allowed: TODOS. La entidad indicada no admite ese verbo HTTP.
- 409 Conflict: POST y PUT. Ha ocurrido un conflicto de versiones.
- 422 Unprocessable Entity: TODOS. Por alguna razón, no se puede llevar a cabo el proceso.
- 5xx: errores de servidor.
- 500 Internal Server Error: TODOS. Una excepción ocurrió en el servidor y no se procesó nada.
- Búsquedas:
- Por defecto, usar GET pasando los parámetros como “query strings”:
GET /api/v1/pedidos?tipo=zapatos&fecha=2022-04-07 - Si son muchos parámetros, usar POST y pasarlos en el <cuerpo> (nunca como “query strings”).
- Acciones:
- Hay que evitarlo en la medida de lo posible (pero a veces aporta legibilidad y facilidad de uso).
- Siempre con POST y al final de la URI: /api/v1/luz/encender
Avanzado
- Documentación:
- Swagger/OpenAPI: estándar de facto para documentar APIs REST síncronas (asíncronas: AsyncAPI).
- Incluye: endpoints, parámetros, autenticación e información general.
- Puede generar tanto la propia API como las librerías de cliente de forma automática.
- Algunas librerías de lenguajes permiten generar la documentación de forma automática.
- Formato: archivo JSON cuya especificación está en https://swagger.io/specification/
- .NET Core:
- Paquete: Swashbuckel.AspNetCore
- En el archivo.csproj, agregar las siguientes líneas dentro de <Project>:
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
- En Startup.ConfigureServices, agregar services.AddSwaggerGen(c => {…})
- Dentro, configurar c.SwaggerDoc(…) e c.IncludeXmlComments(path).
- En Startup.Configure, agregar app.UseSwagger() y app.UseSwaggerUi(c => {…})
- Dentro del UseSwaggerUi, configurar c.SwaggerEndpoint(jsonPath)
- Versionado:
- Siempre incluir versiones de nuestra API.
- No cambiar una API que se está consumiendo ya (salvo bugs), hay que crear una nueva versión.
- Se puede implementar de 3 formas:
- En la URI (la más común): /api/v1/entidad
- En el “Query String” (evitar totalmente): /api/entidad?version=1
- En las Cabeceras HTTP (la más correcta): Accept: application/vnd.nombre.v1+json
- Seguridad:
- Autenticación (AuthN): quién eres.
- Autorización (AuthZ): si tienes permisos o no.
- OAuth2: protocolo estándar de autenticación y autorización. https://oauth.net/2/
- El API debe registrarse previamente en un servidor de autenticación (Google, Microsoft, etc.)
- La aplicación llama al API de forma anónima.
- La API le pide a la aplicación que se redirija al servidor de autenticación.
- El servidor de autenticación comprueba las credenciales del usuario.
- El servidor de autenticación comprueba si el usuario tiene permitido acceder al recurso del API.
- El servidor de autenticación devuelve un token de acceso con información de AuthN y AuthZ.
- La aplicación guarda el token en un cookie (con un tiempo de validez) y lo envía a la API.
- La API comprueba el token para comprobar su información de AuthN y AuthZ.
- JWT (JSON Web Token): https://jwt.io/
- Token de acceso estándar en formato JSON.
- Cabecera (header): tipo de token y algoritmo de firma.
- Carga (payload): datos del usuario (nombre, rol, etc.), pero cuantos menos datos, mejor.
- Firma (signature): firma digital de la cabecera y la carga.
- Se codifica todo en Base64, separando cada parte por un punto.
- Se envía en la cabecera HTTP Authoritation: Bearer <JWT>
- Rendimiento:
- Async: usar asincronía (async/await) cuando se accede a recursos externos (IO, red, BDs, etc.)
- Caching: almacenar en memoria datos que se solicitan frecuentemente y que no cambian.
- Rate Limit: limitar el número máximo de peticiones concurrentes a una API.
- Quota: limitar el número máximo de peticiones que puede realizar un usuario.
- Monitorización:
- Una API siempre debe estar monitorizada:
- Detectar problemas antes de que ocurran.
- Analizar problemas después de que ocurran.
- Saber qué está ocurriendo en cada momento.
- Métricas:
- Peticiones por segundo.
- Número y porcentaje de fallos.
- Latencia (tiempo en contestar una vez recibida una petición).
- CPU, RAM y disco.
- Número de usuarios.
- Número de sesiones.
- Distribución geográfica.
- Azure: Insight.
- HATEOAS: Hypermedia As The Engine Of Application State
- No solo envía los datos de una entidad, sino que también los datos de sus entidades relacionadas.
- Se pueden incluir los datos como tal o indicar las URIs a dichos recursos.
- Desacoplar Servicios:
- API Gateway:
- El cliente se comunica solo con el gateway y este lo hace con el resto de servicios.
- Puede aportar también balanceo de carga, AuthN/AuthZ, monitorización, políticas o enrutado.
- Puede provocar cuellos de botella.
- API Discovery:
- Un servicio de directorio guardará las URIs del resto de servicios.
- Cuando alguien quiere comunicarse en un servicio, primero preguntar por su URI al directorio.
- Los servicios deben registrarse en el directorio para que puedan ser usados.
- El registro y desregistro, así como las URIs, pueden ser dinámicas.
- Puede aportar balanceo de carga (pero no AuthN/AuthZ, monitorización o políticas).