Resumen de API REST y RESTful

156 Visitas 15 minutos Enlace Permanente

API sencilla basada en HTTP y con datos en formato JSON

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&param2=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.
  • 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).

Anexos

Recursos