Diseño de APIs con Ruby   Edwin Cruz @softr8
PLAN• Que   es una API• Como   implementar una buena API• Usando   Ruby on Rails para implementar una API• Patrones   de d...
“   Application    Programming    Interface                  “
API  Es una manera para     comunicar dosaplicaciones entre ellas.
TIPOS DE API• Library• SDK• Web   services
PRIMERAS API - SOAP       Simple       Object       Access       Protocol
RESTREpresentationStateTransfer
REQUISITOS REST
REQUISITOS RESTSeparación de responsabilidades
REQUISITOS RESTSeparación de responsabilidadesCliente/Servidor
REQUISITOS RESTSeparación de responsabilidadesCliente/ServidorSin estado
REQUISITOS RESTSeparación de responsabilidadesCliente/ServidorSin estadoPuede ser “Cacheable”
REQUISITOS RESTSeparación de responsabilidadesCliente/ServidorSin estadoPuede ser “Cacheable”Sistema a capas
REQUISITOS RESTSeparación de responsabilidadesCliente/ServidorSin estadoPuede ser “Cacheable”Sistema a capasInterface unif...
CRUDCreate   AltasRead     BajasUpdate   CambiosDelete   Consultas
REST + CRUD
REST + CRUD   Recursos a través de URLs únicasUsando correctamente los verbos HTTP
RECURSO
RECURSOCualquier accion expuesta a travez de un servidorweb
RECURSOCualquier accion expuesta a travez de un servidorwebTienen una representación en datos
RECURSOCualquier accion expuesta a travez de un servidorwebTienen una representación en datosCon un servicio web intercamb...
REST-ISH + JSON
REST-ISH + JSON       =
REST-ISH + JSON         =  Cosas Increibles
¿PORQUÉ UN API?
¿PORQUÉ UN API?Aumenta la flexibilidad y utilidad de tus              aplicaciones
¿PORQUÉ UN API?Aumenta la flexibilidad y utilidad de tus              aplicaciones     Proporciona valor de negocio
¿PORQUÉ UN API?Aumenta la flexibilidad y utilidad de tus              aplicaciones     Proporciona valor de negocio Ayuda a...
¿QUÉCARACTERÍSTICAS?
¿QUÉCARACTERÍSTICAS? Fácil de implementar y mantener
¿QUÉCARACTERÍSTICAS? Fácil de implementar y mantener Buen rendimiento
¿QUÉCARACTERÍSTICAS? Fácil de implementar y mantener Buen rendimiento Escalable
¿CUÁLES SON LOS    RETOS?
¿CUÁLES SON LOS           RETOS?La red es un eslabón débil, GEO localizacion de losclientes
¿CUÁLES SON LOS           RETOS?La red es un eslabón débil, GEO localizacion de losclientesAdministrar Cambios
¿CUÁLES SON LOS           RETOS?La red es un eslabón débil, GEO localizacion de losclientesAdministrar CambiosUso indebido
¿CUÁLES SON LOS           RETOS?La red es un eslabón débil, GEO localizacion de losclientesAdministrar CambiosUso indebido...
¿CUÁLES SON LOS           RETOS?La red es un eslabón débil, GEO localizacion de losclientesAdministrar CambiosUso indebido...
¿CUÁLES SON LOS           RETOS?La red es un eslabón débil, GEO localizacion de losclientesAdministrar CambiosUso indebido...
DISEÑAR UNA BUENA        API
CONVENCIONES REST
USAR CORRECTAMENTE    VERBOS HTTP
REST + CRUD                       GET /api/products #Listado{"products" :  [    {"product" : { "id" : 1, "name" : "Product...
REST + CRUD                         GET /api/products/2 #Ver{"product" : { "id" : 2, "name" : "Producto 2", "status" : "ac...
REST + CRUD                       POST /api/products #Crear{    "name" : "Producto 2"}
REST + CRUD                  PUT /api/products/2 #Actualizar{    "name" : "Producto dos"}
REST + CRUDDELETE /api/products/2 #Eliminar
VERSIONES DE LA API• API   Interna (entre aplicaciones)• API   Externa (aplicacion movil ? )• API   Usuarios (publico en g...
VERSIONANDO TU API    /int/api/products    /ext/api/products    /pub/api/products
VERSIONANDO TU API /int/api/products?version=2 /ext/api/products?version=2 /pub/api/products?version=2
VERSIONANDO TU API   /v2/int/api/products   /v2/ext/api/products   /v2/pub/api/products
VERSIONANDO TU APIhttp://int.myapp.com/productshttp://api.myapp.com/products
MUNDO IDEAL
MUNDO IDEALUso de: Accept Header
MUNDO IDEALUso de: Accept HeaderAccept: application/vnd.mycompany.com;version=2,application/json
CODIGOS HTTP200 OK201 Created202 Accepted400   Bad Request401   Unauthorized402   Payment Required404   Not Found409   Con...
CODIGOS HTTPHTTP/1.1 200 okGET /v1/products{"products" :  [    {"product" : { "id" : 1, "name" : "Producto 1", "status" : ...
CODIGOS HTTP HTTP/1.1 201 Created POST /v1/products {   “product”: [     “name” : “name”   ] }
CODIGOS HTTPHTTP/1.1 400 Bad Request{  “errors”: [    “Estructura JSON no valida”,    “unexpected TSTRING, expected ‘}’ at...
CODIGOS HTTPHTTP/1.1 401 Unauthorized{    “errors”: [      “api_key not found”    ]}
CODIGOS HTTPHTTP/1.1 401 Unauthorized{  “errors”: [    “api_key no valida”,    “api_key no puede contenerespacios”  ]}
CODIGOS HTTPHTTP/1.1 401 Unauthorized{  “errors”: [    “api_key no encontrada, por favorvisita http://account.myapp.com/ap...
CODIGOS HTTPHTTP/1.1 422 Unprocessable Entity{  “errors”: [     “vendor_code: no puede estar vacio”  ],  “documentacion”: ...
CODIGOS HTTPHTTP/1.1 500 Internal Server Error{    “exception”: [      “Base de datos no disponible”    ]}
CODIGOS HTTPHTTP/1.1 503 Service Unavailable{    “messages”: [      “En mantenimiento”    ]}
OPCIONES AVANZADAS• Simuladores• Autenticación• Validadores• Limite   de uso• Rapidez• Balanceo
USANDO RUBY ON     RAILS PARAIMLEMENTAR UNA API
APIS ON RAILS - REST#config/routes.rbMyApp::Application.routes.draw do  resources :productsend$ rake routes    products GE...
APIS ON RAILS - REST#config/routes.rbMyApp::Application.routes.draw do  scope ‘/api’ do    resources :products  endend    ...
APIS ON RAILS -                VERSIONESgem versionist#config/routes.rbMyApp::Application.routes.draw do  api_version(:mod...
APIS ON RAILS,             CONTROLADORclass V1::ProductsController < ApplicationController  def index    products = Produc...
APIS ON RAILS,                CONTROLADORclass ApplicationController < ActionController::Base  rescue_from ActiveRecord::U...
APIS ON RAILS,              CONTROLADORclass V2::ProductsController < ApplicationController  respond_to [:json, :xml, :htm...
APIS ON RAILS -   MODELOclass V2::Product < Product  JSON_ATTRIBUTES = {    properties: [       :id,       :upc,       :sk...
APIS ON RAILS,             CONTROLADORgem ‘rabl’class V3::ProductsController < ApplicationController  respond_to [:json, :...
APIS ON RAILS                           VISTAS#app/views/api/v3/products/index.rablcollection @productsattributes :id, :na...
APIS ON RAILS                 VISTASgem ‘jbuilder’Jbuilder.encode do |json|  json.content format_content(@message.content)...
APIS ON RAILS                 VISTASgem ‘active_model_serializer’class PostSerializer < ActiveModel::Serializer  attribute...
APIS ON RAILS           SEGURIDADDeviseAutenticacion Flexible para aplicaciones RailsCompuesta de 12 modulos: database aut...
APIS ON RAILS           SEGURIDADDeviseAutenticacion Flexible para aplicaciones RailsCompuesta de 12 modulos: database aut...
APIS ON RAILS                 SEGURIDADgem ‘rabl’class V3::ProductsController < ApplicationController  before_filter :auth...
ESCRIBIENDO PRUEBAS
APIS ON RAILS                  PRUEBASdescribe V3::ProductsController do  before do    @request.env["HTTP_ACCEPT"] = "appl...
APIS ON RAILS                   PRUEBASdescribe V3::ProductsController do  before do    @request.env["HTTP_ACCEPT"] = "app...
APIS ON RAILS                   PRUEBASdescribe V3::ProductsController do  before do    @request.env["HTTP_ACCEPT"] = "app...
APIS ON RAILS                   PRUEBASdescribe V3::ProductsController do  before do    @request.env["HTTP_ACCEPT"] = "app...
ROR, DEMACIADO PARA       LAS API?• Helpers• Vistas• Administracion   de assets• Generadores   de html• Template   engines
<Module:0x007ff271221e40>, ActionDispatch::Routing::Helpers, #<Module:0x007ff2714ad268>, ActionController::Base, ActionDis...
<Module:0x007ff271221e40>, ActionDispatch::Routing::Helpers, #<Module:0x007ff2714ad268>, ActionController::Base, ActionDis...
RAILS A DIETA
RAILS A DIETA  Rails es modular
RAILS A DIETA              Rails es modularPara crear APIs, algunos Middlewares no son                    necesarios
RAILS A DIETA              Rails es modularPara crear APIs, algunos Middlewares no son                    necesarios      ...
use ActionDispatch::Staticuse Rack::Lockuse#<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x007fd3b32928c0>use R...
use ActionDispatch::Staticuse Rack::Lockuse                                     use ActionDispatch::Static#<ActiveSupport:...
RAILS-API?• ActiveRecord    (manejo de errores)• Validaciones   (responder a varios formatos)• Controladores, sistema   de...
RAILS-API?• REST• CRUD
CONCLUSION
CONCLUSIONRails es perfecto para API’s!
Gracias!Preguntas?              Edwin Cruz      edwin@crowdint.com                 @softr8
Upcoming SlideShare
Loading in...5
×

Api development with rails

2,116

Published on

En esta platica trate de transmitir mejores practicas que se deben tener en cuenta cuando se diseña una API, y como ruby on rails te podria ayudar a desarrollarla en muy poco tiempo

Published in: Technology, Business
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,116
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
25
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide
  • \n
  • Mi plan es hablarles acerca de las famosas y muy comunmente usadas APIs, como implementar una buena API que todo mundo quedra usarla y como ruby on rails te ayudara a hacerla en muy poco tiempo\n
  • dicho de una manera mas sencilla:\n\n
  • Asi como las interfaces de usuario ayudan a los usuarios a comunicarse con las aplicaciones, las apis ayudan a comunicar dos softwares distintos entre ellos\n
  • Estas son algunos ejemplos de APIs, pueden ser tanto como librerias como SDK&amp;#x2019;s, el problema con esto, es que generalmente tienen que ser usadas en el mismo lenguaje de programacion, por ejemplo Net::HTTP es un ejemplo de la API de ruby para establecer conexiones http\n
  • Estas fueron las primeras API&amp;#x2019;s que se empezaron a consumir en el mundo web, luego llegaron las wsdl&amp;#x2019;s y generalmente eran con mensajes en xml demaciaaado complejas, en esta platica quiero enfocarme a algunas mejores practicas para implementar apis usando las nuevas caracteristicas que se agregaron al http 1.1, especificamente al famoso REST\n
  • REST nacio en la implementacion de HTTP 1.1, de alguna manera fue mejora del 1.0, y no es mas que un estilo o convension para transferir datos entre el servidor web y el navegador. REST es una manera de organizar recursos con url&amp;#x2019;s unicas por lo tanto, es un patron de dise&amp;#xF1;o para web services\n\nQue requisitos debe tener una aplicacion para ser RESTful ?\n
  • El server se encarga del almacenamiento, el cliente se encarga de la UI y del estado.\n\nSin estado significa que ninguna llamada REST depende de llamadas pasadas, ocea que el servidor no mantiene ningun valor del cliente en sesion \n\nLa respuesta puede ser cacheable por el cliente o no, se debe de expresar explicitamente, para evitar que el cliente tenga copias obsoletas - Incrementa escalabilidad -\n\nEl cliente nunca podra saber si esta conectado al servidor final - balanceo de cargar, cache -\n\nInterface uniforme es que tiene que ser lo m&amp;#xE1;s explicito posible el mensaje\n\n
  • El server se encarga del almacenamiento, el cliente se encarga de la UI y del estado.\n\nSin estado significa que ninguna llamada REST depende de llamadas pasadas, ocea que el servidor no mantiene ningun valor del cliente en sesion \n\nLa respuesta puede ser cacheable por el cliente o no, se debe de expresar explicitamente, para evitar que el cliente tenga copias obsoletas - Incrementa escalabilidad -\n\nEl cliente nunca podra saber si esta conectado al servidor final - balanceo de cargar, cache -\n\nInterface uniforme es que tiene que ser lo m&amp;#xE1;s explicito posible el mensaje\n\n
  • El server se encarga del almacenamiento, el cliente se encarga de la UI y del estado.\n\nSin estado significa que ninguna llamada REST depende de llamadas pasadas, ocea que el servidor no mantiene ningun valor del cliente en sesion \n\nLa respuesta puede ser cacheable por el cliente o no, se debe de expresar explicitamente, para evitar que el cliente tenga copias obsoletas - Incrementa escalabilidad -\n\nEl cliente nunca podra saber si esta conectado al servidor final - balanceo de cargar, cache -\n\nInterface uniforme es que tiene que ser lo m&amp;#xE1;s explicito posible el mensaje\n\n
  • El server se encarga del almacenamiento, el cliente se encarga de la UI y del estado.\n\nSin estado significa que ninguna llamada REST depende de llamadas pasadas, ocea que el servidor no mantiene ningun valor del cliente en sesion \n\nLa respuesta puede ser cacheable por el cliente o no, se debe de expresar explicitamente, para evitar que el cliente tenga copias obsoletas - Incrementa escalabilidad -\n\nEl cliente nunca podra saber si esta conectado al servidor final - balanceo de cargar, cache -\n\nInterface uniforme es que tiene que ser lo m&amp;#xE1;s explicito posible el mensaje\n\n
  • El server se encarga del almacenamiento, el cliente se encarga de la UI y del estado.\n\nSin estado significa que ninguna llamada REST depende de llamadas pasadas, ocea que el servidor no mantiene ningun valor del cliente en sesion \n\nLa respuesta puede ser cacheable por el cliente o no, se debe de expresar explicitamente, para evitar que el cliente tenga copias obsoletas - Incrementa escalabilidad -\n\nEl cliente nunca podra saber si esta conectado al servidor final - balanceo de cargar, cache -\n\nInterface uniforme es que tiene que ser lo m&amp;#xE1;s explicito posible el mensaje\n\n
  • El server se encarga del almacenamiento, el cliente se encarga de la UI y del estado.\n\nSin estado significa que ninguna llamada REST depende de llamadas pasadas, ocea que el servidor no mantiene ningun valor del cliente en sesion \n\nLa respuesta puede ser cacheable por el cliente o no, se debe de expresar explicitamente, para evitar que el cliente tenga copias obsoletas - Incrementa escalabilidad -\n\nEl cliente nunca podra saber si esta conectado al servidor final - balanceo de cargar, cache -\n\nInterface uniforme es que tiene que ser lo m&amp;#xE1;s explicito posible el mensaje\n\n
  • operaciones comunes en sistemas de informacion, generalmente todo gira alrededor de estas operaciones basicas\n
  • \n
  • Representacion en datos, basicamente es un documento que se va a transferir del servidor al cliente\n\nOrigen de alguna informacion en especifico\n
  • Representacion en datos, basicamente es un documento que se va a transferir del servidor al cliente\n\nOrigen de alguna informacion en especifico\n
  • Representacion en datos, basicamente es un documento que se va a transferir del servidor al cliente\n\nOrigen de alguna informacion en especifico\n
  • Hace un momento comentaba de que los primeros web services usaban estructuras de datos basadas en definiciones xml, llegaban a ser mensajes demaciado grandes, y era complicado para un humano leerlas, entonces que pasa, si usamos una estructura mas sensilla?\nPorque JSON ?, si se te complica hacer una estructura con json, algo estas haciendo mal, mensajes son muy cortos, human readable, gzip\n
  • Hace un momento comentaba de que los primeros web services usaban estructuras de datos basadas en definiciones xml, llegaban a ser mensajes demaciado grandes, y era complicado para un humano leerlas, entonces que pasa, si usamos una estructura mas sensilla?\nPorque JSON ?, si se te complica hacer una estructura con json, algo estas haciendo mal, mensajes son muy cortos, human readable, gzip\n
  • Ejemplo: middleware\n
  • Ejemplo: middleware\n
  • Ejemplo: middleware\n
  • Como va a estar abierto a m&amp;#xE1;s personas, ejemplo de clientes, cuotas, \nnada de prametros ocultos, cuando regrese errores que los haga bien descriptivo\nbuena documentacion, eventos,\n
  • Como va a estar abierto a m&amp;#xE1;s personas, ejemplo de clientes, cuotas, \nnada de prametros ocultos, cuando regrese errores que los haga bien descriptivo\nbuena documentacion, eventos,\n
  • Como va a estar abierto a m&amp;#xE1;s personas, ejemplo de clientes, cuotas, \nnada de prametros ocultos, cuando regrese errores que los haga bien descriptivo\nbuena documentacion, eventos,\n
  • administracion de cambios\nsi tienes duda de que publicar en tu api, no la publiques, alguien mas la va a implementar y tendras que soportarla\n
  • administracion de cambios\nsi tienes duda de que publicar en tu api, no la publiques, alguien mas la va a implementar y tendras que soportarla\n
  • administracion de cambios\nsi tienes duda de que publicar en tu api, no la publiques, alguien mas la va a implementar y tendras que soportarla\n
  • administracion de cambios\nsi tienes duda de que publicar en tu api, no la publiques, alguien mas la va a implementar y tendras que soportarla\n
  • administracion de cambios\nsi tienes duda de que publicar en tu api, no la publiques, alguien mas la va a implementar y tendras que soportarla\n
  • administracion de cambios\nsi tienes duda de que publicar en tu api, no la publiques, alguien mas la va a implementar y tendras que soportarla\n
  • \n
  • Una buena API siempre debe seguir convenciones REST, basicamente es seguir la convencion de un buen patron de dise&amp;#xF1;o para solucionar este problema.\n\n
  • GET, POST, DELETE, PUT, etc\n
  • \n
  • \n
  • \n
  • \n
  • no regresaria ningun contenido, solo un http status code\n
  • \n
  • \n
  • muy dificil de adminsitrar, porque un solo controlador se encargaria de despachar todas las versiones\n
  • \n
  • \n
  • La informacion contenida en el header la utiliza el cliente y el servidor para ponerse de acuerdo como van a transmitir la informacion, esto significa que el cliente le esta diciendo al servidor que el soporta la version 2 de la api, y que debe regresarsela en modo json\n
  • La informacion contenida en el header la utiliza el cliente y el servidor para ponerse de acuerdo como van a transmitir la informacion, esto significa que el cliente le esta diciendo al servidor que el soporta la version 2 de la api, y que debe regresarsela en modo json\n
  • 401, Se excede la cuota mensual\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Mashery\nLimite de uso, para limitar a los usuarios de no hacer mal uso de los recursos, CDN pero para APIS, Balanceo de cargas\nOauth\nSandbox para probar\nbloqueo de IP&amp;#x2019;s, Accesos basados en roles\n
  • se puede aprovechar al maximo lo que rails ofrece para crear apis muy poderosa, rails ya tiene REST implementado, sistema de cache, autenticacion, logging de eventos, MVC, observers, se puede extender su funcionalidad muy facil, por ejemplo montarle un fulltext search engine como solr, es muy facil escribir pruebas unitarias\n
  • Rails ya nos da todo para hacer aplicaciones REST\n
  • Rails soporta namespaces para los recurcos nativamente, pero puede llegar a ser un problema al resolver los nombres de los controladores, para esto alguien mas ya hizo algo al respecto\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Funciona transparente con el .to_json, active_model_serializer es bueno para aplicaciones web que usan javascript frameworks como ember o backbone\n
  • \n
  • \n
  • \n
  • Las pruebas son muy importantes al momento de desarrollar cualquier software, existen herramientas que hacen de esto literalmente un placer, muy facil de automatizar las pruebas\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • basico para una api\n
  • basico para una api\n
  • basico para una api\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Api development with rails

    1. 1. Diseño de APIs con Ruby Edwin Cruz @softr8
    2. 2. PLAN• Que es una API• Como implementar una buena API• Usando Ruby on Rails para implementar una API• Patrones de diseño
    3. 3. “ Application Programming Interface “
    4. 4. API Es una manera para comunicar dosaplicaciones entre ellas.
    5. 5. TIPOS DE API• Library• SDK• Web services
    6. 6. PRIMERAS API - SOAP Simple Object Access Protocol
    7. 7. RESTREpresentationStateTransfer
    8. 8. REQUISITOS REST
    9. 9. REQUISITOS RESTSeparación de responsabilidades
    10. 10. REQUISITOS RESTSeparación de responsabilidadesCliente/Servidor
    11. 11. REQUISITOS RESTSeparación de responsabilidadesCliente/ServidorSin estado
    12. 12. REQUISITOS RESTSeparación de responsabilidadesCliente/ServidorSin estadoPuede ser “Cacheable”
    13. 13. REQUISITOS RESTSeparación de responsabilidadesCliente/ServidorSin estadoPuede ser “Cacheable”Sistema a capas
    14. 14. REQUISITOS RESTSeparación de responsabilidadesCliente/ServidorSin estadoPuede ser “Cacheable”Sistema a capasInterface uniforme
    15. 15. CRUDCreate AltasRead BajasUpdate CambiosDelete Consultas
    16. 16. REST + CRUD
    17. 17. REST + CRUD Recursos a través de URLs únicasUsando correctamente los verbos HTTP
    18. 18. RECURSO
    19. 19. RECURSOCualquier accion expuesta a travez de un servidorweb
    20. 20. RECURSOCualquier accion expuesta a travez de un servidorwebTienen una representación en datos
    21. 21. RECURSOCualquier accion expuesta a travez de un servidorwebTienen una representación en datosCon un servicio web intercambiamosrepresentaciones de recursos
    22. 22. REST-ISH + JSON
    23. 23. REST-ISH + JSON =
    24. 24. REST-ISH + JSON = Cosas Increibles
    25. 25. ¿PORQUÉ UN API?
    26. 26. ¿PORQUÉ UN API?Aumenta la flexibilidad y utilidad de tus aplicaciones
    27. 27. ¿PORQUÉ UN API?Aumenta la flexibilidad y utilidad de tus aplicaciones Proporciona valor de negocio
    28. 28. ¿PORQUÉ UN API?Aumenta la flexibilidad y utilidad de tus aplicaciones Proporciona valor de negocio Ayuda a comunicar aplicaciones entre ellas
    29. 29. ¿QUÉCARACTERÍSTICAS?
    30. 30. ¿QUÉCARACTERÍSTICAS? Fácil de implementar y mantener
    31. 31. ¿QUÉCARACTERÍSTICAS? Fácil de implementar y mantener Buen rendimiento
    32. 32. ¿QUÉCARACTERÍSTICAS? Fácil de implementar y mantener Buen rendimiento Escalable
    33. 33. ¿CUÁLES SON LOS RETOS?
    34. 34. ¿CUÁLES SON LOS RETOS?La red es un eslabón débil, GEO localizacion de losclientes
    35. 35. ¿CUÁLES SON LOS RETOS?La red es un eslabón débil, GEO localizacion de losclientesAdministrar Cambios
    36. 36. ¿CUÁLES SON LOS RETOS?La red es un eslabón débil, GEO localizacion de losclientesAdministrar CambiosUso indebido
    37. 37. ¿CUÁLES SON LOS RETOS?La red es un eslabón débil, GEO localizacion de losclientesAdministrar CambiosUso indebidoBalanceo de trafico
    38. 38. ¿CUÁLES SON LOS RETOS?La red es un eslabón débil, GEO localizacion de losclientesAdministrar CambiosUso indebidoBalanceo de traficoPicos de uso
    39. 39. ¿CUÁLES SON LOS RETOS?La red es un eslabón débil, GEO localizacion de losclientesAdministrar CambiosUso indebidoBalanceo de traficoPicos de usoErrores
    40. 40. DISEÑAR UNA BUENA API
    41. 41. CONVENCIONES REST
    42. 42. USAR CORRECTAMENTE VERBOS HTTP
    43. 43. REST + CRUD GET /api/products #Listado{"products" : [ {"product" : { "id" : 1, "name" : "Producto 1", "status" : "archived"} }, {"product" : { "id" : 2, "name" : "Producto 2", "status" : "active" } } ]}
    44. 44. REST + CRUD GET /api/products/2 #Ver{"product" : { "id" : 2, "name" : "Producto 2", "status" : "active" } }
    45. 45. REST + CRUD POST /api/products #Crear{ "name" : "Producto 2"}
    46. 46. REST + CRUD PUT /api/products/2 #Actualizar{ "name" : "Producto dos"}
    47. 47. REST + CRUDDELETE /api/products/2 #Eliminar
    48. 48. VERSIONES DE LA API• API Interna (entre aplicaciones)• API Externa (aplicacion movil ? )• API Usuarios (publico en general)
    49. 49. VERSIONANDO TU API /int/api/products /ext/api/products /pub/api/products
    50. 50. VERSIONANDO TU API /int/api/products?version=2 /ext/api/products?version=2 /pub/api/products?version=2
    51. 51. VERSIONANDO TU API /v2/int/api/products /v2/ext/api/products /v2/pub/api/products
    52. 52. VERSIONANDO TU APIhttp://int.myapp.com/productshttp://api.myapp.com/products
    53. 53. MUNDO IDEAL
    54. 54. MUNDO IDEALUso de: Accept Header
    55. 55. MUNDO IDEALUso de: Accept HeaderAccept: application/vnd.mycompany.com;version=2,application/json
    56. 56. CODIGOS HTTP200 OK201 Created202 Accepted400 Bad Request401 Unauthorized402 Payment Required404 Not Found409 Conflict422 Unprocessable Entity500 Internal Server Error503 Service Unavailable
    57. 57. CODIGOS HTTPHTTP/1.1 200 okGET /v1/products{"products" : [ {"product" : { "id" : 1, "name" : "Producto 1", "status" : "archived"} }, {"product" : { "id" : 2, "name" : "Producto 2", "status" : "active" } } ]}
    58. 58. CODIGOS HTTP HTTP/1.1 201 Created POST /v1/products { “product”: [ “name” : “name” ] }
    59. 59. CODIGOS HTTPHTTP/1.1 400 Bad Request{ “errors”: [ “Estructura JSON no valida”, “unexpected TSTRING, expected ‘}’ atline 2” ]}
    60. 60. CODIGOS HTTPHTTP/1.1 401 Unauthorized{ “errors”: [ “api_key not found” ]}
    61. 61. CODIGOS HTTPHTTP/1.1 401 Unauthorized{ “errors”: [ “api_key no valida”, “api_key no puede contenerespacios” ]}
    62. 62. CODIGOS HTTPHTTP/1.1 401 Unauthorized{ “errors”: [ “api_key no encontrada, por favorvisita http://account.myapp.com/api paraobtenerla” ]}
    63. 63. CODIGOS HTTPHTTP/1.1 422 Unprocessable Entity{ “errors”: [ “vendor_code: no puede estar vacio” ], “documentacion”: [ “vendor_code”: [ “descripcion” : “Codigo asignado por proveedor”, “formato” : “Combinacion de tres letras seguidas de 4numeros”, “ejemplo” : “SOL1234” ] ]}
    64. 64. CODIGOS HTTPHTTP/1.1 500 Internal Server Error{ “exception”: [ “Base de datos no disponible” ]}
    65. 65. CODIGOS HTTPHTTP/1.1 503 Service Unavailable{ “messages”: [ “En mantenimiento” ]}
    66. 66. OPCIONES AVANZADAS• Simuladores• Autenticación• Validadores• Limite de uso• Rapidez• Balanceo
    67. 67. USANDO RUBY ON RAILS PARAIMLEMENTAR UNA API
    68. 68. APIS ON RAILS - REST#config/routes.rbMyApp::Application.routes.draw do resources :productsend$ rake routes products GET /products(.:format) products#index POST /products(.:format) products#create new_product GET /products/new(.:format) products#newedit_product GET /products/:id/edit(.:format) products#edit product GET /products/:id(.:format) products#show PUT /products/:id(.:format) products#update DELETE /products/:id(.:format) products#destroy
    69. 69. APIS ON RAILS - REST#config/routes.rbMyApp::Application.routes.draw do scope ‘/api’ do resources :products endend products GET /api/products(.:format) products#index POST /api/products(.:format) products#create new_product GET /api/products/new(.:format) products#newedit_product GET /api/products/:id/edit(.:format) products#edit product GET /api/products/:id(.:format) products#show PUT /api/products/:id(.:format) products#update DELETE /api/products/:id(.:format) products#destroy
    70. 70. APIS ON RAILS - VERSIONESgem versionist#config/routes.rbMyApp::Application.routes.draw do api_version(:module => V1, :path => v2) do resources :products endend v2_products GET /v2/products(.:format) V1/products#index POST /v2/products(.:format) V1/products#create new_v2_product GET /v2/products/new(.:format) V1/products#newedit_v2_product GET /v2/products/:id/edit(.:format) V1/products#edit v2_product GET /v2/products/:id(.:format) V1/products#show PUT /v2/products/:id(.:format) V1/products#update DELETE /v2/products/:id(.:format) V1/products#destroy
    71. 71. APIS ON RAILS, CONTROLADORclass V1::ProductsController < ApplicationController def index products = Product.paginate(:page => (params[:page] || 1), :per_page => (params[:per_page] || 100)).all render :json => products.to_json end def show product = Product.find(params[:id]) render :json => product.to_json end def update product = Product.find(params[:id]) product.update_attributes(params[:product]) render :json => product.to_json end def destroy product = Product.find(params[:id]) head product.destroy ? :ok : :unprocessable_entity endend
    72. 72. APIS ON RAILS, CONTROLADORclass ApplicationController < ActionController::Base rescue_from ActiveRecord::UnknownAttributeError, ArgumentError do |exception| respond_with_error(exception, 400) end rescue_from ActiveRecord::RecordNotFound do |exception| respond_with_error(exception, 404) end rescue_from ActiveRecord::RecordInvalid do |exception| respond_with_error(exception, 422, errors: exception.record.errors.messages) end rescue_from RuntimeError do |exception| respond_with_error(exception, 500) end private def respond_with_error(exception, code, errors = {}) render json: {error: exception.class.to_s, message: exception.to_s, errors: errors}, status: code endend
    73. 73. APIS ON RAILS, CONTROLADORclass V2::ProductsController < ApplicationController respond_to [:json, :xml, :html] def index @products = V2::Product.paginate(:page => (params[:page] || 1), :per_page => (params[:per_page] || 100)).all respond_with @products end def show @product = V2::Product.find(params[:id]) respond_with @product end def update @product = V2::Product.find(params[:id]) @product.update_attributes(params[:product]) respond_with @product end def destroy @product = V2::Product.find(params[:id]) respond_with @product.destroy endend
    74. 74. APIS ON RAILS - MODELOclass V2::Product < Product JSON_ATTRIBUTES = { properties: [ :id, :upc, :sku, :list_cost, :color, :dimension, :size, :created_at, :updated_at, ], methods: [ :units_on_hand ] }end
    75. 75. APIS ON RAILS, CONTROLADORgem ‘rabl’class V3::ProductsController < ApplicationController respond_to [:json, :xml] def index @products = V3::Product.paginate(:page => (params[:page] || 1), :per_page => (params[:per_page] || 100)).all end def show @product = V3::Product.find(params[:id]) end def update @product = V3::Product.find(params[:id]) @product.update_attributes(params[:product]) end def destroy @product = V3::Product.find(params[:id]) render json: {}, status: @product.destroy ? :ok : :unprocessable_entity endend
    76. 76. APIS ON RAILS VISTAS#app/views/api/v3/products/index.rablcollection @productsattributes :id, :name, :statusnode(:url) {|product| product_url(product) }node(:current_stock) {|product| product.variants.map(&:on_hand).sum }child :variants do attributes :upc, :color, :size, :on_handend{"products" : [ {"product" : { "id" : 1, "name" : "Producto 1", "status" : "archived", “current_stock” : 10, “variants” : [ {“upc” : “ASDFS”, “color” : “negro”, “size” : “M”, “on_hand” : 10} ] } } ]}
    77. 77. APIS ON RAILS VISTASgem ‘jbuilder’Jbuilder.encode do |json| json.content format_content(@message.content) json.(@message, :created_at, :updated_at) json.author do |json| json.name @message.creator.name.familiar json.email_address @message.creator.email_address_with_name json.url url_for(@message.creator, format: :json) end if current_user.admin? json.visitors calculate_visitors(@message) end json.comments @message.comments, :content, :created_atend
    78. 78. APIS ON RAILS VISTASgem ‘active_model_serializer’class PostSerializer < ActiveModel::Serializer attributes :id, :body attribute :title, :key => :name has_many :comments def tags tags.order :name endend
    79. 79. APIS ON RAILS SEGURIDADDeviseAutenticacion Flexible para aplicaciones RailsCompuesta de 12 modulos: database authenticable,token authenticable, omniauthable, confirmable,recoverable, registerable, trackable, timeoutable,validatable, lockable
    80. 80. APIS ON RAILS SEGURIDADDeviseAutenticacion Flexible para aplicaciones RailsCompuesta de 12 modulos: database authenticable,token authenticable, omniauthable, confirmable,recoverable, registerable, trackable, timeoutable,validatable, lockable
    81. 81. APIS ON RAILS SEGURIDADgem ‘rabl’class V3::ProductsController < ApplicationController before_filter :authenticate_user! respond_to :json, :xml def index @products = V3::Product.paginate(:page => (params[:page] || 1), :per_page => (params[:per_page] || 100)).all end def show @product = V3::Product.find(params[:id]) end def update @product = V3::Product.find(params[:id]) @product.update_attributes(params[:product]) end def destroy @product = V3::Product.find(params[:id]) render json: {}, status: @product.destroy ? :ok : :unprocessable_entity endend
    82. 82. ESCRIBIENDO PRUEBAS
    83. 83. APIS ON RAILS PRUEBASdescribe V3::ProductsController do before do @request.env["HTTP_ACCEPT"] = "application/json" end describe "#index" do context "cuando no se pasa ningun atributo" do it "regresa los registros en paginas" do get :index response.should be_success data = JSON.parse(response.body) Product.count.should > 0 data[products].length.should == Product.count end end endend
    84. 84. APIS ON RAILS PRUEBASdescribe V3::ProductsController do before do @request.env["HTTP_ACCEPT"] = "application/json" end describe "#show" do context "pasando un id inexistente" do it "responde con http 404 y un mensaje de error" do get :show, id: -1 response.code.should == "404" json_response = JSON.parse(response.body) json_response[error].should == "ActiveRecord::RecordNotFound" json_response[message].should == "Couldnt find Product with id=-1" end end endend
    85. 85. APIS ON RAILS PRUEBASdescribe V3::ProductsController do before do @request.env["HTTP_ACCEPT"] = "application/json" end describe "#create" do context "con malos atributos" do it "responde con un error" do post :create, product: {bad_key: "foo"} response.code.should == "400" json_response = JSON.parse(response.body) json_response[error].should == "ActiveRecord::UnknownAttributeError" json_response[message].should == "unknown attribute: bad_key" end end endend
    86. 86. APIS ON RAILS PRUEBASdescribe V3::ProductsController do before do @request.env["HTTP_ACCEPT"] = "application/json" end describe "#create" do context "con atributos correctos" do it "responde correctamente y crea el producto" do expect { post :create, product: {name: "productito"} }.to change(Product, :count).by(1) end end endend
    87. 87. ROR, DEMACIADO PARA LAS API?• Helpers• Vistas• Administracion de assets• Generadores de html• Template engines
    88. 88. <Module:0x007ff271221e40>, ActionDispatch::Routing::Helpers, #<Module:0x007ff2714ad268>, ActionController::Base, ActionDispatch::Routing::RouteSet::MountedHelpers, HasScope, ActionController::Compatibility, ActionController::ParamsWrapper, ActionController::Instrumentation, ActionController::Rescue, ActiveSupport::Rescuable, ActionController::HttpAuthentication::Token::ControllerMethods, ActionController::HttpAuthentication::Digest::ControllerMethods, ActionController::HttpAuthentication::Basic::ControllerMethods, ActionController::RecordIdentifier, ActionController::DataStreaming, ActionController::Streaming, ActionController::ForceSSL, ActionController::RequestForgeryProtection, AbstractController::Callbacks, ActiveSupport::Callbacks, ActionController::Flash, ActionController::Cookies, ActionController::MimeResponds, ActionController::ImplicitRender, ActionController::Caching, ActionController::Caching::Fragments, ActionController::Caching::ConfigMethods, ActionController::Caching::Pages, ActionController::Caching::Actions, ActionController::ConditionalGet, ActionController::Head, ActionController::Renderers::All, ActionController::Renderers, ActionController::Rendering, ActionController::Redirecting, ActionController::RackDelegation, ActiveSupport::Benchmarkable, AbstractController::Logger, ActionController::UrlFor, AbstractController::UrlFor, ActionDispatch::Routing::UrlFor, ActionDispatch::Routing::PolymorphicRoutes, ActionController::HideActions, ActionController::Helpers, AbstractController::Helpers, AbstractController::AssetPaths, AbstractController::Translation, AbstractController::Layouts, AbstractController::Rendering, AbstractController::ViewPaths, ActionController::Metal, AbstractController::Base, ActiveSupport::Configurable, Object, ActiveSupport::Dependencies::Loadable, JSON::Ext::Generator::GeneratorMethods::Object, PP::ObjectMixin, Kernel, BasicObject
    89. 89. <Module:0x007ff271221e40>, ActionDispatch::Routing::Helpers, #<Module:0x007ff2714ad268>, ActionController::Base, ActionDispatch::Routing::RouteSet::MountedHelpers, HasScope, ActionController::Compatibility, ActionController::ParamsWrapper, ActionController::Instrumentation, ActionController::Rescue, ActiveSupport::Rescuable, ActionController::HttpAuthentication::Token::ControllerMethods, ActionController::HttpAuthentication::Digest::ControllerMethods, #<Module:0x007f9211d5cd70>, ActionController::HttpAuthentication::Basic::ControllerMethods, ActionDispatch::Routing::Helpers, ActionController::RecordIdentifier, #<Module:0x007f9211f7b5e8>, ActionController::DataStreaming, ActionController::API, ActionController::Streaming, ActiveRecord::Railties::ControllerRuntime, ActionController::ForceSSL, ActionDispatch::Routing::RouteSet::MountedHelpers, ActionController::RequestForgeryProtection, ActionController::Instrumentation, AbstractController::Callbacks, ActionController::Rescue, ActiveSupport::Callbacks, ActiveSupport::Rescuable, ActionController::Flash, ActionController::DataStreaming, ActionController::Cookies, ActionController::ForceSSL, ActionController::MimeResponds, AbstractController::Callbacks, ActionController::ImplicitRender, ActiveSupport::Callbacks, ActionController::Caching, ActionController::ConditionalGet, ActionController::Caching::Fragments, ActionController::Head, ActionController::Caching::ConfigMethods, ActionController::Renderers::All, ActionController::Caching::Pages, ActionController::Renderers, ActionController::Caching::Actions, ActionController::Rendering, ActionController::ConditionalGet, AbstractController::Rendering, ActionController::Head, AbstractController::ViewPaths, ActionController::Renderers::All, ActionController::Redirecting, ActionController::Renderers, ActionController::RackDelegation, ActionController::Rendering, ActiveSupport::Benchmarkable, ActionController::Redirecting, AbstractController::Logger, ActionController::RackDelegation, ActionController::UrlFor, ActiveSupport::Benchmarkable, AbstractController::UrlFor, AbstractController::Logger, ActionDispatch::Routing::UrlFor, ActionController::UrlFor, ActionDispatch::Routing::PolymorphicRoutes, AbstractController::UrlFor, ActionController::HideActions, ActionDispatch::Routing::UrlFor, ActionController::Metal, ActionDispatch::Routing::PolymorphicRoutes, AbstractController::Base, ActionController::HideActions, ActiveSupport::Configurable, ActionController::Helpers, Object, AbstractController::Helpers, JSON::Ext::Generator::GeneratorMethods::Object, AbstractController::AssetPaths, ActiveSupport::Dependencies::Loadable, AbstractController::Translation, PP::ObjectMixin, AbstractController::Layouts, Kernel, AbstractController::Rendering, BasicObject AbstractController::ViewPaths, ActionController::Metal, AbstractController::Base, ActiveSupport::Configurable, Object, ActiveSupport::Dependencies::Loadable, JSON::Ext::Generator::GeneratorMethods::Object, PP::ObjectMixin, Kernel, BasicObject
    90. 90. RAILS A DIETA
    91. 91. RAILS A DIETA Rails es modular
    92. 92. RAILS A DIETA Rails es modularPara crear APIs, algunos Middlewares no son necesarios
    93. 93. RAILS A DIETA Rails es modularPara crear APIs, algunos Middlewares no son necesarios rails-api
    94. 94. use ActionDispatch::Staticuse Rack::Lockuse#<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x007fd3b32928c0>use Rack::Runtimeuse Rack::MethodOverrideuse ActionDispatch::RequestIduse Rails::Rack::Loggeruse ActionDispatch::ShowExceptionsuse ActionDispatch::DebugExceptionsuse ActionDispatch::RemoteIpuse ActionDispatch::Reloaderuse ActionDispatch::Callbacksuse ActionDispatch::CookiesuseActionDispatch::Session::CookieStoreuse ActionDispatch::Flashuse ActionDispatch::ParamsParseruse ActionDispatch::Headuse Rack::ConditionalGetuse Rack::ETaguseActionDispatch::BestStandardsSupportuse
    95. 95. use ActionDispatch::Staticuse Rack::Lockuse use ActionDispatch::Static#<ActiveSupport::Cache::Strategy::Loc use Rack::LockalCache::Middleware:0x007fd3b32928c0> useuse Rack::Runtime #<ActiveSupport::Cache::Strategy::LocalCacuse Rack::MethodOverride he::Middleware:0x007fe74448cf50>use ActionDispatch::RequestId use Rack::Runtimeuse Rails::Rack::Logger use ActionDispatch::RequestIduse ActionDispatch::ShowExceptions use Rails::Rack::Loggeruse ActionDispatch::DebugExceptions use ActionDispatch::ShowExceptionsuse ActionDispatch::RemoteIp use ActionDispatch::DebugExceptionsuse ActionDispatch::Reloader use ActionDispatch::RemoteIpuse ActionDispatch::Callbacks use ActionDispatch::Reloaderuse ActionDispatch::Cookies use ActionDispatch::Callbacksuse useActionDispatch::Session::CookieStore ActiveRecord::ConnectionAdapters::Connectiuse ActionDispatch::Flash onManagementuse ActionDispatch::ParamsParser use ActiveRecord::QueryCacheuse ActionDispatch::Head use ActionDispatch::ParamsParseruse Rack::ConditionalGet use ActionDispatch::Headuse Rack::ETag use Rack::ConditionalGetuse use Rack::ETagActionDispatch::BestStandardsSupportuse
    96. 96. RAILS-API?• ActiveRecord (manejo de errores)• Validaciones (responder a varios formatos)• Controladores, sistema de rutas (versionamiento)• Muchas librerias(Gems)• Autenticación (oauth, token, basic auth)• Mismos web servers confiables (mismo hosting)
    97. 97. RAILS-API?• REST• CRUD
    98. 98. CONCLUSION
    99. 99. CONCLUSIONRails es perfecto para API’s!
    100. 100. Gracias!Preguntas? Edwin Cruz edwin@crowdint.com @softr8
    1. ¿Le ha llamado la atención una diapositiva en particular?

      Recortar diapositivas es una manera útil de recopilar información importante para consultarla más tarde.

    ×