Criando APIs - Usando Rails
Fernando Kakimoto
Desenvolvedor @ ThoughtWorks
O que é uma API mesmo?
Application Programming Interface
Biblioteca que inclui especificações para rotinas,
estruturas de ...
Características de boas APIs
 Fácil de aprender e memorizar
 Dificilmente usada de maneira errada
 Minimalista
 Comple...
Tópicos para hoje
 REST
 Consistência
 Versionamento
 Segurança
REST
REpresentational State Transfer
Um padrão arquitetural para sistemas hipermídias
distribuídos
REST
 URL base
 Tipo de mídia
 Operações (Método HTTP)
REST
GET
https://api.twitter.com/1.1/statuses/menti
ons_timeline.json
REST
GET
https://api.twitter.com/1.1/statuses/menti
ons_timeline.json
URL base
REST
GET
https://api.twitter.com/1.1/statuses/menti
ons_timeline.jsonTipo de mídia
REST
GET
https://api.twitter.com/1.1/statuses/menti
ons_timeline.json
Método
2 URLs base por recurso
• GET /tickets - recupera conjunto de tickets
• GET /tickets/12 - recupera o ticket #12
• POST /ti...
Restrições REST
 Cliente-Servidor
 Stateless
 Cacheable
 Sistema em camadas
 Interface Uniforme
API RESTful
API implementada usando
princípios HTTP e REST
> nandokakimoto@Development$ rails new blog
> nandokakimoto@blog$ rails generate scaffold Post name:string title:string
co...
Consistência
Métodos Safe
Métodos que nunca modificam um
recurso
Dados não devem ser alterados como resultado de uma requisição GET
Métodos Idempotentes
Métodos com o mesmo resultado
mesmo que requisição seja repetida
diversas vezes
POST é o único método...
Código de Resposta
Respostas HTTP padronizam como
informar o cliente sobre o resultado da
sua requisição
Código de Resposta
 1xx - Informacional
 2xx - Sucesso
 3xx - Redirecionamento
 4xx - Erro de cliente
 5xx - Erro de ...
