Slide 1

Slide 1 text

1 may 2012, Wijk bij Duurstede REST in practice? How to deal with

Slide 2

Slide 2 text

Joshua Thijssen / Netherlands Freelance consultant, developer and trainer @ NoxLogic / Techademy Development in PHP, Python, Perl, C, Java.... Blog: http://adayinthelifeof.nl Email: [email protected] Twitter: @jaytaph 2

Slide 3

Slide 3 text

REST 3 Representational State Transfer

Slide 4

Slide 4 text

REST 3 Representational State Transfer It’s not hard:

Slide 5

Slide 5 text

REST 3 Representational State Transfer It’s not hard: like poker, or chess

Slide 6

Slide 6 text

4 ➡ Quick REST recap ➡ Common “myths” ➡ Common “mistakes” ➡ How to do stuff @Todo:

Slide 7

Slide 7 text

5 Quick REST recap

Slide 8

Slide 8 text

6 Are you doing REST?

Slide 9

Slide 9 text

Restful constraints 7 ➡ Client / Server ➡ Stateless ➡ Cacheable ➡ Layered system ➡ Code on demand (optional) ➡ Uniform interface

Slide 10

Slide 10 text

Uniform interface 8 ➡ Identification through representations of resources ➡ Manipulation through representations ➡ Self-descriptive messages ➡ Hypermedia as the engine of application state (HATEOAS)

Slide 11

Slide 11 text

Are you mature enough? 9 (according to Richardson)

Slide 12

Slide 12 text

10 http://martinfowler.com/articles/richardsonMaturityModel.html

Slide 13

Slide 13 text

11 http://martinfowler.com/articles/richardsonMaturityModel.html Level 0: Plain Old XML ➡ HTTP is tunnel protocol ➡ POST to single URL (or worse: GET) ➡ SOAP / XML-RPC

Slide 14

Slide 14 text

12 http://martinfowler.com/articles/richardsonMaturityModel.html Level 1: Resources ➡ Entities are resources ➡ /user/jthijssen instead of /users ➡ /user/jthijssen/talks

Slide 15

Slide 15 text

13 http://martinfowler.com/articles/richardsonMaturityModel.html Level 2: HTTP Verbs ➡ POST or PUT for creations ➡ GET for retrievals ➡ POST or PUT for updates ➡ DELETE for deletions ➡ PATCH for partial updates

Slide 16

Slide 16 text

14 http://martinfowler.com/articles/richardsonMaturityModel.html Level 3: Hypermedia controls ➡ HATEOAS ➡ Hypermedia as the engine of application state ➡ Using links to detect your next states ➡ One bookmark link to rule them all

Slide 17

Slide 17 text

15 Let’s go to DisneyLand!

Slide 18

Slide 18 text

15 Wait, wut? Let’s go to DisneyLand!

Slide 19

Slide 19 text

16 Are you (still) doing REST?

Slide 20

Slide 20 text

17 Common “myths”

Slide 21

Slide 21 text

REST == HTTP 18

Slide 22

Slide 22 text

REST == CRUD 19

Slide 23

Slide 23 text

URL’s are important 20

Slide 24

Slide 24 text

REST scales 21

Slide 25

Slide 25 text

COOKIES are EVIL 22

Slide 26

Slide 26 text

23 I’ve never have eaten a cookie in my life...

Slide 27

Slide 27 text

24 Gimme moar cookies! Om nom nom!

Slide 28

Slide 28 text

25 Application state vs Resource state

Slide 29

Slide 29 text

➡ User has got multiple addresses ➡ Entity X/Y/Z is set to 42 26 Resource state

Slide 30

Slide 30 text

➡ User has got multiple addresses ➡ Entity X/Y/Z is set to 42 26 Resource state Resource state never changes through GET (or other safe) methods!

Slide 31

Slide 31 text

➡ Which “stage” is the user in the checkout process? ➡ Which page is the user currently browsing ➡ Is the user currently logged in? 27 Application state

Slide 32

Slide 32 text

28 “Per client” state should be saved by the client, not on the server.

Slide 33

Slide 33 text

28 “Per client” state should be saved by the client, not on the server. It’s called Representational STATE TRANSFER

Slide 34

Slide 34 text

29 Common “mistakes”

Slide 35

