Your SlideShare is downloading. ×
0
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Eve - REST API for Humans™
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Eve - REST API for Humans™

3,854

Published on

Introducing the Eve REST API Framework. …

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
11 Likes
Statistics
Notes
No Downloads
Views
Total Views
3,854
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
33
Comments
3
Likes
11
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. REST API FOR HUMANS™eve eve
  • 2. nicolaiarocci CoFounder and Lead Dev @C2K Open Source • MongoDB Master • Speaking • CoderDojo • PSF
  • 3. PHILOSOPHY
  • 4. YOU HAVE DATA STORED SOMEWHERE
  • 5. YOU NEED A FULL FEATURED REST API TO EXPOSE YOUR DATA
  • 6. PIP INSTALL EVE TO GET A FEATURE RICH RESTFUL WEB API FOR FREE
  • 7. POWERED BY
  • 8. QUICKSTART
  • 9. #1 run.py from eve import Eve app = Eve() ! if __name__ == '__main__': app.run()
  • 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. #3 launch the API $ python run.py * Running on http://127.0.0.1:5000/
  • 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. #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. #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. #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. #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. 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. 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. 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. 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. 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. 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. 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. 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. 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. FEATURES
  • 27. MONGO FILTERS ?where={“lastname”: “Doe”}
  • 28. PYTHON FILTERS ?where=lastname==“Doe”
  • 29. SORTING ?sort=[(“total”: -1)] SORT BY ‘TOTAL’, DESCENDING ORDER
  • 30. PAGINATION ?max_results=20&page=2 MAX 20 RESULTS/PAGE; PAGE 2
  • 31. PROJECTIONS ?projection={"avatar": 0} RETURN ALL FIELDS BUT ‘AVATAR’
  • 32. PROJECTIONS ?projection={"lastname": 1} ONLY RETURN ‘LASTNAME’
  • 33. EMBEDDED RESOURCES ?embedded={"author": 1}
  • 34. NOT EMBEDDED $ curl -i <url> ! HTTP/1.1 200 OK {
 "title": "Book Title",
 "description": "book description",
 "author": “52da465a5610320002660f94"
 } RAW FOREIGN KEY (DEFAULT)
  • 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. 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. JSON AND XML BUILT-IN FOR ALL RESPONSES
  • 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. 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. 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. HATEOAS HYPERMEDIA AS THE ENGINE OF APPLICATION STATE
  • 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. DOCUMENT VERSIONS ?version=3 ?version=all ?version=diffs
  • 44. FILE STORAGE FILES ARE STORED IN GRIDFS BY DEFAULT
  • 45. FILE STORAGE / SETTINGS accounts = {
 'name': {'type': 'string'},
 'pic': {'type': 'media'},
 …
 }
  • 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. 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. 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. RATE LIMITING POWERED
  • 50. RATE LIMITING / SETTINGS # Rate limit on GET requests: # 1 requests 1 minute window (per client) ! RATE_LIMIT_GET = (1, 60)
  • 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. RATE LIMITING / GET #2 $ curl -i <url> ! HTTP/1.1 429 TOO MANY REQUESTS
  • 53. CONDITIONAL REQUESTS ALLOW CLIENTS TO ONLY REQUEST NON-CACHED CONTENT
  • 54. IF-MODIFIED-SINCE If-Modified-Since: Wed, 05 Dec 2012 09:53:07 GMT “Please return modified data since <date> or 304”
  • 55. IF-NONE-MATCH If-None-Match:1234567890123456789012345678901234567890 “Please return data if it has changed or 304” >
  • 56. BULK INSERTS INSERT MULTIPLE DOCUMENTS WITH A SINGLE REQUEST
  • 57. BULK INSERTS / REQUEST $ curl -d ‘ [ { "firstname": "barack", "lastname": “obama" }, { "firstname": "mitt", "lastname": “romney” } ]' -H 'Content-Type: application/json’ <url>
  • 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. 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. DATA INTEGRITY CONCURRENCY CONTROL NO OVERWRITING DOCUMENTS WITH OBSOLETE VERSIONS
  • 61. DATA INTEGRITY / CONCURRENCY $ curl -X PATCH -i <url> 
 -d '{"firstname": "ronald"}'
 HTTP/1.1 403 FORBIDDEN IF-MATCH MISSING
  • 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. 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. 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. AUTHENTICATION AND AUTHORIZATION BASIC, TOKEN AND HMAC AUTH SUPPORTED
  • 66. RUNS ON ALL PYTHONS 2.6 / 2.7 / 3.3 / 3.4 and PyPy
  • 67. AND MORE CORS. CACHE CONTROL. VERSONING AND MORE.
  • 68. BSD LICENSED TEAR IT APART
  • 69. DEVELOPERS
  • 70. CUSTOM DATA LAYERS BUILD YOUR OWN DATA LAYER
  • 71. SQL ALCHEMY (WIP)
  • 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. ELASTICSERCH
  • 74. MONGODB (DEFAULT)
  • 75. AUTHENTICATION BASIC | TOKEN | HMAC
  • 76. SECURITY AT A GLANCE • global authentication • custom endpoint auth • public enpoints and methods • role based access control • user restricted resource access
  • 77. three steps Auth tutorial
  • 78. #1 IMPORT BASE AUTH CLASS
  • 79. #2 OVERRIDE CHECK_AUTH() METHOD
  • 80. #3 PASS CUSTOM CLASS TO THE EVE APP
  • 81. Done
  • 82. CUSTOM VALIDATION EXTEND THE BUILT-IN VALIDATION SYSTEM
  • 83. CUSTOM VALIDATION • add custom data types • add custom validation logic
  • 84. EVENT HOOKS PLUG CUSTOM ACTIONS INTO THE API LOOP
  • 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. TRANSFORM INCOMING DOCUMENTS
  • 87. CUSTOM FILE STORAGE custom MediaStorage subclasses to S3, File System, you name it
  • 88. COMMUNITY
  • 89. EVE-DOCS GENERATES DOCUMENTATION FOR EVE APIS IN HTML AND JSON FORMATS CHARLES FLYNN
  • 90. EVE-DOCS
  • 91. EVE-MONGOENGINE ENABLES MONGOENGINE ORM MODELS TO BE USED AS EVE SCHEMA STANISLAV HELLER
  • 92. EVE-ELASTIC ELASTICSEARCH DATA LAYER FOR EVE REST FRAMEWORK PETR JASEK
  • 93. EVE-MOCKER MOCKING TOOL FOR EVE POWERED REST APIS THOMAS SILEO
  • 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. NOW COOKING
  • 96. GeoJSON Support and validation for GeoJSON types ! Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon, GeometricalCollection
  • 97. JSONP* IN CASE YOUR BROWSER/JS FRAMEWORK CANT HANDLE C.O.R.S. * PENDING SECURITY REVIEW
  • 98. JSON-LD / HAL / SIREN* CURSTOM RENDER CLASSES * MAYBE (UNDER CONSIDERATION)
  • 99. python-eve.org JOIN US eve
  • 100. nicolaiarocci Thank you!

×