Falcon Overview
http://falconframework.org/
What is Falcon?
Falcon is a high-performance Python framework for building cloud APIs. It encourages the REST architectural style, and tries to do as little as possible while remaining highly effective.
As they say:
Ok, another WSGI server...
But light, fast and flexible!
Benchmarks

- GET request on each framework's app.
- Parse a route template with a single embedded parameter
- read a query parameter and a header
- set an x-header on the response, 10 KiB plain-text
Scenario
eag@MacKenzie-2:src (task/CYCLOPS-11 *)$pip install pecan
eag@MacKenzie-2:src (task/CYCLOPS-11 *)$pip install bottle
eag@MacKenzie-2:src (task/CYCLOPS-11 *)$ falcon-bench
No module named flask
Skipping missing library: flask
No module named werkzeug.wrappers
Skipping missing library: werkzeug
Benchmarking, Trial 1 of 3....done.
Benchmarking, Trial 2 of 3....done.
Benchmarking, Trial 3 of 3....done.
Results:
1. falcon.........25,638 req/sec or 39.00 μs/req (6x)
2. falcon-ext.....19,256 req/sec or 51.93 μs/req (4x)
3. bottle.........14,359 req/sec or 69.64 μs/req (3x)
4. pecan...........4,504 req/sec or 222.02 μs/req (1x)Try it yourself ...
pip install falcon
falcon-benchprint "hola"So fast and about coding?
You dont have any aysnc/sync dependency.
You should add your things.
Only create falcon API, add resources and speak WSGI!

import falcon
import json
from datetime import datetime
# REST resources ...
class MyResource:
def on_get(self, req, resp):
"""Handles GET requests"""
resp.status = falcon.HTTP_200
def handlerDatetime(obj):
if isinstance(obj, datetime):
return obj.strftime('%Y-%m-%dT%H:%M:%S.%fZ')
else:
raise TypeError(
'Object of type %s with value of %s is not JSON serializable'.format(type(obj),
repr(obj)))
resp.body = json.dumps({'status': 'ok', 'time': datetime.utcnow()}, default=handlerDatetime)
# falcon.API instances are callable WSGI apps
app = falcon.API()
# things will handle all requests to the '/things' URL path
app.add_route('/my_path', MyResource())
A basic falcon app
# Hooks
def token_is_valid(token, user_id):
return True
def auth(req, resp, params):
# Alternatively, use Talons or do this in WSGI middleware...
token = req.get_header('X-Auth-Token')
if token is None:
raise falcon.HTTPUnauthorized('Auth token required', 'Auth token required')
if not token_is_valid(token, params['user_id']):
raise falcon.HTTPUnauthorized('Invalid token', 'The token is invalid')
def check_media_type(req, resp, params):
if not req.client_accepts_json:
raise falcon.HTTPUnsupportedMediaType('only JSON please')
What more can do?
set hooks globally or with falcon.before
# Configure your WSGI server to load "things.app" (app is a WSGI callable)
app = falcon.API(before=[auth, check_media_type])
app.add_route('/users/{user_id}', MySuperResource())
class MySuperResource:
def __init__(self):
self.db = {'frodo': 'Frodo bolson', 'gandalf': 'Gandalf el blanco'}
def on_get(self, req, resp, user_id):
"""Handles GET requests"""
name_friends = req.get_param_as_list('name_friends', transform=str.upper, required=True)
easy_param = req.get_param('easy_param')
full_names = {name: self.db[key] for name in name_friends if key in self.db}
resp.set_header('X-Powered-By', 'Telefonica')
resp.status = falcon.HTTP_200
resp.body = json.dumps(full_names)
def on_post(self, req, resp, user_id):
# req.stream is wsgi.input but wrapped with Body for easy read
if req.stream.stream_len == 0:
raise falcon.HTTPBadRequest("Empty Body", "It was expected a json body")
body = req.stream.read()
try:
json_body = ujson.loads(body)
except ValueError as e:
print "Invalid json body %s", e
raise falcon.HTTPUnsupportedMediaType("Body is not a valid JSON object/array")
self.db[json_body['name']] = json_body['full_name']
resp.status = falcon.HTTP_201
resp.location = '/users/%s/amigos/%s' % (user_id, json_body['name'])
Headers, body, location
def on_put(self, request, response, user_id):
raise Exception('Can not put')
def handleException(ex, req, resp, params):
resp.body = json.dumps({'error': 'Exception'})
resp.status = falcon.HTTP_500
app.add_error_handler(Exception, handleException)
# Useful for debugging problems in your API; works with pdb.set_trace()
if __name__ == '__main__':
httpd = simple_server.make_server('127.0.0.1', 8000, app)
httpd.serve_forever()
# or uwsgi, apache, gunicorn, ...
Error handling...
QUESTIONS?

FALCON
By Eduardo Alonso García
FALCON
- 960