> nandokakimoto@blog$ curl -v http://localhost:3000/posts.json
* Connected to localhost (127.0.0.1) port 3000 (#0)
> GET /...
> nandokakimoto@blog$ curl -v -d "post[name]=Geek Night&post[title]=Scala
Dojo&post[content]=Come and learn Scala" http://...
> nandokakimoto@blog$ curl -v -d "post[name]=Geek
Night&post[content]=Come and learn Scala" http://localhost:3000/posts.js...
Versionamento
Versionamento
Sempre versione a sua API
Diferentes opniões sobre se a versão deve estar na URL ou no
cabeçalho
Versionamento
 Versionist - https://github.com/bploetz/versionist
 RocketPants - https://github.com/filtersquad/rocket_p...
config/routes.rb
> nandokakimoto@blog$ rake routes
(…)
GET /api/v1/products(.:format) api/v1/posts#index
POST /api/v1/products(.:format) ap...
app/controllers/api/v1/posts_controller.rb
> nandokakimoto@blog$ curl -v http://localhost:3000/api/v1/posts.json
* Connected to localhost (127.0.0.1) port 3000 (#0)
...
> nandokakimoto@blog$ curl -v http://localhost:3000/api/v1/posts/15.json
* Connected to localhost (127.0.0.1) port 3000 (#...
Versionamento
Novo Requisito
Mostrar apenas id, nome e título do post
config/routes.rb
> nandokakimoto@blog$ rake routes
(…)
GET /api/v2/posts(.:format) api/v2/posts#index
POST /api/v2/posts(.:format) api/v2/p...
app/controllers/api/v2/posts_controller.rb
RABL
RABL (Ruby API Builder Language) consiste num sistema de
template RAILS para geração de JSON
app/views/api/v2/show.rabl.json
app/views/api/v2/index.rabl.json
> nandokakimoto@blog$ curl -v http://localhost:3000/api/v2/posts
* Connected to localhost (127.0.0.1) port 3000 (#0)
> GET...
Segurança
HTTP Basic Authentication
 Solução mais simples
 Fácil de implementar
 Maioria dos clientes suportam
app/controllers/api/v2/posts_controller.rb
> nandokakimoto@blog$ curl -v http://localhost:3000/api/v2/posts
* Connected to localhost (127.0.0.1) port 3000 (#0)
> GET...
> nandokakimoto@blog$ curl -v -d "post[name]=RubyConf&post[title]=RubyConf
Details&post[content]=RubyConf was awesome"
htt...
> nandokakimoto@blog$ curl -v -d "post[name]=RubyConf&post[title]=RubyConf
Details&post[content]=RubyConf was awesome"
htt...
Token de Acesso
 Maior entropia
 Token é salvo no servidor
 Data de expiração
> nandokakimoto@blog$ rails g model api_key access_token
invoke active_record
create db/migrate/20130907211645_create_api_...
app/model/api_key.rb
app/controllers/api/v2/posts_controller.rb
> nandokakimoto@blog$ curl -v http://localhost:3000/api/v2/posts
curl -v http://localhost:3000/api/v2/posts
* Connected to...
> nandokakimoto@blog$ curl -v http://localhost:3000/api/v2/posts -H
'Authorization: Token token=”8219a125816b331d0e478eeab...
OAuth
“An open protocol to allow secure
authorization in a simple and
standard method from web, mobile
and desktop applica...
OAuth
 Doorkeeper
 Oauth2
Tópicos Futuros
 Filtros, ordenação, busca
 Paginação
 Documentação
 Limitação de uso
Pra Terminar
API é a intefarce de usuário para os
desenvolvedores
Trabalhe para garantir que ela seja funcional e prazeros...
Construindo APIs Usando Rails
Construindo APIs Usando Rails
Construindo APIs Usando Rails
Construindo APIs Usando Rails
Construindo APIs Usando Rails
Construindo APIs Usando Rails
Upcoming SlideShare
Loading in …5
×

Construindo APIs Usando Rails

1,646 views

Published on

Essa apresentação aconteceu no 17 encontro dos usuários de Rails de PE - Frevo on Rails. Nela, eu abordo 4 tópicos importantes na hora de implementar APIs: Rest, Consistencia, Versionamento e Segurança.

Published in: Technology
0 Comments
5 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,646
On SlideShare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
21
Comments
0
Likes
5
Embeds 0
No embeds

No notes for slide
  • http://www4.in.tum.de/~blanchet/api-design.pdf
  • If there's one thing that has gained wide adoption, it's RESTful principles. These were first introduced by Roy Felding in Chapter 5 of his dissertation on network based software architectures. The key principles of REST involve separating your API into logical resources. These resources are manipulated using HTTP requests where the method (GET, POST, PUT, PATCH, DELETE) has specific meaning.A resource should be nouns (not verbs!) that make sense from the perspective of the API consume.REST is a simple way to organize interactions between independent systems
  • It is a collection of resources, with four defined aspects
  • Client–server:A uniform interface separates clients from servers. This separation of concerns means that, for example, clients are not concerned with data storage, which remains internal to each server, so that the portability of client code is improved. Servers are not concerned with the user interface or user state, so that servers can be simpler and more scalable. Servers and clients may also be replaced and developed independently, as long as the interface between them is not altered.Stateless: The client–server communication is further constrained by no client context being stored on the server between requests. Each request from any client contains all of the information necessary to service the request, and any session state is held in the client.Cacheable: As on the World Wide Web, clients can cache responses. Responses must therefore, implicitly or explicitly, define themselves as cacheable, or not, to prevent clients reusing stale or inappropriate data in response to further requests. Well-managed caching partially or completely eliminates some client–server interactions, further improving scalability and performance.Layered system: A client cannot ordinarily tell whether it is connected directly to the end server, or to an intermediary along the way. Intermediary servers may improve system scalability by enabling load-balancing and by providing shared caches. They may also enforce security policies.Uniform interface:The uniform interface between clients and servers, discussed below, simplifies and decouples the architecture, which enables each part to evolve independently. The four guiding principles of this interface are detailed below.
  • To prevent an API consumer from having to hit the API again for an updated representation, have the API return the updated (or created) representation as part of the response.
  • Status codes tell the client application what it needs to do with the response in general terms. For example, if your API returns a 401 you know you need a logged in user. If the API returns a 403 you know the user you’re working with doesn’t have sufficient authorization. If the API returns a 418 you know that the API is telling you it’s a teapot and was probably written by knobs.Validation error in Rails = 422 unprocessableentityDelete in Rails = 204 No Content
  • Just like an HTML error page shows a useful error message to a visitor, an API should provide a useful error message in a known consumable format. The representation of an error should be no different than the representation of any resource, just with its own set of fields.API that return 200 but error in the response code.
  • Always version your API. Versioning helps you iterate faster and prevents invalid requests from hitting updated endpoints. It also helps smooth over any major API version transitions as you can continue to offer old API versions for a period of time.There are mixed opinions around whether an API version should be included in the URL or in a header. Academically speaking, it should probably be in a header. However, the version needs to be in the URL to ensure browser explorability of the resources across versions (remember the API requirements specified at the top of this post?).
  • https://blog.apigee.com/detail/restful_api_design_tips_for_versioning
  • https://blog.apigee.com/detail/restful_api_design_tips_for_versioning
  • A RESTful API should be stateless. This means that request authentication should not depend on cookies or sessions. Instead, each request should come with some sort authentication credentials.
  • HTTP Basic authentication (BA) implementation is the simplest technique for enforcing access controls to web resources because it doesn't require cookies, session identifier and login pages. Rather, HTTP Basic authentication uses static, standard HTTP headers which means that no handshakes have to be done in anticipation.One thing to watch out for is that the credentials are sent as clear text so we should be sure to use a secure connection or maybe a digest connection.
  • API keys/secrets are usually a long series of random characters that are difficult to guess. Username/password are typically much smaller in length, use common words, are generally insecure, and can be subject to brute force and dictionary attacks.
  • It provides a much needed solution for security web APIs without requiring users to share their usernames and passwordsOAuth provides a mechanism for users to grant access to private data without sharing their private credentials (username/password). Many sites have started enabling APIs to use OAuth because of its security and standard set of libraries.
  • Construindo APIs Usando Rails

    1. 1. Criando APIs - Usando Rails Fernando Kakimoto Desenvolvedor @ ThoughtWorks
    2. 2. O que é uma API mesmo? Application Programming Interface Biblioteca que inclui especificações para rotinas, estruturas de dados, objetos, classes e variáveis
    3. 3. Características de boas APIs  Fácil de aprender e memorizar  Dificilmente usada de maneira errada  Minimalista  Completa
    4. 4. Tópicos para hoje  REST  Consistência  Versionamento  Segurança
    5. 5. REST REpresentational State Transfer Um padrão arquitetural para sistemas hipermídias distribuídos
    6. 6. REST  URL base  Tipo de mídia  Operações (Método HTTP)
    7. 7. REST GET https://api.twitter.com/1.1/statuses/menti ons_timeline.json
    8. 8. REST GET https://api.twitter.com/1.1/statuses/menti ons_timeline.json URL base
    9. 9. REST GET https://api.twitter.com/1.1/statuses/menti ons_timeline.jsonTipo de mídia
    10. 10. REST GET https://api.twitter.com/1.1/statuses/menti ons_timeline.json Método
    11. 11. 2 URLs base por recurso • GET /tickets - recupera conjunto de tickets • GET /tickets/12 - recupera o ticket #12 • POST /tickets - cria um novo ticket • PUT /tickets/12 - atualiza ticket #12 • DELETE /tickets/12 - remove ticket #12
    12. 12. Restrições REST  Cliente-Servidor  Stateless  Cacheable  Sistema em camadas  Interface Uniforme
    13. 13. API RESTful API implementada usando princípios HTTP e REST
    14. 14. > nandokakimoto@Development$ rails new blog > nandokakimoto@blog$ rails generate scaffold Post name:string title:string content:text > nandokakimoto@blog$ rake routes posts GET /posts(.:format) posts#index POST /posts(.:format) posts#create new_post GET /posts/new(.:format) posts#new edit_post GET /posts/:id/edit(.:format) posts#edit post GET /posts/:id(.:format) posts#show PUT /posts/:id(.:format) posts#update DELETE /posts/:id(.:format) posts#destroy
    15. 15. Consistência
    16. 16. Métodos Safe Métodos que nunca modificam um recurso Dados não devem ser alterados como resultado de uma requisição GET
    17. 17. Métodos Idempotentes Métodos com o mesmo resultado mesmo que requisição seja repetida diversas vezes POST é o único método não idempotente
    18. 18. Código de Resposta Respostas HTTP padronizam como informar o cliente sobre o resultado da sua requisição
    19. 19. Código de Resposta  1xx - Informacional  2xx - Sucesso  3xx - Redirecionamento  4xx - Erro de cliente  5xx - Erro de servidor
    20. 20. > nandokakimoto@blog$ curl -v http://localhost:3000/posts.json * Connected to localhost (127.0.0.1) port 3000 (#0) > GET /posts.json HTTP/1.1 < < HTTP/1.1 200 OK < Server: WEBrick/1.3.1 (Ruby/1.9.3/2013-06-27) [{"content": "Melhor evento ever <3 <3 <3", "created_at": "2013-09-03T02:12:26Z", "id": 1, "name": "Frevo on Rails", "title": "Evento 14 Setembro", "updated_at": "2013- 09-03T02:12:26Z"}]
    21. 21. > nandokakimoto@blog$ curl -v -d "post[name]=Geek Night&post[title]=Scala Dojo&post[content]=Come and learn Scala" http://localhost:3000/posts.json * Connected to localhost (127.0.0.1) port 3000 (#0) > POST /posts.json HTTP/1.1 > Host: localhost:3000 < < HTTP/1.1 201 Created < Location: http://localhost:3000/posts/2 < Server: WEBrick/1.3.1 (Ruby/1.9.3/2013-06-27) {"content": "Come and learn Scala", "created_at": "2013-09-04T01:19:33Z", "id”: 2, "name": "Geek Night", "title":"Scala Dojo", "updated_at": "2013-09-04T01:19:33Z"}
    22. 22. > nandokakimoto@blog$ curl -v -d "post[name]=Geek Night&post[content]=Come and learn Scala" http://localhost:3000/posts.json * Connected to localhost (127.0.0.1) port 3000 (#0) > POST /posts.json HTTP/1.1 > Host: localhost:3000 > Content-Length: 56 > < HTTP/1.1 422 < Server: WEBrick/1.3.1 (Ruby/1.9.3/2013-06-27) < Content-Length: 28 {"title":["can't be blank"]}
    23. 23. Versionamento
    24. 24. Versionamento Sempre versione a sua API Diferentes opniões sobre se a versão deve estar na URL ou no cabeçalho
    25. 25. Versionamento  Versionist - https://github.com/bploetz/versionist  RocketPants - https://github.com/filtersquad/rocket_pants
    26. 26. config/routes.rb
    27. 27. > nandokakimoto@blog$ rake routes (…) GET /api/v1/products(.:format) api/v1/posts#index POST /api/v1/products(.:format) api/v1/posts#create GET /api/v1/products/new(.:format) api/v1/posts#new GET /api/v1/products/:id/edit(.:format) api/v1/posts#edit GET /api/v1/products/:id(.:format) api/v1/posts#show PUT /api/v1/products/:id(.:format) api/v1/posts#update DELETE /api/v1/products/:id(.:format) api/v1/posts#destroy
    28. 28. app/controllers/api/v1/posts_controller.rb
    29. 29. > nandokakimoto@blog$ curl -v http://localhost:3000/api/v1/posts.json * Connected to localhost (127.0.0.1) port 3000 (#0) > GET /api/v1/posts HTTP/1.1 > Host: localhost:3000 < < HTTP/1.1 200 OK < Server: WEBrick/1.3.1 (Ruby/1.9.3/2013-06-27) < Content-Length: 330 [{"content": "Melhor evento ever <3 <3 <3", "created_at":"2013-09-03T02:12:26Z", "id": 1, "name": "Frevo on Rails", "title": "Evento 14 Setembro", "updated_at": "2013- 09-03T02:12:26Z"}, {"content": "Come and learn Scala", "created_at": "2013-09- 04T01:19:33Z", "id": 2, "name": "Geek Night", "title": "Scala Dojo", "updated_at": "2013-09-04T01:19:33Z"}]
    30. 30. > nandokakimoto@blog$ curl -v http://localhost:3000/api/v1/posts/15.json * Connected to localhost (127.0.0.1) port 3000 (#0) > GET /api/v1/posts/15.json HTTP/1.1 > Host: localhost:3000 > < HTTP/1.1 404 Not Found < Server: WEBrick/1.3.1 (Ruby/1.9.3/2013-06-27) < Content-Length: 1 <
    31. 31. Versionamento Novo Requisito Mostrar apenas id, nome e título do post
    32. 32. config/routes.rb
    33. 33. > nandokakimoto@blog$ rake routes (…) GET /api/v2/posts(.:format) api/v2/posts#index POST /api/v2/posts(.:format) api/v2/posts#create GET /api/v2/posts/new(.:format) api/v2/posts#new GET /api/v2/posts/:id/edit(.:format) api/v2/posts#edit GET /api/v2/posts/:id(.:format) api/v2/posts#show PUT /api/v2/posts/:id(.:format) api/v2/posts#update DELETE /api/v2/posts/:id(.:format) api/v2/posts#destroy
    34. 34. app/controllers/api/v2/posts_controller.rb
    35. 35. RABL RABL (Ruby API Builder Language) consiste num sistema de template RAILS para geração de JSON
    36. 36. app/views/api/v2/show.rabl.json app/views/api/v2/index.rabl.json
    37. 37. > nandokakimoto@blog$ curl -v http://localhost:3000/api/v2/posts * Connected to localhost (127.0.0.1) port 3000 (#0) > GET /api/v2/posts HTTP/1.1 > Host: localhost:3000 < < HTTP/1.1 200 OK < Server: WEBrick/1.3.1 (Ruby/1.9.3/2013-06-27) < Content-Length: 113 [{"id":1,"name":"Frevo on Rails","title":"Evento 14 Setembro"},{"id”:2,"name":"Geek Night","title":"Scala Dojo"}]
    38. 38. Segurança
    39. 39. HTTP Basic Authentication  Solução mais simples  Fácil de implementar  Maioria dos clientes suportam
    40. 40. app/controllers/api/v2/posts_controller.rb
    41. 41. > nandokakimoto@blog$ curl -v http://localhost:3000/api/v2/posts * Connected to localhost (127.0.0.1) port 3000 (#0) > GET /api/v2/posts HTTP/1.1 > Host: localhost:3000 < < HTTP/1.1 200 OK < Server: WEBrick/1.3.1 (Ruby/1.9.3/2013-06-27) < Content-Length: 113 [{"id":1,"name":"Frevo on Rails","title":"Evento 14 Setembro"},{"id”:2,"name":"Geek Night","title":"Scala Dojo"}]
    42. 42. > nandokakimoto@blog$ curl -v -d "post[name]=RubyConf&post[title]=RubyConf Details&post[content]=RubyConf was awesome" http://localhost:3000/api/v2/posts.json * Connected to localhost (127.0.0.1) port 3000 (#0) > POST /api/v2/posts.json HTTP/1.1 > Host: localhost:3000 > Content-Length: 82 > < HTTP/1.1 401 Unauthorized < WWW-Authenticate: Basic realm="Application" < Server: WEBrick/1.3.1 (Ruby/1.9.3/2013-06-27) < Content-Length: 27 < HTTP Basic: Access denied.
    43. 43. > nandokakimoto@blog$ curl -v -d "post[name]=RubyConf&post[title]=RubyConf Details&post[content]=RubyConf was awesome" http://localhost:3000/api/v2/posts.json -u "admin:secret" * Connected to localhost (127.0.0.1) port 3000 (#0) * Server auth using Basic with user 'admin' > POST /api/v2/posts.json HTTP/1.1 > Authorization: Basic YWRtaW46c2VjcmV0 > Host: localhost:3000 > Content-Length: 83 > < HTTP/1.1 201 Created < Location: http://localhost:3000/api/v2/posts/3 < Server: WEBrick/1.3.1 (Ruby/1.9.3/2013-06-27) < Content-Length: 159 {"id":3,"name":"RubyConf","title":"RubyConf Details”}
    44. 44. Token de Acesso  Maior entropia  Token é salvo no servidor  Data de expiração
    45. 45. > nandokakimoto@blog$ rails g model api_key access_token invoke active_record create db/migrate/20130907211645_create_api_keys.rb create app/models/api_key.rb invoke test_unit create test/unit/api_key_test.rb create test/fixtures/api_keys.yml
    46. 46. app/model/api_key.rb
    47. 47. app/controllers/api/v2/posts_controller.rb
    48. 48. > nandokakimoto@blog$ curl -v http://localhost:3000/api/v2/posts curl -v http://localhost:3000/api/v2/posts * Connected to localhost (127.0.0.1) port 3000 (#0) > GET /api/v2/posts HTTP/1.1 > Host: localhost:3000 > < HTTP/1.1 401 Unauthorized < WWW-Authenticate: Token realm="Application" < Server: WEBrick/1.3.1 (Ruby/1.9.3/2013-06-27) < Content-Length: 27 < HTTP Token: Access denied.
    49. 49. > nandokakimoto@blog$ curl -v http://localhost:3000/api/v2/posts -H 'Authorization: Token token=”8219a125816b331d0e478eeab566bf7c”' * Connected to localhost (127.0.0.1) port 3000 (#0) > GET /api/v2/posts HTTP/1.1 > Host: localhost:3000 > Authorization: Token token="8219a125816b331d0e478eeab566bf7c" > < HTTP/1.1 200 OK < Server: WEBrick/1.3.1 (Ruby/1.9.3/2013-06-27) < Content-Length: 168 [{"id":1,"name":"Frevo on Rails","title":"Evento 14 Setembro"},{"id":2,"name":"Geek Night","title":"Scala Dojo"},{"id":3,"name":"RubyConf","title":"RubyConf Details"}]
    50. 50. OAuth “An open protocol to allow secure authorization in a simple and standard method from web, mobile and desktop application” - http://oauth.net -
    51. 51. OAuth  Doorkeeper  Oauth2
    52. 52. Tópicos Futuros  Filtros, ordenação, busca  Paginação  Documentação  Limitação de uso
    53. 53. Pra Terminar API é a intefarce de usuário para os desenvolvedores Trabalhe para garantir que ela seja funcional e prazerosa de usar

    ×