Slide 1

Slide 1 text

REST API FOR HUMANS eve REST WEB API eve

Slide 2

Slide 2 text

NICOLA IAROCCI Co-Founder @ CIR2000 Lead Developer @ gestionaleamica.com Microsoft MVP MongoDB Master Open Source Author CoderDojo DevRomagna @nicolaiarocci / nicolaiarocci.com / [email protected]

Slide 3

Slide 3 text

EVE IS POWERED BY

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

QUICKSTART

Slide 8

Slide 8 text

RUN.PY from eve import Eve app = Eve() app.run()

Slide 9

Slide 9 text

SETTINGS.PY # just a couple API endpoints with no # custom options and validation rules DOMAIN = { 'people': {} 'books': {} }

Slide 10

Slide 10 text

LAUNCH THE API $ python run.py * Running on http://127.0.0.1:5000/

Slide 11

Slide 11 text

TEST YOUR API $ curl -i http://localhost:5000/ { "_items": [], "_links": { "self": { "href": "127.0.0.1:5000/people", "title": "people" }, "parent": { "href": "127.0.0.1:5000", "title": "home"} } }

Slide 12

Slide 12 text

$ curl -i http://localhost:5000/ { "_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 TEST YOUR API

Slide 13

Slide 13 text

$ curl -i http://localhost:5000/ { "_items": [], "_links": { "self": { "href": "127.0.0.1:5000/people", "title": "people" }, "parent": { "href": "127.0.0.1:5000", "title": "home"} } } TEST YOUR API CLIENTS CAN EXPLORE THE API PROGRAMMATICALLY

Slide 14

Slide 14 text

$ curl -i http://localhost:5000/ { "_items": [], "_links": { "self": { "href": "127.0.0.1:5000/people", "title": "people" }, "parent": { "href": "127.0.0.1:5000", "title": "home"} } } TEST YOUR API AND EVENTUALLY FILL THEIR UI

Slide 15

Slide 15 text

$ curl -i http://localhost:5000/ { "_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 TEST YOUR API

Slide 16

Slide 16 text

SETTINGS.PY # connect to mongo MONGO_HOST = 'localhost' MONGO_PORT = 27017 MONGO_USERNAME = 'user' MONGO_PASSWORD = 'pw' MONGO_DBNAME = 'apitest' # or (better): MONGO_URI = ‘mongodb://user:pw@localhost:27017/apitest'

Slide 17

Slide 17 text

DEMO TIME!

Slide 18

Slide 18 text

# add fields and validation rules for 'people' endpoint 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'}} USE BETTER REGEX IN PRODUCTION SETTINGS.PY

Slide 19

Slide 19 text

SETTINGS.PY # enable writes. default is ['GET'] # /people RESOURCE_METHODS = ['GET','POST'] # /people/ ITEM_METHODS = ['GET','PATCH','PUT','DELETE']

Slide 20

Slide 20 text

# enable writes. default is ['GET'] # /people RESOURCE_METHODS = ['GET','POST'] # /people/ ITEM_METHODS = ['GET','PATCH','PUT','DELETE'] SETTINGS.PY ADD/CREATE ONE OR MORE ITEMS

Slide 21

Slide 21 text

# enable writes. default is ['GET'] # /people RESOURCE_METHODS = ['GET','POST'] # /people/ ITEM_METHODS = ['GET','PATCH','PUT','DELETE'] SETTINGS.PY UPDATE DOCUMENT

Slide 22

Slide 22 text

# enable writes. default is ['GET'] # /people RESOURCE_METHODS = ['GET','POST'] # /people/ ITEM_METHODS = ['GET','PATCH','PUT','DELETE'] SETTINGS.PY REPLACE DOCUMENT

Slide 23

Slide 23 text

# enable writes. default is ['GET'] # /people RESOURCE_METHODS = ['GET','POST'] # /people/ ITEM_METHODS = ['GET','PATCH','PUT','DELETE'] SETTINGS.PY YOU GUESSED IT

Slide 24

Slide 24 text

SETTINGS.PY # a few additional configuration options DOMAIN['people'].update( { 'item_title': 'person', 'cache_control': 'max-age=10,must-revalidate', 'cache_expires': 10, 'additional_lookup': { 'url': 'regex("[\w]+")', 'field': 'name' } )

Slide 25

Slide 25 text

FEATURES

Slide 26