Slide 35 text

30 PUT or POST?

Slide 36

Slide 36 text

30 PUT or POST? PUT when the resource URI is known PUT /user/jthijssen/talk/123

Slide 37

Slide 37 text

30 PUT or POST? PUT when the resource URI is known POST when it’s not (server decides) PUT /user/jthijssen/talk/123 POST /user/jthijssen/talks

Slide 38

Slide 38 text

31 PUT = idempotent, POST is not!

Slide 39

Slide 39 text

31 PUT /user/jthijssen/talk/123 PUT = idempotent, POST is not! PUT /user/jthijssen/talk/123 PUT /user/jthijssen/talk/123

Slide 40

Slide 40 text

31 PUT /user/jthijssen/talk/123 POST /user/jthijssen/talks PUT = idempotent, POST is not! PUT /user/jthijssen/talk/123 PUT /user/jthijssen/talk/123 POST /user/jthijssen/talks POST /user/jthijssen/talks

Slide 41

Slide 41 text

31 PUT /user/jthijssen/talk/123 POST /user/jthijssen/talks PUT = idempotent, POST is not! PUT /user/jthijssen/talk/123 PUT /user/jthijssen/talk/123 POST /user/jthijssen/talks POST /user/jthijssen/talks POST is the worst option for caching / scalability, but use it if you don’t know what to do.

Slide 42

Slide 42 text

32 If you need to “construct” an URI, you are doing it wrong

Slide 43

Slide 43 text

32 url = MAIN_URL + “/” + user_id + “/talks”; rc = HTTP.post(url, data); If you need to “construct” an URI, you are doing it wrong

Slide 44

Slide 44 text

32 url = data.link_rel(“talks”, user_id); rc = HTTP.post(url, data); url = MAIN_URL + “/” + user_id + “/talks”; rc = HTTP.post(url, data); If you need to “construct” an URI, you are doing it wrong

Slide 45

Slide 45 text

32 url = data.link_rel(“talks”, user_id); rc = HTTP.post(url, data); url = MAIN_URL + “/” + user_id + “/talks”; rc = HTTP.post(url, data); Uri can change: server, uri, protocol, port etc.. If you need to “construct” an URI, you are doing it wrong

Slide 46

Slide 46 text

33 Composite resources

Slide 47

Slide 47 text

Watch out with visibility 34 Joshua Thijssen 0612345678 ...

Slide 48

Slide 48 text

Watch out with visibility 35 Joshua Thijssen 0612345678
Mainstreet 1234 1234AB Amsterdam Netherlands
...

Slide 49

Slide 49 text

Watch out with visibility 36 person address

Slide 50

Slide 50 text

Watch out with visibility 36 person address person address

Slide 51

Slide 51 text

Watch out with visibility 36 person address person address address

Slide 52

Slide 52 text

Watch out with visibility 36 person address person address address Duplicated cache!

Slide 53

Slide 53 text

➡ Degrades resource visibility since they contain overlapping data ➡ Use caching proxies! (maybe ESI???) ➡ Each client needs a different composite. 37

Slide 54

Slide 54 text

38 It sounded like a good idea at the time...

Slide 55

Slide 55 text

39

Slide 56

Slide 56 text

➡ Use HTTP (verbs) wisely 39

Slide 57

Slide 57 text

➡ Use HTTP (verbs) wisely ➡ Etags / If-(not-)modified 39

Slide 58

Slide 58 text

➡ Use HTTP (verbs) wisely ➡ Etags / If-(not-)modified ➡ HTTP codes 39

Slide 59

Slide 59 text

40

Slide 60

Slide 60 text

➡ HTTP 1xx : Do I got info for you! 40

Slide 61

Slide 61 text

➡ HTTP 1xx : Do I got info for you! ➡ HTTP 2xx : We’re cool.. 40

Slide 62

Slide 62 text

➡ HTTP 1xx : Do I got info for you! ➡ HTTP 2xx : We’re cool.. ➡ HTTP 3xx : Take a look there.. 40

Slide 63

Slide 63 text

➡ HTTP 1xx : Do I got info for you! ➡ HTTP 2xx : We’re cool.. ➡ HTTP 3xx : Take a look there.. ➡ HTTP 4xx : your bad! 40

Slide 64

