Apresentado no auditório da NuBank em São Paulo dia 28 de Março de 2017 - PyData Meetup.
- O que são Web APIs
- Consumindo web APIs com Python
- O que fazer com os dados?
- Publicando web APIs com Python.
http://github.com/rochacbruno/flasgger
6. API é só web?
API
App A
App B
def function_a(argument1, argument2):
...
def function_b(argument1, argument2):
...
return function_a('value1', 'value2')
API
API
Tipos de APIs: (baseadas em seus protocolos)
- Memory Pointers
- Object orientation members
- Remote Procedure Call
- Telnet
- EDI (Eletronic Data Interchange)
- Serial Com
- Parallel Com
- Universal Serial Bus
- ftp
- Ssh
- Gopher, POP, SMTP, IMAP...
- http
- …. (muitas outras)
7. Especificações, padrões e protocolos
- RPC / CORBA (Remote Procedure Call - Xerox 1976)
- EDI (Eletronic Data Exchange - University of Minnesota in 1991)
- Windows COMs (Component Object Model 1993)
- HTTP ( ietf 1990)
- SOA (Service-Oriented Architecture - Gartner Group 1996)
- XML + XML-RPC (Microsoft 1998)
- SOAP (W3C - 2000)
- REST (Roy Fielding 2000)
- AMQP (JPMorgan 2003)
- Web Services / WS protocol (W3C 2005)
- JSON + JSON RPC (Douglas Crockford - 2006)
- Thrift, MQ, ProtoBuf (Apache, Google, Pivotal etc…. - WIP)
- Microservices - (Martin Fowler - 2014)
- GraphQL - (Facebook 2015)
40 anos!
8. O que mudou em 20 anos?
- RPC / CORBA (Remote Procedure Call - Xerox 1976)
- EDI (Eletronic Data Exchange - University of Minnesota in 1991)
- Windows COMs (Component Object Model 1993)
- HTTP ( ietf 1990)
- SOA (Service-Oriented Architecture - Gartner Group 1996)
- XML + XML-RPC (Microsoft 1998)
- SOAP (W3C - 2000)
- REST (Roy Fielding 2000)
- AMQP (JPMorgan 2003)
- Web Services / WS protocol (W3C 2005)
- JSON + JSON RPC (Douglas Crockford - 2006)
- Thrift, MQ, ProtoBuf (Apache, Google, Pivotal etc…. - WIP)
- Microservices - (Martin Fowler - 2014)
- GraphQL - (Facebook 2015)
20 anos!
The Internet Days
9. O que é uma API web (http)?
Interface de comunicação baseada nos verbos HTTP com retorno de dados
padronizado em formatos largamente adotados como JSON e XML etc.
VERBO CRRUD Retorno esperado
POST Create 201 (created), 409, 50x
GET Read 200 (Ok), 204, 404, 500
PUT Replace 200, 201, 409, 404, 50x
PATCH Update 200, 201, 409, 404, 50x
DELETE Delete 200, 404, 50x
http://www.restapitutorial.com/lessons/httpmethods.html
10. O que é REST?
O que faz uma web API ser REST é a concordancia com o padrão HATEOAS, ou
seja, é a maneira como o fluxo de navegação e estado entre os recursos é
arquitetada, em uma API Restfull de verdade além dos dados em si também
trafegam informações semanticas, metadados de estado e localização dos recursos.
HyperMedia
define o
protocolo
e o estado!
11. GraphQL - (REST vai morrer?) http://graphql.org - http://graphene-python.org/
13. $ curl -XPOST http://localhost:5000/product -d “{‘id’: 5, ‘name’: ‘foo’, ‘category’: ‘bar’}”
….
Response 201 Created
{
“msg”: “Produto inserido com sucesso”,
“product”: “/product/5”
}
Cliente HTTP
*Programa capaz de se comunicar através dos verbos HTTP (GET, POST, PUT….)
14. https://httpie.org/
● Colorized and formatted terminal output
● Built-in JSON support
● Forms and file uploads
● HTTPS, proxies, and authentication
● Extensions
● Linux, Mac OSX, and Windows support
● And more…
30. Caracteristicas de uma boa web API
1. CAP
a. Consistencia(c) imediata é sacrificada
em troca de Disponibilidade(a) e Particionamento(p)!
2. Escalável
a. MicroServices (fila de processamento)
b. Caching
c. Async Response
3. Stateless
a. REST/HATEOAS/OAuth
4. Concisa
a. Versionamento
b. Formato de dados
c. Documentação
5. Segura
a. Throtling
b. Autenticação
31. Tem framework
para fazer as
mágica pra nóis?
MethodViews
Flask-Classy
Flask RestFull
Flask RestPlus
Flask-Potion
Eve
Conexxion
Flasgger
33. from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_potion import Api, ModelResource
app = Flask(__name__)
db = SQLAlchemy(app)
class Book(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(),
nullable=False)
year_published = db.Column(db.Integer)
db.create_all()
class BookResource(ModelResource):
class Meta:
model = Book
api = Api(app)
api.add_resource(BookResource)
34. from eve import Eve
app = Eve()
app.config.MONGO_HOST = “localhost”
app.run()
40. from sanic import Sanic as Flask
from sanic.response import json as jsonify
app = Flask()
@app.route("/")
async def test(request):
return jsonify({"hello": "world"})
app.run(host="0.0.0.0", port=8000)
from flask import Flask
from flask import jsonify
app = Flask()
@app.route("/")
def test():
return jsonify({"hello": "world"})
app.run(host="0.0.0.0", port=8000)
Flask (sync, blocking) Sanic (asyncio)
Otimização prematura é a raiz de todo o mal!
Pode ser que seu projeto não precise de AsyncIO
Antes de partir para o Sanic + AsyncIO tente:
- Arquitetura distribuida (+workers)
- Gunicorn, twisted, gevent
- Async microservices (e MQs)
41.
42. import nameko
class MyService(nameko.Service):
@nameko.rpc
def my_resource():
data = # expensive computation
return data
import nameko
from flask import Flask
from flask import jsonify
app = Flask()
@app.route("/")
def test():
with nameko.rpc(‘my-rabbit’) as rpc:
result = rpc.my_resource()
return jsonify(result)
# or return only the “future” as task id
Microservices
Nameko + rabbit MQ (microserviço)
+ $ gunicorn -w 4 -b 127.0.0.1:4000 myproject:app
+ $ twistd web --wsgi myproject.app
+ $ gevent.wsgi.WSGIServer(('', 5000), app)
Flask API
+ $ nameko run my_service -c 10
+ $ docker run -d --hostname my-rabbit --name
my-rabbit -p 15672:15672 -p 5672:5672
rabbitmq:3-management
43. API é Front-End!
● Performance
● Design
● Usabilidade
● User Experience
● Java Script Compat
● ...
49. @app.route('/product', methods=['POST'])
def post_product():
data = request.json
product.create(**data)
result = {'msg': 'Produto inserido com sucesso!',
‘product’: url_for(‘get_product’, product.id)}
….
return jsonify(**result), 201
$ curl -XPOST http://localhost:5000/product -d “{‘id’: 5, ‘name’: ‘foo’, ‘category’: ‘bar’}”
….
Response 201 Created
{
“msg”: “Produto inserido com sucesso”,
“product”: “/product/5”
}
50.
51. from flasgger import Swagger, validate
Swagger(app)
@app.route('/product', methods=['POST'])
def post_product():
“””Create a new product
parameters:
- in: body
schema:
required: [name, category, id]
properties:
name:
type: string description: The name of the product
“””
data = request.json
validate(data)
return jsonify(result={'msg': 'Deu Certo!'}), 201
54. from flasgger import Swagger, SwaggerView
from flasgger import validate, Schema, fields
class Product(Schema):
name = fields.Str(required=True)
category = fields.Nested(Category)
id = fields.Str(required=True)
class ProductAPIView(SwaggerView):
parameters = Product
validation = True
def post(self):
return jsonify(result={'msg': 'Deu Certo!'}), 201
55.
56. Tutorial de Flask
http://bit.ly/whattheflask
DEMO do Flasgger
http://flasgger-rochacbruno.rhcloud.com/
Tutorial de Flasgger
http://brunorocha.org/python/flask/flasgger-api-playgrou
nd-with-flask-and-swagger-ui.html
API com Flasgger baseada em MicroServices
http://brunorocha.org/python/microservices-with-python-
rabbitmq-and-nameko.html