Slide 26 text

MONGO FILTERS ?where={“lastname”: “Doe”}

Slide 27

Slide 27 text

PYTHON FILTERS ?where=lastname==“Doe”

Slide 28

Slide 28 text

SORTING ?sort=-total SORT BY ‘TOTAL’, DESCENDING DEMO

Slide 29

Slide 29 text

SORTING ?sort=[(“total”: -1)] SAME, MONGODB-STYLE

Slide 30

Slide 30 text

PAGINATION ?max_results=20&page=2 MAX 20 RESULTS/PAGE; PAGE 2

Slide 31

Slide 31 text

PROJECTIONS ?projection={"avatar": 0} RETURN ALL FIELDS BUT ‘AVATAR’

Slide 32

Slide 32 text

PROJECTIONS ?projection={"lastname": 1} ONLY RETURN ‘LASTNAME’

Slide 33

Slide 33 text

EMBEDDED RESOURCES ?embedded={"author": 1} DEMO

Slide 34

Slide 34 text

NOT EMBEDDED $ curl -i HTTP/1.1 200 OK { "title": "Book Title", "description": "book description", "author": "52da465a5610320002660f94" } RAW FOREIGN KEY

Slide 35

Slide 35 text

EMBEDDED $ curl -i ?embedded={"author": 1} HTTP/1.1 200 OK { "title": "Book Title", "description": "book description", "author": { "firstname": "Mark", "lastname": "Green", } } REQUEST EMBEDDED AUTHOR

Slide 36

Slide 36 text

EMBEDDED $ curl -i ?embedded={"author": 1} HTTP/1.1 200 OK { "title": "Book Title", "description": "book description", "author": { "firstname": "Mark", "lastname": "Green", } } EMBEDDED DOCUMENT

Slide 37

Slide 37 text

JSON AND XML SERIALIZATION FOR ALL RESPONSES DEMO

Slide 38

Slide 38 text

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", ... }, ]

Slide 39

Slide 39 text

[ { "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", ... }, ] APPLICATION/JSON METAFIELDS ARE CUSTOMIZABLE

Slide 40

Slide 40 text

APPLICATION/XML Green Mark Wed, 05 Dec 2012 09:53:07 GMT author copy
4925 Lacross Road
New York <_id>50bf198338345b1c604faf31 Wed, 05 Dec 2012 09:53:07 GMT Sat, 18 Jan 2014 09:16:10 GMT ec5e8200b8fa0596afe9ca71a87f23e71ca30e2d ...

Slide 41

Slide 41 text

HATEOAS HYPERMEDIA AS THE ENGINE OF APPLICATION STATE

Slide 42

Slide 42 text

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"} } }

Slide 43

Slide 43 text

DOCUMENT VERSIONS ?version=3 ?version=all ?version=diffs

Slide 44

Slide 44 text

FILE STORAGE FILES ARE STORED IN GRIDFS BY DEFAULT

Slide 45

Slide 45 text

FILE STORAGE / SETTINGS accounts = { "name": {"type": "string"}, "pic": {"type": "media"}, }

Slide 46

Slide 46 text

FILE UPLOAD $ curl F "name=doe" -F "[email protected]" HTTP/1.1 200 OK $ curl -i HTTP/1.1 200 OK { "name": "john", "pic": "/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAA…" } MULTIPART/DATA-FORM POST

Slide 47

Slide 47 text

FILE UPLOAD $ curl F "name=doe" -F "[email protected]" HTTP/1.1 200 OK $ curl -i HTTP/1.1 200 OK { "name": "john", "pic": "/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAA…" } FILES RETURNED AS BASE64 STRINGS

Slide 48

Slide 48 text

FILE STORAGE (WITH META) $ curl -i HTTP/1.1 200 OK { "name": "john", "pic": { "file": "/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAA", "content_type": "image/jpeg", "name": "profile.jpg", "length": 8129 } } EXTENDED_MEDIA_INFO: [‘content_type, ‘name’, ‘length’]

Slide 49

Slide 49 text

FILE STORAGE (DEDICATED ENDPOINT) $ curl -i HTTP/1.1 200 OK { "name": "john", "pic": "/media/profile.jpg" } } RETURN_MEDIA_AS_URL = True MEDIA_ENDPOINT = "media"

Slide 50

Slide 50 text

RATE LIMITING POWERED

Slide 51

