Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Diseña APIs como si supieras lo que haces

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on. →

Diseña APIs como si supieras lo que haces

En la charla se tratan principios básicos de diseño de APIs, así como estandares de cumplimiento REST, y ejemplos prácticos de APIs reales (como facebook, twitter o netflix, marvel comics).

Se tratan conceptos como la semántica de recursos, requests, responses, paginación, errores y versionado.

Charla para OpenSouthCode impartida el 2 de Junio de 2018.

https://www.opensouthcode.org/conferences/opensouthcode2018/program/proposals/158

Avatar for Francisco M. González

Francisco M. González

June 02, 2018

More Decks by Francisco M. González

Other Decks in Technology

Transcript

  1. Índice - Economía de APIs - API REST - Semántica

    - Requests - Responses - Búsquedas y paginación - Errores - Versionado @fmgonzalez76
  2. Economía de APIs - ¿Cuándo empezamos a hablar de APIs?

    - ¿Tiene sentido en el contexto de una aplicación in-house? - Sí, para consumo propio también tiene sentido. - Aumenta la mantenibilidad y la escalabilidad - Así empiezan los microservicios - APIs como producto final, como modelo de negocio @fmgonzalez76
  3. Modelos de negocio - Por acceso / uso - Cuotas

    - APIs Fremium / Premium - Orientada a desarrolladores @fmgonzalez76
  4. API REST Largo recorrido: - CORBA (1991) - SOAP (1998)

    - REST (2000) - GraphQL? (2015) @fmgonzalez76
  5. API REST - Arquitectura orientada a recursos - No guarda

    el estado - Niveles de cumplimiento: - Uso correcto de URL - Uso correcto de HTTP - Uso correcto de Hypermedia @fmgonzalez76
  6. Semántica de REST (recursos) Vamos a escribir un API para

    mantener nuestros clientes. - /addNewClient - /showClient - /updateClient - /deleteClient - /deleteAllClients - /showAllClients - /showBestClients - … @fmgonzalez76
  7. Semántica de REST (recursos) Vamos a escribir un API para

    mantener nuestros clientes. - /addNewClient - /showClient - /updateClient - /deleteClient - /deleteAllClients - /showAllClients - /showBestClients - … @fmgonzalez76 MAL: - Crece sin control - Difícil de mantener - Funcionalidades redundantes - Inconsistencias
  8. Semántica de REST (recursos) - Todo son recursos. - Nombres

    bien. Verbos mal. - Sólo nombres en plural (consistencia) - Para identificar un único recurso utilizamos un id en la url @fmgonzalez76
  9. Semántica de REST (recursos) Twitter: - GET statuses/show/:id - GET

    statuses/lookup - POST favorites/create/:id https://developer.twitter.com/en/docs/tweets /post-and-engage/overview @fmgonzalez76 Marvel Comics: - GET /v1/public/comics - GET /v1/public/comics/:id - GET /v1/public/series - GET /v1/public/series/:id https://developer.marvel.com/docs
  10. Request en REST (verbos HTTP) - GET /comics - GET

    /comics/:id - POST /comics - PUT /comics/:id - PATCH /comics/:id - DELETE /comics/:id - RESTafarians @fmgonzalez76
  11. Request en REST (verbos HTTP) - GET /characters - GET

    /characters/1234 Recursos anidados - GET /comics/1234/characters - GET /comics/1234/characters/5678 @fmgonzalez76
  12. Request en REST (verbos HTTP) - GET /characters - GET

    /characters/1234 Recursos anidados - GET /comics/1234/characters - GET /comics/1234/characters/5678 @fmgonzalez76
  13. Request en REST (verbos HTTP) - GET /characters - GET

    /characters/1234 Recursos anidados - GET /comics/1234/characters - GET /comics/1234/characters/5678 @fmgonzalez76 Por consistencia. Intentaremos evitar la duplicidad.
  14. Request en REST (verbos HTTP) - POST /characters - PUT

    /characters/1234 - PATCH /characters/1234 - DELETE /characters/1234 Recursos anidados - POST /comics/1234/characters - DELETE /comics/1234/characters/5678 - PUT? PATCH? @fmgonzalez76
  15. Request en REST (Formato) - GET /characters/1234.json - GET /characters/1234.xml

    O mejor, usa el parámetro Accept del HEADER de la petición. - GET /characters/1234 Accept: application/xml, application/json, application/html @fmgonzalez76
  16. Request en REST (Multi idioma) La mejor opción vuelve a

    ser utilizar el parámetro Accept-Languaje del header. Accept-Languaje: es-ES;es;en-US;en @fmgonzalez76
  17. Responses en REST (HTTP Status Codes) 2xx (OK) - 200

    Ok. Para peticiones GET que han sido exitosas - 201 Created. Para peticiones POST de creación que han sido exitosas - 202 Accepted. Para peticiones válidas que serán atendidas en otro momento (tareas encoladas). - 204 No Content. Para peticiones DELETE que han sido exitosas. @fmgonzalez76
  18. Responses en REST (HTTP Status Codes) 3xx (Redirecciones) - 304

    Not Modified. Cuando se asume que el cliente ya tiene esa información y no se quiere devolver la misma información de nuevo. @fmgonzalez76
  19. Responses en REST (Content) GET /characters/1234 { “id”: 1234, “name”:

    Batman, “location”: Gotham city } @fmgonzalez76
  20. Responses en REST (Content envelope) GET /characters/1234 { “data”: {

    “id”: 1234, “name”: Batman, “location”: Gotham city } } @fmgonzalez76
  21. Responses en REST (Content colecciones) GET /characters/ { “data”: [

    { “id”: 1234, “name”: Batman, “location”: Gotham city }, { “id”: 1235, “name”: Robin, “location”: Gotham city }, ... ] } @fmgonzalez76
  22. Responses en REST (Content metas) GET /characters/ { “data”: [

    { “id”: 1234, “name”: Batman, “location”: Gotham city }, ... ], “meta”: { “nextPage”: /characters?page=2, “lastPage”: /characters?page=12 } } @fmgonzalez76
  23. Responses en REST (Content HATEOAS sample) GET /characters/ { “data”:

    [ { “id”: 1234, “name”: Batman, “location”: Gotham city, “_links”: { “self”: /characters/1234, “teams”: /teams?member=1234 } }, ... ] } @fmgonzalez76
  24. Responses en REST (Content HATEOAS sample) Netflix: … "_links" :

    { "self" : { "href" : "https://genie.example.com/api/v3/jobs/425c4a6a-a069-4849-a66e-d08d6e8d1912" }, "output" : { "href" : "https://genie.example.com/api/v3/jobs/425c4a6a-a069-4849-a66e-d08d6e8d1912/output" }, "status" : { "href" : "https://genie.example.com/api/v3/jobs/425c4a6a-a069-4849-a66e-d08d6e8d1912/status" }, ... https://netflix.github.io/genie/docs/3.0.0/rest/ @fmgonzalez76
  25. Responses en REST (jsonApi) GET /characters/1234 { “data”: { “id”:

    1234, “type”: character, “attributes”: { “name”: Batman, “location”: Gotham } } @fmgonzalez76
  26. Responses en REST (jsonApi) { “data”: { “id”: 1234, “type”:

    character, “attributes”: { “name”: Batman, “sidekick”: { “id”: 1235, “type”: character, } } }, “includes”: [ { “id”: 1235, “type”: character, “attributes”: {...} } ] } @fmgonzalez76
  27. Responses en REST (jsonApi) { “data”: { “id”: 1234, “type”:

    character, “attributes”: { “name”: Batman, “sidekick”: { “id”: 1235, “type”: character, } } }, “includes”: [ { “id”: 1235, “type”: character, “attributes”: {...} } ] } @fmgonzalez76
  28. Responses en REST (jsonApi) { “data”: { “id”: 1234, “type”:

    character, “attributes”: { “name”: Batman, “sidekick”: { “id”: 1235, “type”: character, } } }, “includes”: [ { “id”: 1235, “type”: character, “attributes”: {...} } ] } @fmgonzalez76
  29. Búsquedas - Simplifica las relaciones GET /comics/1234/characters - Y lleva

    la complejidad a la query string GET /comics/1234/characters?role=guest&type=hero @fmgonzalez76
  30. Errores - Nunca devolver códigos de error personalizados. - Utilizar

    los códigos de estado de HTTP. - Siempre que sea posible los mensajes de HTTP. @fmgonzalez76
  31. Errores (HTTP Status Codes) 4xx (Errores del cliente) - 400

    Bad Request. Indicamos que no hemos procesado la petición, porque la petición no era válida. - 403 Forbidden. No procesamos la petición, por falta de privilegios. - 404 Not Found. El recurso no existe. - 406 Not Acceptable. No podemos devolver el recurso en el formato solicitado en el Accept header. @fmgonzalez76
  32. Errores (HTTP Status Codes) 5xx (Errores del servidor) - No

    queremos devolver ninguno de estos. @fmgonzalez76
  33. Errores (Códigos propios) Facebook Status Code: 200 OK { “error”:

    { “type”: "Exception", “code”: 103, "message":"Incorrect signature" } } https://developers.facebook.com/docs/marketing-api/error-reference @fmgonzalez76
  34. Versionado (en la url) Marvel Comics GET /v1/public/comics Twitter GET

    /1.1/search/tweets.json?q=from%3ANasa%20OR%20%23nasa @fmgonzalez76
  35. Versionado (en el header) - Añadiendo un parámetro propio en

    el header - Por ejemplo: franci-api-version: 1.1 - Las url siempre son las mismas. - Pero se añade una cabecera no estándar. @fmgonzalez76
  36. Consistencia - Elige un criterio y mantenlo - Documenta tus

    decisiones antes que tu API - Un API consistente es más fácil de utilizar que un API documentada llena de inconsistencias @fmgonzalez76