REST API FOR HUMANS™eve
eve
nicolaiarocci
CoFounder and Lead Dev @C2K
Open Source • MongoDB Master • Speaking • CoderDojo • PSF
PHILOSOPHY
YOU HAVE DATA
STORED SOMEWHERE
YOU NEED
A FULL FEATURED REST API
TO EXPOSE YOUR DATA
PIP INSTALL EVE
TO GET A FEATURE RICH RESTFUL WEB API FOR FREE
POWERED BY
QUICKSTART
#1 run.py
from eve import Eve
app = Eve()
!
if __name__ == '__main__':
app.run()
#2 settings.py
# just a couple API endpoints with no custom
# schema or rules. Will just dump from people
# and books db c...
#3 launch the API
$ python run.py
* Running on http://127.0.0.1:5000/
#4 enjoy
$ curl -i http://127.0.0.1:5000/people
{
"_items": [],
"_links": {
"self": {
"href": "127.0.0.1:5000/people",
"ti...
#4 enjoy
$ curl -i http://127.0.0.1:5000/people
{
"_items": [],
"_links": {
"self": {
"href": "127.0.0.1:5000/people",
"ti...
#4 enjoy
$ curl -i http://127.0.0.1:5000/people
{
"_items": [],
"_links": {
"self": {
"href": "127.0.0.1:5000/people",
"ti...
#4 enjoy
$ curl -i http://127.0.0.1:5000/people
{
"_items": [],
"_links": {
"self": {
"href": "127.0.0.1:5000/people",
"ti...
#4 enjoy
$ curl -i http://127.0.0.1:5000/people
{
"_items": [],
"_links": {
"self": {
"href": "127.0.0.1:5000/people",
"ti...
settings.py
# let’s connect to a mongo instance
!
MONGO_HOST = 'localhost'
MONGO_PORT = 27017
MONGO_USERNAME = 'user'
MONG...
settings.py
# let’s also add some validation rules
!
DOMAIN['people']['schema'] = {
'name': {
'type': 'string',
'maxlength...
settings.py
# let’s also add some validation rules
!
DOMAIN['people']['schema'] = {
'name': {
'type': 'string',
'maxlength...
settings.py
# allow write access to API endpoints
# (default is [‘GET’] for both settings)
!
# /people
RESOURCE_METHODS = ...
settings.py
# allow write access to API endpoints
# (default is [‘GET’] for both settings)
!
# /people
RESOURCE_METHODS = ...
settings.py
# allow write access to API endpoints
# (default is [‘GET’] for both settings)
!
# /people
RESOURCE_METHODS = ...
settings.py
# allow write access to API endpoints
# (default is [‘GET’] for both settings)
!
# /people
RESOURCE_METHODS = ...
settings.py
# allow write access to API endpoints
# (default is [‘GET’] for both settings)
!
# /people
RESOURCE_METHODS = ...
settings.py
# a few more config options
!
DOMAIN[‘people’].update(
{
‘item_title’: ‘person’,
‘cache_control’: ‘max-age=10,...
FEATURES
MONGO FILTERS
?where={“lastname”: “Doe”}
PYTHON FILTERS
?where=lastname==“Doe”
SORTING
?sort=[(“total”: -1)]
SORT BY ‘TOTAL’, DESCENDING ORDER
PAGINATION
?max_results=20&page=2
MAX 20 RESULTS/PAGE; PAGE 2
PROJECTIONS
?projection={"avatar": 0}
RETURN ALL FIELDS BUT ‘AVATAR’
PROJECTIONS
?projection={"lastname": 1}
ONLY RETURN ‘LASTNAME’
EMBEDDED RESOURCES
?embedded={"author": 1}
NOT EMBEDDED
$ curl -i <url>
!
HTTP/1.1 200 OK
{

"title": "Book Title",

"description": "book description",

"author": “5...
EMBEDDED
$ curl -i <url>?embedded={“author”: 1}
!
HTTP/1.1 200 OK
{

"title": "Book Title",

"description": "book descript...
EMBEDDED
$ curl -i <url>?embedded={“author”: 1}
!
HTTP/1.1 200 OK
{

"title": "Book Title",

"description": "book descript...
JSON AND XML
BUILT-IN FOR ALL RESPONSES
APPLICATION/JSON
[
{
"firstname": "Mark",
"lastname": "Green",
"born": "Sat, 23 Feb 1985 12:00:00 GMT",
"role": ["copy", "...
APPLICATION/JSON
[
{
"firstname": "Mark",
"lastname": "Green",
"born": "Sat, 23 Feb 1985 12:00:00 GMT",
"role": ["copy", "...
APPLICATION/XML
<resource href=“localhost:5000/people" title="people">
<resource href="localhost:5000/people/<id>" title="...
HATEOAS
HYPERMEDIA AS THE ENGINE OF APPLICATION STATE
HATEOAS
{
“_links”: {
“self”: {
“href”: “/people”,
“title”: “people”},
“parent”: {
“href”: “/”,
“title”: “home”},
“next”: ...
DOCUMENT VERSIONS
?version=3
?version=all
?version=diffs
FILE STORAGE
FILES ARE STORED IN GRIDFS BY DEFAULT
FILE STORAGE / SETTINGS
accounts = {

'name': {'type': 'string'},

'pic': {'type': 'media'},

…

}
FILE STORAGE
$ curl F “name=doe” —F “pic=@profile.jpg" <url>
HTTP/1.1 200 OK
!
$ curl -i <url>
HTTP/1.1 200 OK
{

"name": ...
FILE STORAGE
$ curl F “name=doe” —F “pic=@profile.jpg" <url>
HTTP/1.1 200 OK
!
$ curl -i <url>
HTTP/1.1 200 OK
{

"name": ...
FILE STORAGE (WITH META)
$ curl -i <url>
HTTP/1.1 200 OK
{

"name": "john",

"pic": {
“file”: ”/9j/4QAYRXhpZgAASUkqAAgAAAA...
RATE LIMITING
POWERED
RATE LIMITING / SETTINGS
# Rate limit on GET requests:
# 1 requests 1 minute window (per client)
!
RATE_LIMIT_GET = (1, 60)
RATE LIMITING / GET #1
$ curl -i <url>
!
HTTP/1.1 200 OK
X-RateLimit-Limit: 1
X-RateLimit-Remaining: 0
X-RateLimit-Reset: ...
RATE LIMITING / GET #2
$ curl -i <url>
!
HTTP/1.1 429 TOO MANY REQUESTS
CONDITIONAL REQUESTS
ALLOW CLIENTS TO ONLY REQUEST
NON-CACHED CONTENT
IF-MODIFIED-SINCE
If-Modified-Since: Wed, 05 Dec 2012 09:53:07 GMT
“Please return modified data since <date> or 304”
IF-NONE-MATCH
If-None-Match:1234567890123456789012345678901234567890
“Please return data if it has changed or 304”
>
BULK INSERTS
INSERT MULTIPLE DOCUMENTS WITH A SINGLE REQUEST
BULK INSERTS / REQUEST
$ curl -d ‘
[
{
"firstname": "barack",
"lastname": “obama"
},
{
"firstname": "mitt",
"lastname": “r...
BULK INSERTS / RESPONSE
[
{
"_status": "OK",
"_updated": "Thu, 22 Nov 2012 15:22:27 GMT",
"_id": "50ae43339fa12500024def5b...
BULK INSERTS / RESPONSE
[
{
"_status": "OK",
"_updated": "Thu, 22 Nov 2012 15:22:27 GMT",
"_id": "50ae43339fa12500024def5b...
DATA INTEGRITY
CONCURRENCY CONTROL
NO OVERWRITING DOCUMENTS
WITH OBSOLETE VERSIONS
DATA INTEGRITY / CONCURRENCY
$ curl -X PATCH -i <url> 

-d '{"firstname": "ronald"}'

HTTP/1.1 403 FORBIDDEN
IF-MATCH MISS...
DATA INTEGRITY / CONCURRENCY
$ curl -X PATCH -i <url>

-H "If-Match: <obsolete_etag>”

-d '{"firstname": “ronald”}'
!
HTTP...
DATA INTEGRITY / CONCURRENCY
$ curl -X PATCH -i <url>

-H “If-Match: 206fb4a39815cc0ebf48b2b52d7…”

-d '{"firstname": “ron...
DATA VALIDATION
[
{
"_status": "ERR",
"_issues": {“name”: “value ‘clinton’ not unique”}
},
{
"_status": “OK",
"_updated": ...
AUTHENTICATION
AND AUTHORIZATION
BASIC, TOKEN AND HMAC AUTH SUPPORTED
RUNS ON ALL PYTHONS
2.6 / 2.7 / 3.3 / 3.4 and PyPy
AND MORE
CORS. CACHE CONTROL. VERSONING AND MORE.
BSD LICENSED
TEAR IT APART
DEVELOPERS
CUSTOM DATA LAYERS
BUILD YOUR OWN DATA LAYER
SQL ALCHEMY (WIP)
SQLALCHEMY (WIP)
@registerSchema('invoices')
class Invoices(CommonColumns):
__tablename__ = 'invoices'
number = db.Column(...
ELASTICSERCH
MONGODB (DEFAULT)
AUTHENTICATION
BASIC | TOKEN | HMAC
SECURITY AT A GLANCE
• global authentication
• custom endpoint auth
• public enpoints and methods
• role based access cont...
three steps
Auth
tutorial
#1
IMPORT BASE AUTH CLASS
#2
OVERRIDE CHECK_AUTH() METHOD
#3
PASS CUSTOM CLASS TO THE EVE APP
Done
CUSTOM VALIDATION
EXTEND THE BUILT-IN VALIDATION SYSTEM
CUSTOM VALIDATION
• add custom data types
• add custom validation logic
EVENT HOOKS
PLUG CUSTOM ACTIONS INTO THE API LOOP
EVENT HOOKS AT A GLANCE
• POST on_insert/on_inserted
• GET on_fetch/on_fetched
• PATCH on_update/on_updated
• PUT on_repla...
TRANSFORM INCOMING DOCUMENTS
CUSTOM FILE STORAGE
custom MediaStorage subclasses to S3, File System, you name it
COMMUNITY
EVE-DOCS
GENERATES DOCUMENTATION FOR EVE APIS IN HTML AND JSON FORMATS
CHARLES FLYNN
EVE-DOCS
EVE-MONGOENGINE
ENABLES MONGOENGINE ORM MODELS TO BE USED AS EVE SCHEMA
STANISLAV HELLER
EVE-ELASTIC
ELASTICSEARCH DATA LAYER FOR EVE REST FRAMEWORK
PETR JASEK
EVE-MOCKER
MOCKING TOOL FOR EVE POWERED REST APIS
THOMAS SILEO
{48: <you name here>}
Bryan Cattle Christoph Witzany Daniele Pizzolli
dccrazyboy Dong Wei Ming Florian Rathgeber Francisco...
NOW COOKING
GeoJSON
Support and validation for GeoJSON types
!
Point, LineString, Polygon, MultiPoint,
MultiLineString, MultiPolygon, ...
JSONP*
IN CASE YOUR BROWSER/JS FRAMEWORK CANT HANDLE C.O.R.S.
* PENDING SECURITY REVIEW
JSON-LD / HAL / SIREN*
CURSTOM RENDER CLASSES
* MAYBE (UNDER CONSIDERATION)
python-eve.org
JOIN US
eve
nicolaiarocci
Thank you!
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Upcoming SlideShare
Loading in...5
×

Eve - REST API for Humans™

4,291

Published on

Introducing the Eve REST API Framework.

FOSDEM 2014, Brussels
PyCon Sweden 2014, Stockholm
PyCon Italy 2014, Florence
Python Meetup, Helsinki
EuroPython 2014, Berlin

Published in: Technology, News & Politics
3 Comments
13 Likes
Statistics
Notes
No Downloads
Views
Total Views
4,291
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
43
Comments
3
Likes
13
Embeds 0
No embeds

No notes for slide

Eve - REST API for Humans™

  1. 1. REST API FOR HUMANS™eve eve
  2. 2. nicolaiarocci CoFounder and Lead Dev @C2K Open Source • MongoDB Master • Speaking • CoderDojo • PSF
  3. 3. PHILOSOPHY
  4. 4. YOU HAVE DATA STORED SOMEWHERE
  5. 5. YOU NEED A FULL FEATURED REST API TO EXPOSE YOUR DATA
  6. 6. PIP INSTALL EVE TO GET A FEATURE RICH RESTFUL WEB API FOR FREE
  7. 7. POWERED BY
  8. 8. QUICKSTART
  9. 9. #1 run.py from eve import Eve app = Eve() ! if __name__ == '__main__': app.run()
  10. 10. #2 settings.py # just a couple API endpoints with no custom # schema or rules. Will just dump from people # and books db collections ! DOMAIN = { ‘people’: {} ‘books’: {} }
  11. 11. #3 launch the API $ python run.py * Running on http://127.0.0.1:5000/
  12. 12. #4 enjoy $ curl -i http://127.0.0.1:5000/people { "_items": [], "_links": { "self": { "href": "127.0.0.1:5000/people", "title": "people" }, "parent": { "href": "127.0.0.1:5000", "title": "home"} } }
  13. 13. #4 enjoy $ curl -i http://127.0.0.1:5000/people { "_items": [], "_links": { "self": { "href": "127.0.0.1:5000/people", "title": “people" }, "parent": { "href": "127.0.0.1:5000", "title": “home"} } } HATEOAS AT WORK HERE
  14. 14. #4 enjoy $ curl -i http://127.0.0.1:5000/people { "_items": [], "_links": { "self": { "href": "127.0.0.1:5000/people", "title": "people" }, "parent": { "href": "127.0.0.1:5000", "title": "home"} } } CLIENTS CAN EXPLORE THE API PROGRAMMATICALLY
  15. 15. #4 enjoy $ curl -i http://127.0.0.1:5000/people { "_items": [], "_links": { "self": { "href": "127.0.0.1:5000/people", "title": "people" }, "parent": { "href": "127.0.0.1:5000", "title": "home"} } } AND EVENTUALLY FILL THEIR UI
  16. 16. #4 enjoy $ curl -i http://127.0.0.1:5000/people { "_items": [], "_links": { "self": { "href": "127.0.0.1:5000/people", "title": "people" }, "parent": { "href": "127.0.0.1:5000", "title": "home"} } } EMTPY RESOURCE AS WE DIDN’T CONNECT ANY DATASOURCE
  17. 17. settings.py # let’s connect to a mongo instance ! MONGO_HOST = 'localhost' MONGO_PORT = 27017 MONGO_USERNAME = 'user' MONGO_PASSWORD = 'user' MONGO_DBNAME = ‘apitest'
  18. 18. settings.py # let’s also add some validation rules ! DOMAIN['people']['schema'] = { 'name': { 'type': 'string', 'maxlength': 50, 'unique': True} 'email': { 'type': 'string', 'regex': '^S+@S+$'}, 'location': { 'type': 'dict', 'schema': { 'address': {'type': 'string'}, 'city': {'type': 'string'}}}, 'born': {'type': ‘datetime'}}
  19. 19. settings.py # let’s also add some validation rules ! DOMAIN['people']['schema'] = { 'name': { 'type': 'string', 'maxlength': 50, 'unique': True} 'email': { 'type': 'string', 'regex': '^S+@S+$'}, 'location': { 'type': 'dict', 'schema': { 'address': {'type': 'string'}, 'city': {'type': 'string'}}}, 'born': {'type': ‘datetime'}} THIS REGEX SUCKS. DON’T USE IN PRODUCTION
  20. 20. settings.py # allow write access to API endpoints # (default is [‘GET’] for both settings) ! # /people RESOURCE_METHODS = ['GET','POST'] ! # /people/<id> ITEM_METHODS = ['GET','PATCH','PUT','DELETE']
  21. 21. settings.py # allow write access to API endpoints # (default is [‘GET’] for both settings) ! # /people RESOURCE_METHODS = ['GET','POST'] ! # /people/<id> ITEM_METHODS = ['GET','PATCH','PUT','DELETE'] ADD/CREATE ONE OR MORE ITEMS
  22. 22. settings.py # allow write access to API endpoints # (default is [‘GET’] for both settings) ! # /people RESOURCE_METHODS = ['GET', 'POST'] ! # /people/<id> ITEM_METHODS = ['GET','PATCH','PUT','DELETE'] EDIT ITEM
  23. 23. settings.py # allow write access to API endpoints # (default is [‘GET’] for both settings) ! # /people RESOURCE_METHODS = ['GET', 'POST'] ! # /people/<id> ITEM_METHODS = ['GET','PATCH','PUT','DELETE'] REPLACE ITEM
  24. 24. settings.py # allow write access to API endpoints # (default is [‘GET’] for both settings) ! # /people RESOURCE_METHODS = ['GET', 'POST'] ! # /people/<id> ITEM_METHODS = ['GET','PATCH','PUT','DELETE'] YOU GUESSED IT
  25. 25. settings.py # a few more config options ! DOMAIN[‘people’].update( { ‘item_title’: ‘person’, ‘cache_control’: ‘max-age=10,must-revalidate, ‘cache_expires’: 10, ‘additional_lookup’: { ‘url’: ‘regex)”[w]+”)’, ‘field’: ‘name’ } )
  26. 26. FEATURES
  27. 27. MONGO FILTERS ?where={“lastname”: “Doe”}
  28. 28. PYTHON FILTERS ?where=lastname==“Doe”
  29. 29. SORTING ?sort=[(“total”: -1)] SORT BY ‘TOTAL’, DESCENDING ORDER
  30. 30. PAGINATION ?max_results=20&page=2 MAX 20 RESULTS/PAGE; PAGE 2
  31. 31. PROJECTIONS ?projection={"avatar": 0} RETURN ALL FIELDS BUT ‘AVATAR’
  32. 32. PROJECTIONS ?projection={"lastname": 1} ONLY RETURN ‘LASTNAME’
  33. 33. EMBEDDED RESOURCES ?embedded={"author": 1}
  34. 34. NOT EMBEDDED $ curl -i <url> ! HTTP/1.1 200 OK {
 "title": "Book Title",
 "description": "book description",
 "author": “52da465a5610320002660f94"
 } RAW FOREIGN KEY (DEFAULT)
  35. 35. EMBEDDED $ curl -i <url>?embedded={“author”: 1} ! HTTP/1.1 200 OK {
 "title": "Book Title",
 "description": "book description",
 "author": {
 “firstname”: “Mark”,
 “lastname”: “Green”,
 }
 } REQUEST EMBEDDED AUTHOR
  36. 36. EMBEDDED $ curl -i <url>?embedded={“author”: 1} ! HTTP/1.1 200 OK {
 "title": "Book Title",
 "description": "book description",
 "author": {
 “firstname”: “Mark”,
 “lastname”: “Green”,
 }
 } EMBEDDED DOCUMENT
  37. 37. JSON AND XML BUILT-IN FOR ALL RESPONSES
  38. 38. APPLICATION/JSON [ { "firstname": "Mark", "lastname": "Green", "born": "Sat, 23 Feb 1985 12:00:00 GMT", "role": ["copy", "author"], "location": {"city": "New York", "address": "4925 Lacross Road"}, "_id": "50bf198338345b1c604faf31", "_updated": "Wed, 05 Dec 2012 09:53:07 GMT", "_created": "Wed, 05 Dec 2012 09:53:07 GMT", "_etag": "ec5e8200b8fa0596afe9ca71a87f23e71ca30e2d", }, { "firstname": "John", ... }, ]
  39. 39. APPLICATION/JSON [ { "firstname": "Mark", "lastname": "Green", "born": "Sat, 23 Feb 1985 12:00:00 GMT", "role": ["copy", "author"], "location": {"city": "New York", "address": "4925 Lacross Road"}, "_id": "50bf198338345b1c604faf31", "_updated": "Wed, 05 Dec 2012 09:53:07 GMT", "_created": "Wed, 05 Dec 2012 09:53:07 GMT", "_etag": "ec5e8200b8fa0596afe9ca71a87f23e71ca30e2d", }, { "firstname": "John", ... }, ] METAFIELDS ARE CONFIGURABLE
  40. 40. APPLICATION/XML <resource href=“localhost:5000/people" title="people"> <resource href="localhost:5000/people/<id>" title="person"> <lastname>Green</lastname> <firstname>Mark</firstname> <born>Wed, 05 Dec 2012 09:53:07 GMT</born> <role>author</role> <role>copy</role> <location> <address>4925 Lacross Road</address> <city>New York</city> </location> <_id>50bf198338345b1c604faf31</_id> <created>Wed, 05 Dec 2012 09:53:07 GMT</created> <updated>Sat, 18 Jan 2014 09:16:10 GMT</updated> <etag>ec5e8200b8fa0596afe9ca71a87f23e71ca30e2d</etag> </resource> ... <resource>
  41. 41. HATEOAS HYPERMEDIA AS THE ENGINE OF APPLICATION STATE
  42. 42. HATEOAS { “_links”: { “self”: { “href”: “/people”, “title”: “people”}, “parent”: { “href”: “/”, “title”: “home”}, “next”: { “href”: “/people?page=2”, “title”: “next page”}, “last”: { “href: “/people?page=10”, “title”: “last page”} } }
  43. 43. DOCUMENT VERSIONS ?version=3 ?version=all ?version=diffs
  44. 44. FILE STORAGE FILES ARE STORED IN GRIDFS BY DEFAULT
  45. 45. FILE STORAGE / SETTINGS accounts = {
 'name': {'type': 'string'},
 'pic': {'type': 'media'},
 …
 }
  46. 46. FILE STORAGE $ curl F “name=doe” —F “pic=@profile.jpg" <url> HTTP/1.1 200 OK ! $ curl -i <url> HTTP/1.1 200 OK {
 "name": "john",
 "pic": "/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAA…"
 } MULTIPART/DATA-FORM POST
  47. 47. FILE STORAGE $ curl F “name=doe” —F “pic=@profile.jpg" <url> HTTP/1.1 200 OK ! $ curl -i <url> HTTP/1.1 200 OK {
 "name": "john",
 "pic": "/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAA…"
 } FILES RETURNED AS BASE64 STRINGS
  48. 48. FILE STORAGE (WITH META) $ curl -i <url> HTTP/1.1 200 OK {
 "name": "john",
 "pic": { “file”: ”/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAA”, “content_type”: “image/jpeg”, “name”: “profile.jpg”, “length”: 8129 }
 } EXTENDED_MEDIA_INFO: TRUE
  49. 49. RATE LIMITING POWERED
  50. 50. RATE LIMITING / SETTINGS # Rate limit on GET requests: # 1 requests 1 minute window (per client) ! RATE_LIMIT_GET = (1, 60)
  51. 51. RATE LIMITING / GET #1 $ curl -i <url> ! HTTP/1.1 200 OK X-RateLimit-Limit: 1 X-RateLimit-Remaining: 0 X-RateLimit-Reset: 1390486659
  52. 52. RATE LIMITING / GET #2 $ curl -i <url> ! HTTP/1.1 429 TOO MANY REQUESTS
  53. 53. CONDITIONAL REQUESTS ALLOW CLIENTS TO ONLY REQUEST NON-CACHED CONTENT
  54. 54. IF-MODIFIED-SINCE If-Modified-Since: Wed, 05 Dec 2012 09:53:07 GMT “Please return modified data since <date> or 304”
  55. 55. IF-NONE-MATCH If-None-Match:1234567890123456789012345678901234567890 “Please return data if it has changed or 304” >
  56. 56. BULK INSERTS INSERT MULTIPLE DOCUMENTS WITH A SINGLE REQUEST
  57. 57. BULK INSERTS / REQUEST $ curl -d ‘ [ { "firstname": "barack", "lastname": “obama" }, { "firstname": "mitt", "lastname": “romney” } ]' -H 'Content-Type: application/json’ <url>
  58. 58. BULK INSERTS / RESPONSE [ { "_status": "OK", "_updated": "Thu, 22 Nov 2012 15:22:27 GMT", "_id": "50ae43339fa12500024def5b", "_etag": "749093d334ebd05cf7f2b7dbfb7868605578db2c" "_links": {"self": {"href": “<url>”, "title": "person"}} }, { "_status": "OK", "_updated": "Thu, 22 Nov 2012 15:22:27 GMT", "_id": "50ae43339fa12500024def5c", "_etag": "62d356f623c7d9dc864ffa5facc47dced4ba6907" "_links": {"self": {"href": “<url>", "title": "person"}} } ] COHERENCE MODE OFF: ONLY META FIELDS ARE RETURNED
  59. 59. BULK INSERTS / RESPONSE [ { "_status": "OK", "_updated": "Thu, 22 Nov 2012 15:22:27 GMT", "_id": "50ae43339fa12500024def5b", "_etag": "749093d334ebd05cf7f2b7dbfb7868605578db2c" "_links": {"self": {"href": “<url>”, "title": “person”}}, "firstname": "barack", "lastname": "obama", ! }, { "_status": "OK", "_updated": "Thu, 22 Nov 2012 15:22:27 GMT", "_id": "50ae43339fa12500024def5c", "_etag": "62d356f623c7d9dc864ffa5facc47dced4ba6907" "_links": {"self": {"href": “<url>", "title": "person"}} "firstname": "mitt", "lastname": "romney", } ] COHERENCE MODE ON: ALL FIELDS RETURNED
  60. 60. DATA INTEGRITY CONCURRENCY CONTROL NO OVERWRITING DOCUMENTS WITH OBSOLETE VERSIONS
  61. 61. DATA INTEGRITY / CONCURRENCY $ curl -X PATCH -i <url> 
 -d '{"firstname": "ronald"}'
 HTTP/1.1 403 FORBIDDEN IF-MATCH MISSING
  62. 62. DATA INTEGRITY / CONCURRENCY $ curl -X PATCH -i <url>
 -H "If-Match: <obsolete_etag>”
 -d '{"firstname": “ronald”}' ! HTTP/1.1 412 PRECONDITION FAILED
 ETAG MISMATCH
  63. 63. DATA INTEGRITY / CONCURRENCY $ curl -X PATCH -i <url>
 -H “If-Match: 206fb4a39815cc0ebf48b2b52d7…”
 -d '{"firstname": “ronald"}' ! HTTP/1.1 200 OK UPDATE ALLOWED IF CLIENT AND SERVER ETAG MATCH
  64. 64. DATA VALIDATION [ { "_status": "ERR", "_issues": {“name”: “value ‘clinton’ not unique”} }, { "_status": “OK", "_updated": "Thu, 22 Nov 2012 15:22:27 GMT”, "_id": “50ae43339fa12500024def5c", "_etag": “62d356f623c7d9dc864ffa5facc47dced4ba6907" "_links": { "self": { "href": “<url>”, "title": “person" } } } ]
  65. 65. AUTHENTICATION AND AUTHORIZATION BASIC, TOKEN AND HMAC AUTH SUPPORTED
  66. 66. RUNS ON ALL PYTHONS 2.6 / 2.7 / 3.3 / 3.4 and PyPy
  67. 67. AND MORE CORS. CACHE CONTROL. VERSONING AND MORE.
  68. 68. BSD LICENSED TEAR IT APART
  69. 69. DEVELOPERS
  70. 70. CUSTOM DATA LAYERS BUILD YOUR OWN DATA LAYER
  71. 71. SQL ALCHEMY (WIP)
  72. 72. SQLALCHEMY (WIP) @registerSchema('invoices') class Invoices(CommonColumns): __tablename__ = 'invoices' number = db.Column(db.Integer) people = db.Column(db.Integer, db.ForeignKey('people._id'))
  73. 73. ELASTICSERCH
  74. 74. MONGODB (DEFAULT)
  75. 75. AUTHENTICATION BASIC | TOKEN | HMAC
  76. 76. SECURITY AT A GLANCE • global authentication • custom endpoint auth • public enpoints and methods • role based access control • user restricted resource access
  77. 77. three steps Auth tutorial
  78. 78. #1 IMPORT BASE AUTH CLASS
  79. 79. #2 OVERRIDE CHECK_AUTH() METHOD
  80. 80. #3 PASS CUSTOM CLASS TO THE EVE APP
  81. 81. Done
  82. 82. CUSTOM VALIDATION EXTEND THE BUILT-IN VALIDATION SYSTEM
  83. 83. CUSTOM VALIDATION • add custom data types • add custom validation logic
  84. 84. EVENT HOOKS PLUG CUSTOM ACTIONS INTO THE API LOOP
  85. 85. EVENT HOOKS AT A GLANCE • POST on_insert/on_inserted • GET on_fetch/on_fetched • PATCH on_update/on_updated • PUT on_replace/on_replaced • DELETE on_delete/on_deteled • on_pre_<method>; on_post_<method>
  86. 86. TRANSFORM INCOMING DOCUMENTS
  87. 87. CUSTOM FILE STORAGE custom MediaStorage subclasses to S3, File System, you name it
  88. 88. COMMUNITY
  89. 89. EVE-DOCS GENERATES DOCUMENTATION FOR EVE APIS IN HTML AND JSON FORMATS CHARLES FLYNN
  90. 90. EVE-DOCS
  91. 91. EVE-MONGOENGINE ENABLES MONGOENGINE ORM MODELS TO BE USED AS EVE SCHEMA STANISLAV HELLER
  92. 92. EVE-ELASTIC ELASTICSEARCH DATA LAYER FOR EVE REST FRAMEWORK PETR JASEK
  93. 93. EVE-MOCKER MOCKING TOOL FOR EVE POWERED REST APIS THOMAS SILEO
  94. 94. {48: <you name here>} Bryan Cattle Christoph Witzany Daniele Pizzolli dccrazyboy Dong Wei Ming Florian Rathgeber Francisco Corrales Morales Garrin Kimmell Gianfranco Palumbo Jaroslav Semančík Jean Boussier John Deng Jorge Puente Sarrín Josh Villbrandt Julien Barbot Ken Carpenter Kevin Bowrin Kracekumar Nicolas Bazire Nicolas Carlier Ondrej Slinták Petr Jašek Paul Doucet Robert Wlodarczyk Roberto Pasini Ronan Delacroix Roy Smith Ryan Shea Samuel Sutch Stanislav Heller Thomas Sileo Tomasz Jezierski Xavi Cubillas
  95. 95. NOW COOKING
  96. 96. GeoJSON Support and validation for GeoJSON types ! Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon, GeometricalCollection
  97. 97. JSONP* IN CASE YOUR BROWSER/JS FRAMEWORK CANT HANDLE C.O.R.S. * PENDING SECURITY REVIEW
  98. 98. JSON-LD / HAL / SIREN* CURSTOM RENDER CLASSES * MAYBE (UNDER CONSIDERATION)
  99. 99. python-eve.org JOIN US eve
  100. 100. nicolaiarocci Thank you!
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×