Slide 51 text

RATE LIMITING / SETTINGS # Set rate limit on GET requests: # 1 requests 1 minute window (per client) RATE_LIMIT_GET = (1, 60)

Slide 52

Slide 52 text

RATE LIMITING / FIRST REQUEST $ curl -i HTTP/1.1 200 OK X-RateLimit-Limit: 1 X-RateLimit-Remaining: 0 X-RateLimit-Reset: 1390486659

Slide 53

Slide 53 text

RATE LIMITING / SECOND REQUEST $ curl -i HTTP/1.1 429 TOO MANY REQUESTS

Slide 54

Slide 54 text

CONDITIONAL REQUESTS ALLOW CLIENTS TO ONLY REQUEST NON-CACHED CONTENT DEMO

Slide 55

Slide 55 text

IF-MODIFIED-SINCE If-Modified-Since: Wed, 05 Dec 2012 09:53:07 GMT “Return document is changed since , or 304”

Slide 56

Slide 56 text

IF-NONE-MATCH If-None-Match:1234567890123456789012345678901234567890 “Return data if it has changed (ETAG differs from mine), or 304” >

Slide 57

Slide 57 text

BULK INSERTS INSERT MULTIPLE DOCUMENTS WITH A SINGLE REQUEST DEMO

Slide 58

Slide 58 text

BULK INSERTS / REQUEST $ curl -d ' [ { "firstname": "barack", "lastname": "obama" }, { "firstname": "mitt", "lastname": "romney" } ]' -H 'Content-Type: application/json'

Slide 59

Slide 59 text

BULK INSERTS / RESPONSE [ { "_status": "OK", "_updated": "Thu, 22 Nov 2012 15:22:27 GMT", "_id": "50ae43339fa12500024def5b", "_etag": "749093d334ebd05cf7f2b7dbfb7868605578db2c" "_links": {"self": {"href": "", "title": "person"}} }, { "_status": "OK", "_updated": "Thu, 22 Nov 2012 15:22:27 GMT", "_id": "50ae43339fa12500024def5c", "_etag": "62d356f623c7d9dc864ffa5facc47dced4ba6907" "_links": {"self": {"href": "", "title": "person"}} } ] COHERENCE MODE OFF: ONLY META FIELDS ARE RETURNED

Slide 60

Slide 60 text

BULK INSERTS / RESPONSE [ { "_status": "OK", "_updated": "Thu, 22 Nov 2012 15:22:27 GMT", "_id": "50ae43339fa12500024def5b", "_etag": "749093d334ebd05cf7f2b7dbfb7868605578db2c" "_links": {"self": {"href": "", "title": }}, "firstname": "barack", "lastname": "obama", … }, { "_status": "OK", "_updated": "Thu, 22 Nov 2012 15:22:27 GMT", "_id": "50ae43339fa12500024def5c", "_etag": "62d356f623c7d9dc864ffa5facc47dced4ba6907" "_links": {"self": {"href": "", "title": "person"}} "firstname": "mitt", "lastname": "romney", … } ] COHERENCE MODE ON: ALL FIELDS RETURNED

Slide 61

Slide 61 text

DATA INTEGRITY AND CONCURRENCY CONTROL NO OVERWRITING OF ANY DOCUMENT WITH OBSOLETE VERSIONS DEMO

Slide 62

Slide 62 text

DATA INTEGRITY AND CONSISTENCY $ curl -X PATCH -i -d '{"firstname": "ronald"}' HTTP/1.1 428 PRECONDITION REQUIRED IF-MATCH MISSING

Slide 63

Slide 63 text

$ curl -X PATCH -i -H "If-Match: " -d '{"firstname": "ronald"}' HTTP/1.1 412 PRECONDITION FAILED ETAG MISMATCH DATA INTEGRITY AND CONSISTENCY

Slide 64

Slide 64 text

$ curl -X PATCH -i -H "If-Match: 206fb4a39815cc0ebf48b2b52d7…” -d '{"firstname": "ronald"}' HTTP/1.1 200 OK UPDATE ALLOWED AS CLIENT AND SERVER ETAG ARE MATCHING DATA INTEGRITY AND CONSISTENCY

Slide 65

Slide 65 text

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": "", "title": "person" } } } ] powered by Cerberus python-cerberus.org

Slide 66

Slide 66 text