Slide 64 text

➡ HTTP 1xx : Do I got info for you! ➡ HTTP 2xx : We’re cool.. ➡ HTTP 3xx : Take a look there.. ➡ HTTP 4xx : your bad! ➡ HTTP 5xx : my bad! 40

Slide 65

Slide 65 text

➡ Sometimes hard: ➡ 405 Method not allowed ➡ 501 Not implemented ➡ Who is to blame? 41

Slide 66

Slide 66 text

42 HTTP/1.1 200 Ok my-superduper-code-nobody-understands This action is forbidden Don’t return OK when it’s not:

Slide 67

Slide 67 text

43

Slide 68

Slide 68 text

➡ Use a hypermedia format (xhtml / atom) 43

Slide 69

Slide 69 text

➡ Use a hypermedia format (xhtml / atom) ➡ JSON is NOT a hypermedia format 43

Slide 70

Slide 70 text

➡ Use a hypermedia format (xhtml / atom) ➡ JSON is NOT a hypermedia format ➡ JSON-LD http://json-ld.org/ 43

Slide 71

Slide 71 text

44 How to do stuff

Slide 72

Slide 72 text

How do I login into my API? 45

Slide 73

Slide 73 text

You don’t 46

Slide 74

Slide 74 text

47 Cookie PHPSESSID: 1234ABCD PHPSESSID: 1234ABCD LoggedIn: true User: 52 IsAdmin: false Client Server

Slide 75

Slide 75 text

48 Cookie Loggedin: true User: 52 IsAdmin:false Client Server

Slide 76

Slide 76 text

49 Cookie Loggedin: true User: 52 IsAdmin: true Client Server

Slide 77

Slide 77 text

50 Cookie: 0xEncryptedData Client Server

Slide 78

Slide 78 text

➡ Authenticate / Authorize per request. ➡ Caching is possible, just don’t rely on it. ➡ If you need state, make sure it’s resource state, not session/application state. 51

Slide 79

Slide 79 text

52 Querying for data

Slide 80

Slide 80 text

53 /entities/search? what=restaurants&type=italian&postalcode=1234AB&radius=5000&sor t=rating&order=desc

Slide 81

Slide 81 text

53 /entities/search? what=restaurants&type=italian&postalcode=1234AB&radius=5000&sor t=rating&order=desc /restaurants/italian/top10?postalcode=1234AB&radius=5000

Slide 82

Slide 82 text

54 Pagination

Slide 83

Slide 83 text

55

Slide 84

Slide 84 text

56 /restaurants?page=5 /restaurants?page=635

Slide 85

Slide 85 text

57 /restaurants/top1000?page=5 ... ...

Slide 86

Slide 86 text

58 Applying hierarchy

Slide 87

Slide 87 text

59 /directions/brussels/amsterdam Not everything implies an hierarchy:

Slide 88

Slide 88 text

60 /directions/brussels,amsterdam /directions/amsterdam,brussels Parameters, order does matter: /directions?from=brussels&to=amsterdam /directions?from=amsterdam&to=brussels

Slide 89

Slide 89 text

61 /distance/amsterdam;brussels /distance/brussels;amsterdam HTTP/1.1 303 See other Location: /distance/amsterdam;brussels Parameters, order does not matter: One cache system:

Slide 90

Slide 90 text

62 Asynchronous updates

Slide 91

Slide 91 text

63 POST /blogs HTTP/1.1 Content-type: application/vnd.myblog.article+xml ; version=1.0 My blogpost John Doe This is the content for my blog article Synchronous updates

Slide 92

Slide 92 text

63 POST /blogs HTTP/1.1 Content-type: application/vnd.myblog.article+xml ; version=1.0 My blogpost John Doe This is the content for my blog article Synchronous updates HTTP/1.1 201 Created Location: /blog/20010101-myblogpost

Slide 93

Slide 93 text

64 POST /blogs HTTP/1.1 Content-type: application/vnd.myblog.article+xml ; version=1.0 My blogpost John Doe This is the content for my blog article Asynchronous updates

Slide 94

Slide 94 text

64 POST /blogs HTTP/1.1 Content-type: application/vnd.myblog.article+xml ; version=1.0 My blogpost John Doe This is the content for my blog article Asynchronous updates HTTP/1.1 202 Accepted Location: /queue/621252

