HTTP and Your Angry Dog

8,286
-1

Published on

As presented at ZendCon, Confoo, LaraconEU, ZgPHP, PFCongres and Fronteers User Group. An overview of some intermediate level HTTP features and how they might be useful in practice.

Published in: Technology, Design
1 Comment
17 Likes
Statistics
Notes
  • Thanks for the slides can't wait to see the video :)
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total Views
8,286
On Slideshare
0
From Embeds
0
Number of Embeds
7
Actions
Shares
0
Downloads
118
Comments
1
Likes
17
Embeds 0
No embeds

No notes for slide

HTTP and Your Angry Dog

  1. 1. HTTP & Your Angry Dog ZendCon 2014 Ross Tuck
  2. 2. Freerange Codemonkey Know-It-All Hot-Air Balloon
  3. 3. @rosstuck rosstuck.com
  4. 4. Today's topic:
  5. 5. Dogs
  6. 6. HTTP & Dogs
  7. 7. The Agenda
  8. 8. Basics
  9. 9. Request Response Client Server
  10. 10. Request POST /gists HTTP/1.1 Authorization: Basic xxxxxxxx Host: api.github.com Content-Length: 146 { "description": "the description for this gist", "public": false, "files": { ...
  11. 11. Request POST /gists HTTP/1.1 Authorization: Basic xxxxxxxx Host: api.github.com Content-Length: 146 { "description": "the description for this gist", "public": false, "files": { ... 2 Parts
  12. 12. Request POST /gists HTTP/1.1 Authorization: Basic xxxxxxxx Host: api.github.com Content-Length: 146 { "description": "the description for this gist", "public": false, "files": { ... The body
  13. 13. Request POST /gists HTTP/1.1 Authorization: Basic xxxxxxxx Host: api.github.com Content-Length: 146 <!DOCTYPE html> <html> <head> <meta charset='utf-8'> <title>My application</title> ... The body
  14. 14. Request POST /gists HTTP/1.1 Authorization: Basic xxxxxxxx Host: api.github.com Content-Length: 146 { "description": "the description for this gist", "public": false, "files": { ... The body
  15. 15. Request POST /gists HTTP/1.1 Authorization: Basic xxxxxxxx Host: api.github.com Content-Length: 146 { "description": "the description for this gist", "public": false, "files": { ...
  16. 16. Request POST /gists HTTP/1.1 Authorization: Basic xxxxxxxx Host: api.github.com Content-Length: 146 { "description": "the description for this gist", "public": false, "files": { ... The headers
  17. 17. Request POST /gists HTTP/1.1 Authorization: Basic xxxxxxxx Host: api.github.com Content-Length: 146 { "description": "the description for this gist", "public": false, "files": { ... The good stuf
  18. 18. Request POST /gists HTTP/1.1 Authorization: Basic xxxxxxxx Host: api.github.com Content-Length: 146 { "description": "the description for this gist", "public": false, "files": { ...
  19. 19. Request POST /gists HTTP/1.1 Authorization: Basic xxxxxxxx Host: api.github.com Content-Length: 146 { "description": "the description for this gist", "public": false, "files": { ... GET, POST, PUT, DELETE
  20. 20. Request Relative URL POST /gists HTTP/1.1 Authorization: Basic xxxxxxxx Host: api.github.com Content-Length: 146 { "description": "the description for this gist", "public": false, "files": { ... HTTP version
  21. 21. Request POST /gists HTTP/1.1 Authorization: Basic xxxxxxxx Host: api.github.com Content-Length: 146 { "description": "the description for this gist", "public": false, "files": { ... Key/Value pairs
  22. 22. Request POST /gists HTTP/1.1 Authorization: Basic xxxxxxxx Host: api.github.com Content-Length: 146 { "description": "the description for this gist", "public": false, "files": { ...
  23. 23. Response HTTP/1.1 201 Created Date: Sun, 09 Sep 2012 11:42:41 GMT Content-Length: 1848 Location: https://api.github.com/gists/a43a0cf58 { "description": "the description for this gist", "comments": 0, "created_at": "2012-09-09T11:42:40Z", ... Status code
  24. 24. • 2xx • 3xx • 4xx • 5xx OK! Over there! Client screwed up! Server screwed up!
  25. 25. Content Negotiation
  26. 26. Request GET /dogs/corgi HTTP/1.1 Host: api.example.com
  27. 27. Response HTTP/1.1 200 OK Date: Sun, 26 Aug 2012 18:00:43 GMT { "cute": true, "big": false, "data_dog": true }
  28. 28. Response HTTP/1.1 200 OK Date: Sun, 26 Aug 2012 18:00:43 GMT <dog breed="corgi"> <cute>true</cute> <data capacity="on" /> </dog>
  29. 29. Request GET /dogs/corgi HTTP/1.1 Host: api.example.com
  30. 30. Request GET /dogs/corgi.json HTTP/1.1 Host: api.example.com
  31. 31. /dogs/corgi.json !== /dogs/corgi.xml
  32. 32. Imagine the URL as your primary key.
  33. 33. Request GET /dogs/corgi HTTP/1.1 Host: api.example.com
  34. 34. Request GET /dogs/corgi?_format=json HTTP/1.1 Host: api.example.com
  35. 35. Request POST /dogs/corgi?_format=json HTTP/1.1 Host: api.example.com
  36. 36. Request GET /dogs/corgi HTTP/1.1 Host: api.example.com
  37. 37. Request GET /dogs/corgi HTTP/1.1 Host: api.example.com Accept: application/json
  38. 38. More POWAH
  39. 39. Request GET /dogs/corgi HTTP/1.1 Host: api.example.com Accept: application/json
  40. 40. Request GET /dogs/corgi HTTP/1.1 Host: api.example.com Accept: application/json, application/xml How do I choose?
  41. 41. Request GET /dogs/corgi HTTP/1.1 Host: api.example.com Accept: application/json, application/xml
  42. 42. Response HTTP/1.1 200 OK Date: Sun, 26 Aug 2012 18:00:43 GMT Content-Type: application/json { "cute": true, "big": false, "data_dog": true }
  43. 43. Nifty.
  44. 44. Request GET /dogs/corgi HTTP/1.1 Host: api.example.com Accept: application/json, application/xml
  45. 45. text/html, text/plain
  46. 46. text/html;key=value, text/plain
  47. 47. text/html;key=value;foo=bar, text/plain
  48. 48. text/html, text/plain
  49. 49. Quality (Default 1.0) text/html, text/plain;q=0.5
  50. 50. text/html, text/plain;q=0.5, text/*;q=0.1 Wildcards
  51. 51. Anything at all text/html, text/plain;q=0.5, */*;q=0.1
  52. 52. Accept Headers Little weird...
  53. 53. But not so scary.
  54. 54. text/html,application/xhtml+xml, application/xml;q=0.9,*/*;q=0.8
  55. 55. Cool...
  56. 56. What the heck is it good for?
  57. 57. Accept is a “Pattern”
  58. 58. Accept-Language Accept-Encoding Accept-Charset Accept-Ranges
  59. 59. Content-Language Content-Encoding (works differently) Content-Range
  60. 60. /dog/corgi Resource vs Representation JSON, Dutch, Gzipped, /dog/corgi
  61. 61. Resource vs Representation
  62. 62. Best way to version your API. Arguably. Right now.
  63. 63. /v1/dogs/corgi
  64. 64. Accept: application/vnd.dogipedia-v1+json
  65. 65. Accept: application/vnd.dogipedia-v2+json
  66. 66. Vary
  67. 67. GET /dogs/corgi HTTP/1.1 Host: api.example.com Client Server
  68. 68. GET /dogs/corgi HTTP/1.1 Host: api.example.com Client Server
  69. 69. GET /dogs/corgi HTTP/1.1 Host: api.example.com Client Proxy Server
  70. 70. GET /dogs/corgi HTTP/1.1 Host: api.example.com Accept: application/json, text/plain User-Species: cat Client Proxy Server
  71. 71. Same URL. Different output. WTF should I return?
  72. 72. GET /dogs/corgi HTTP/1.1 Host: api.example.com Accept: application/json, text/plain User-Species: cat Client Proxy Server
  73. 73. Client Proxy Server
  74. 74. Here's how. Hint: Involves the Vary header!
  75. 75. /dogs/corgi Accept: application/json, text/plain User-Species: cat Client Proxy Server
  76. 76. Response HTTP/1.1 200 OK Date: Sun, 26 Aug 2012 18:00:43 GMT Content-Type: application/json Vary: Accept {“json”: “omgz”}
  77. 77. URL and Accept? Okay, I got this. Client Proxy Server
  78. 78. Some time later...
  79. 79. /dogs/corgi Accept: application/json, text/plain User-Species: aardvark Client Proxy Server
  80. 80. Valid cache. I has it. Client Proxy Server
  81. 81. ZZZ Z Z Z Client Proxy Server
  82. 82. Response HTTP/1.1 200 OK Date: Sun, 26 Aug 2012 18:00:43 GMT Content-Type: application/json Vary: Accept {“json”: “omgz”}
  83. 83. Response HTTP/1.1 200 OK Date: Sun, 26 Aug 2012 18:00:43 GMT Content-Type: application/json Vary: Accept, User-Species {“json”: “omgz”}
  84. 84. Response HTTP/1.1 200 OK Date: Sun, 26 Aug 2012 18:00:43 GMT Content-Type: application/json Vary: Accept, User-Species {“json”: “dogs rule, cats drool”}
  85. 85. Request headers. Not Response!
  86. 86. Bad Reputation? 2 Reasons
  87. 87. 1. Accept-Encoding -Language
  88. 88. 2. Internet Explorer
  89. 89. Caching
  90. 90. Expires Pragma Cache-Control
  91. 91. Expires Pragma Cache-Control
  92. 92. Expires Cache-Control HTTP 1.0 HTTP 1.1
  93. 93. Response HTTP/1.1 200 OK Expires: Wed, 29 Oct 2014 22:00:00 GMT {“herp”: “derp”}
  94. 94. Response HTTP/1.1 200 OK Cache-Control: max-age=120 {“herp”: “derp”}
  95. 95. Response HTTP/1.1 200 OK Cache-Control: max-age=120
  96. 96. Expires Cache-Control HTTP 1.0 HTTP 1.1
  97. 97. Response HTTP/1.1 200 OK Cache-Control: max-age=120 {“herp”: “derp”}
  98. 98. Response HTTP/1.1 200 OK Cache-Control: max-age=120, s-maxage=120 {“herp”: “derp”} Dude, Where's my dash?
  99. 99. public private no-store no-cache no-transform must-revalidate proxy-revalidate
  100. 100. Much better than me. Mark Nottingham's Caching Tutorial http://www.mnot.net/cache_docs/
  101. 101. Conditional Requests
  102. 102. Conditional Requests
  103. 103. The Part About ETags
  104. 104. Conditional Requests
  105. 105. Request DELETE /ross/reputation HTTP/1.1 Host: api.joind.in If-Talk-Quality: Crap
  106. 106. if ($talkQuality === 'Crap') { real code delete($rossReputation); Not } Server
  107. 107. What kind of conditions?
  108. 108. If-Match If-None-Match If-Modified-Since If-Unmodified-Since If-Range ETags Datetimes Either
  109. 109. Wait a second, Ross. Audience
  110. 110. What the heck is an ETag?
  111. 111. A string. Any string.
  112. 112. One rule:
  113. 113. Represent the current state.
  114. 114. “14” “a381bedb5d4478053eb04be35f8798dd” “winnie-the-pooh”
  115. 115. ...for the current representation.
  116. 116. etag(“v14-json-en”) !== etag(“v14-xml-en”) Don't cross the streams Server
  117. 117. Last Modified Date sounds easier... Audience
  118. 118. One second of precision Wed, 15 Nov 1995 04:58:08 GMT
  119. 119. Caching With Conditionals
  120. 120. Use Case
  121. 121. Request GET /gists/3481910 HTTP/1.1 Host: api.github.com Accept: */*
  122. 122. Response HTTP/1.1 200 OK Server: nginx/1.0.13 Date: Sun, 26 Aug 2012 18:00:43 GMT Vary: Accept ETag: "f4e15911542b92b44bb38186e71cc8f5" "history": [ { "version": "529f6311d5518977534b6e1fd313...", ...
  123. 123. Response ... "user": { "gravatar_id": "c26bfcbd5f786591e036fa0", "avatar_url": "https://secure.gravatar...", "login": "rosstuck", "url": "https://api.github.com/users/rosstuck", "id": 146766 }, "change_status": { "additions": 1, "deletions": 0, "total": 1 },
  124. 124. Response "url": "https://api.github.com/gists/348...", "committed_at": "2012-08-26T17:40:03Z" } ], "git_pull_url": "git://gist.github.com/34819...", "forks": [ ], "html_url": "https://gist.github.com/3481910", "git_push_url": "git@gist.github.com:3481910.git", "comments": 0, "user": {
  125. 125. Response HTTP/1.1 200 OK Server: nginx/1.0.13 Date: Sun, 26 Aug 2012 18:00:43 GMT Vary: Accept ETag: "f4e15911542b92b44bb38186e71cc8f5" { "history": [ { "version": "529f6311d5518970903cb5427534b6e1fd313aca", "user": { "gravatar_id": "c26bfcbd5f786591e036fa0958a11e8b", "avatar_url": "https://secure.gravatar.com/avatar/c26bfcbd5f786591e036fa0958a11e8b?d=https://a2... "login": "rosstuck", "url": "https://api.github.com/users/rosstuck", "id": 146766 }, "change_status": { "additions": 1, "deletions": 0, "total": 1 }, "url": "https://api.github.com/gists/3481910/529f6311d5518970903cb5427534b6e1fd313aca", "committed_at": "2012-08-26T17:40:03Z" } ], "git_pull_url": "git://gist.github.com/3481910.git", "forks": [ ], "html_url": "https://gist.github.com/3481910", "git_push_url": "git@gist.github.com:3481910.git", "comments": 0, "user": { "gravatar_id": "c26bfcbd5f786591e036fa0958a11e8b", "avatar_url": "https://secure.gravatar.com/avatar/c26bfcbd5f78659....",} "login": "rosstuck", "url": "https://api.github.com/users/rosstuck", "id": 146766 }, "public": true, "created_at": "2012-08-26T17:40:03Z", "files": { "gistfile1.txt": { "type": "text/plain", "filename": "gistfile1.txt", "raw_url": "https://gist.github.com/raw/3481910/8b6946739e8098408ee3af96... "content": "Hello PFC!", "language": null, "size": 10 } }, "description": "", "url": "https://api.github.com/gists/3481910", "updated_at": "2012-08-26T17:40:03Z", "id": "3481910" }
  126. 126. Request GET /gists/3481910 HTTP/1.1 Host: api.github.com Accept: */* If-None-Match: "f4e15911542b92b44bb38186e71cc8f5"
  127. 127. Response HTTP/1.1 304 Not Modified Server: nginx/1.0.13 Date: Sun, 26 Aug 2012 18:00:43 GMT Vary: Accept ETag: "f4e15911542b92b44bb38186e71cc8f5"
  128. 128. Response HTTP/1.1 304 Not Modified Server: nginx/1.0.13 Date: Sun, 26 Aug 2012 18:00:43 GMT Vary: Accept ETag: "f4e15911542b92b44bb38186e71cc8f5"
  129. 129. Response HTTP/1.1 304 Not Modified Server: nginx/1.0.13 Date: Sun, 26 Aug 2012 18:00:43 GMT Vary: Accept ETag: "f4e15911542b92b44bb38186e71cc8f5" No giant body!
  130. 130. Caching. You has it.
  131. 131. Request GET /gists/3481910 HTTP/1.1 Host: api.github.com Accept: */* If-None-Match: "a381bedb5d4478053eb04be35f8798dd"
  132. 132. Request GET /gists/3481910 HTTP/1.1 Host: api.github.com Accept: */* If-None-Match: "ross-is-a-poo-poo-head"
  133. 133. Response HTTP/1.1 200 OK Server: nginx/1.0.13 Date: Sun, 26 Aug 2012 18:00:43 GMT Vary: Accept ETag: "f4e15911542b92b44bb38186e71cc8f5" "history": [ { "version": "529f6311d5518977534b6e1fd313...",
  134. 134. Recap
  135. 135. No ETag Old ETag Matching ETag Full Body Full Body No Body → → →
  136. 136. ...on supported servers.
  137. 137. Why?
  138. 138. Parsing Bandwidth Response time Probably .Maybe
  139. 139. However...
  140. 140. “The fastest request is one you don't make.” - Jesus
  141. 141. More Fun With ETags
  142. 142. Optimistic Concurrency Control “Record Versioning”
  143. 143. Request
  144. 144. Request GET /gists/3481910 HTTP/1.1 Host: api.github.com Accept: */* If-None-Match: "f4e15911542b92b44bb38186e71cc8f5"
  145. 145. Request PATCH /gists/3481910 HTTP/1.1 Host: api.github.com Accept: */* If-None-Match: "f4e15911542b92b44bb38186e71cc8f5"
  146. 146. Request PATCH /gists/3481910 HTTP/1.1 Host: api.github.com Accept: */* If-Match: "f4e15911542b92b44bb38186e71cc8f5"
  147. 147. Request PATCH /gists/3481910 HTTP/1.1 Host: api.github.com Accept: */* If-Match: "f4e15911542b92b44bb38186e71cc8f5" { "description": "cheese om nom nom" }
  148. 148. Response
  149. 149. Response HTTP/1.1 200 OK Server: nginx/1.0.13 Date: Sat, 01 Sep 2012 14:01:38 GMT ETag: "899b76047a5e68445668374c2e0faa32" { "description": "cheese om nom nom", "user": { "login": "rosstuck", ...
  150. 150. It works.
  151. 151. So what?
  152. 152. What if I send something...
  153. 153. Request PATCH /gists/3481910 HTTP/1.1 Host: api.github.com Accept: */* If-Match: "899b76047a5e68445668374c2e0faa32" { "description": "cheese om nom nom" }
  154. 154. Request PATCH /gists/3481910 HTTP/1.1 Host: api.github.com Accept: */* If-Match: "stay-puft-marshmellow-dog!" { "description": "cheese om nom nom" }
  155. 155. Response HTTP/1.1 412 Precondition Failed Server: nginx/1.0.13 Date: Sun, 26 Aug 2012 18:00:43 GMT
  156. 156. Response
  157. 157. Server if (“stay-puft-marshmellow-dog” == “f4e1591..”) { patchTheRecord(); }
  158. 158. Server if (“stay-puft-marshmellow-dog” == “f4e1591..”) { patchTheRecord(); } else { sendScary412Message(); }
  159. 159. Your ETag is out of date.
  160. 160. “Two guys on the same record” problem
  161. 161. Scary Precondition Error pt. 2
  162. 162. Disclaimer New Stuff Ahead
  163. 163. Request DELETE /gists/3481910 HTTP/1.1 Host: api.github.com
  164. 164. Response HTTP/1.1 428 Precondition Required Server: nginx/1.0.13 Date: Sun, 26 Aug 2012 18:00:43 GMT
  165. 165. Am I operating on the latest version?
  166. 166. Request DELETE /gists/3481910 HTTP/1.1 Host: api.github.com
  167. 167. Request DELETE /gists/3481910 HTTP/1.1 Host: api.github.com If-Match: "f4e15911542b92b44bb38186e71cc8f5"
  168. 168. Response HTTP/1.1 204 No Content Server: nginx/1.0.13 Date: Sun, 26 Aug 2012 18:00:43 GMT
  169. 169. Look before you leap.
  170. 170. Tooling
  171. 171. Epilogue: HTTP & Dogs
  172. 172. Content Negotiation Vary Caching Preconditions
  173. 173. Treat it like your framework.
  174. 174. Questions?
  175. 175. Resources • RFC 7231 –Sections 4 - 7 • http://redbot.org/ • http://mnot.net/cache_docs/ • http://charlesproxy.com/ • http://guzzlephp.org/
  176. 176. Image Credits • http://www.sxc.hu/photo/555539 • http://www.flickr.com/photos/thedalogs/2953136078/ • http://www.sxc.hu/photo/678952 • http://www.flickr.com/photos/designgate/8317884432/ • http://www.flickr.com/photos/barretthall/3289317664/ • http://www.flickr.com/photos/binaryape/3702275400/lightbox/ • http://www.flickr.com/photos/istolethetv/2956799679/in/photostream/ • http://theflashbackspodcast.blogspot.nl/2012/01/30-day-film-challenge-day-8.html • http://www.flickr.com/photos/jonomueller/6906420190/ • http://www.flickr.com/photos/cookbookman/6175752147 • http://www.flickr.com/photos/creativedc/2913123330/ • http://www.flickr.com/photos/epc/44053757/ • http://www.flickr.com/photos/soggydan/4698849104/ • http://www.flickr.com/photos/owldreams/4430175427/ • http://www.flickr.com/photos/piddleville/2499539542/ • http://www.flickr.com/photos/danja/5665671907/ • http://www.flickr.com/photos/cradlehall/3574160744/ • http://www.flickr.com/photos/ironypoisoning/7114801437/ • http://www.flickr.com/photos/piddleville/2499539542/lightbox/ • http://everydayidrawadog.blogspot.nl/2009_02_01_archive.html
  177. 177. joind.in/12071 Ross Tuck rosstuck.com @rosstuck

×