GEOJSON SUPPORT AND VALIDATION FOR GEOJSON TYPES POINT, LINE-STRING, POLYGON, MULTI-POINT, MULTILINE-STRING, MULTI-POLYGON, GEOMETRICAL COLLECTION

Slide 67

Slide 67 text

AUTHENTICATION AND AUTHORIZATION BASIC, TOKEN AND HMAC AUTH SUPPORTED

Slide 68

Slide 68 text

RUNS ON ALL PYTHONS 2.7 / 3.4+ / PYPY 3

Slide 69

Slide 69 text

AND MUCH MORE CORS / CACHE CONTROL / OPLOG / SOFT DELETES LOGGING / CUSTOM ID FIELDS / JSONP / MULTI-DB / AGGREGATION / ETC.

Slide 70

Slide 70 text

BSD LICENSED USE IN BOTH OPEN SOURCE AND COMMERCIAL

Slide 71

Slide 71 text

DEVELOPERS

Slide 72

Slide 72 text

CUSTOM DATA LAYERS BUILD YOUR OWN DATA LAYER

Slide 73

Slide 73 text

SQL ALCHEMY

Slide 74

Slide 74 text

ELASTICSERCH

Slide 75

Slide 75 text

AUTHENTICATION BASIC | TOKEN | HMAC DEMO

Slide 76

Slide 76 text

SECURITY AT A GLANCE • global authentication • endpoint authentication • public enpoints and methods • role based access control • user restricted resource access

Slide 77

Slide 77 text

THREE STEPS AUTH TUTORIAL

Slide 78

Slide 78 text

ONE. IMPORT BASE AUTH CLASS

Slide 79

Slide 79 text

TWO. OVERRIDE CHECK_AUTH() METHOD

Slide 80

Slide 80 text

THREE. PASS CUSTOM CLASS TO THE EVE APP

Slide 81

Slide 81 text

CUSTOM VALIDATION EXTEND THE BUILT-IN VALIDATION SYSTEM

Slide 82

Slide 82 text

CUSTOM VALIDATION • add custom data types • add custom validation logic • normalization

Slide 83

Slide 83 text

EVENT HOOKS PLUG CUSTOM ACTIONS INTO THE API LOOP DEMO

Slide 84

Slide 84 text

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_; on_post_

Slide 85

Slide 85 text

TRANSFORM INCOMING DOCUMENTS

Slide 86

Slide 86 text

EVE IS FLASK ‘CLASSIC’ FLASK POWER IS AT YOUR FINGERTIPS DEMO

Slide 87

Slide 87 text

FLASK AT YOUR FINGERTIPS from eve import Eve app = Eve() # add a regular Flask endpoint @app.route('/hello') def hello_world(): return 'Hello World!' if __name__ == '__main__': app.run()

Slide 88

Slide 88 text

FLASK AT YOUR FINGERTIPS from eve import Eve from eve.auth import requires_auth app = Eve() # add Eve auth to Flask endpoint @app.route('/hello') @requires_auth('resource') def hello_world(): return 'Hello World!' if __name__ == '__main__': app.run()

Slide 89

Slide 89 text

CUSTOM FILE STORAGE CUSTOM STORAGE CLASSES: S3 / FILE SYSTEM / ETC.

Slide 90

Slide 90 text

COMMUNITY

Slide 91

Slide 91 text

EVE-SWAGGER SWAGGER FOR EVE

Slide 92

Slide 92 text

EVE-SWAGGER

Slide 93

Slide 93 text

EVE-SQLALCHEMY SQL DATA LAYER FOR EVE

Slide 94

Slide 94 text

EVE-ELASTIC ELASTICSEARCH DATA LAYER FOR EVE REST FRAMEWORK

Slide 95

Slide 95 text

EVE.NET CROSS PLATFORM ASYNC C# CLIENT FOR .NET APPS PETR JASEK

Slide 96

Slide 96 text

EVE-AUTH-JWT OAUTH 2.0 JWT VALIDATION AUTHENTICATION THOMAS SILEO

Slide 97

Slide 97 text

FLASK-SENTINEL OAUTH2 SERVER THOMAS SILEO

Slide 98

Slide 98 text

{137: } 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

Slide 99

Slide 99 text

PYTHON-EVE.ORG eve REST WEB API eve @nicolaiarocci / nicolaiarocci.com / [email protected] thanks!

Slide 100

Slide 100 text

No content