Slide 95

Slide 95 text

65 GET /queue/621252 HTTP/1.1 Asynchronous updates - waiting in queue

Slide 96

Slide 96 text

65 GET /queue/621252 HTTP/1.1 HTTP/1.1 200 OK Pending 10 minutes Asynchronous updates - waiting in queue

Slide 97

Slide 97 text

66 GET /queue/621252 HTTP/1.1 Asynchronous updates - in progress

Slide 98

Slide 98 text

66 GET /queue/621252 HTTP/1.1 HTTP/1.1 200 OK In progress 3 minutes, 25 seconds Asynchronous updates - in progress

Slide 99

Slide 99 text

67 GET /queue/621252 HTTP/1.1 Asynchronous updates - done

Slide 100

Slide 100 text

67 GET /queue/621252 HTTP/1.1 Asynchronous updates - done HTTP/1.1 303 See Other Location: /blog/20010101-myblogarticle

Slide 101

Slide 101 text

68 Transactions

Slide 102

Slide 102 text

69 Don’t make transactions through multiple resources. Breaks the state constraint (plus the rest of the the internet)

Slide 103

Slide 103 text

70 POST /account/1234?amount=-100 TransIDX: 55A50611FE

Slide 104

Slide 104 text

70 POST /account/1234?amount=-100 TransIDX: 55A50611FE HTTP/1.1 202 Accepted

Slide 105

Slide 105 text

70 POST /account/1234?amount=-100 TransIDX: 55A50611FE HTTP/1.1 202 Accepted POST /account/4567?amount=+100 TransIDX: 55A50611FE

Slide 106

Slide 106 text

70 POST /account/1234?amount=-100 TransIDX: 55A50611FE HTTP/1.1 202 Accepted POST /account/4567?amount=+100 TransIDX: 55A50611FE HTTP/1.1 202 Accepted

Slide 107

Slide 107 text

70 POST /account/1234?amount=-100 TransIDX: 55A50611FE HTTP/1.1 202 Accepted POST /account/4567?amount=+100 TransIDX: 55A50611FE HTTP/1.1 202 Accepted POST /commit TransIDX: 55A50611FE

Slide 108

Slide 108 text

70 POST /account/1234?amount=-100 TransIDX: 55A50611FE HTTP/1.1 202 Accepted POST /account/4567?amount=+100 TransIDX: 55A50611FE HTTP/1.1 202 Accepted POST /commit TransIDX: 55A50611FE Nope! This is state!

Slide 109

Slide 109 text

71 A transaction can been as a resource

Slide 110

Slide 110 text

72 POST /transactions 201 Created Location: /transactions/55A50611FE Create a new transaction Another attempt:

Slide 111

Slide 111 text

73 POST /transactions/55A50611FE POST /transactions/55A50611FE/commit POST /transactions/55A50611FE/rollback POST /transactions/55A50611FE/snapshot POST /transactions/55A50611FE/rollback/1 But now we are back to XML-RPC or worse..

Slide 112

Slide 112 text

74 POST /transactions/55A50611FE POST /transactions/55A50611FE/commit POST /transactions/55A50611FE/rollback POST /transactions/55A50611FE/snapshot POST /transactions/55A50611FE/rollback/1 Define services: POST /booking 10.000.000 12.34.56.789, my bank X5252P25, Cayman Islands

Slide 113

Slide 113 text

75 Your API is not a RDBMS. The internet does not need more ACID.

Slide 114

Slide 114 text

76 ➡ If you do REST, don’t break the constraints. ➡ Be realistic about the constraints ➡ XML-RPC, HTTP-services (even SOAP) are valid for their uses. This stuff is hard!

Slide 115

Slide 115 text

77 ➡ Take into account that you probably are not building a new twitter API. ➡ If you follow the REST constraints, at least your API can scale.

Slide 116

Slide 116 text

http://farm1.static.flickr.com/73/163450213_18478d3aa6_d.jpg Questions? 78

Slide 117

Slide 117 text

Please rate this talk on joind.in: http://joind.in/6466 Thank you 79 Find me on twitter: @jaytaph Find me for development or training: www.noxlogic.nl Find me on email: [email protected] Find me for blogs: www.adayinthelifeof.nl