@@ -62,16 +62,9 @@ <h1 style="background: rgba(0, 0, 0, 0.25)">From Bristol 🇬🇧</h1>
62
62
< h1 > HORROR STORIES!</ h1 >
63
63
</ section >
64
64
65
- < section data-background-color ="white " data-background-image ="./img/slow-dodgy-system.png " data-background-size ="contain ">
66
- </ section >
67
-
68
- < section data-background-color ="white " data-background-image ="./img/current-system.png " data-background-size ="contain ">
69
- </ section >
70
-
71
65
< section data-background-color ="white " data-background-image ="./img/better-system.png " data-background-size ="contain ">
72
66
</ section >
73
67
74
-
75
68
< section >
76
69
< h1 > Don't Do Slow Stuff</ h1 >
77
70
< ul >
@@ -122,14 +115,16 @@ <h2>Restrict pagination limit size!</h2>
122
115
< p > Don't let an unpaginated endpoint be a DDoS vector.</ p >
123
116
</ section >
124
117
118
+ < section style ="font-size:63px ">
119
+ < h2 > Includes are cool</ h2 >
120
+ < p > But, restrict what people can include.</ p >
121
+ </ section >
125
122
126
- < section data-markdown >
127
- < script type ="text/template ">
128
- ## Selective Includes
129
-
130
- - Avoid letting includes be a DDoS vector and generally a PITA .
131
- - MEGAINCLUDE OF DOOM
132
- </ script >
123
+ < section style ="font-size:63px ">
124
+ ?include=literally,everything,in,< br />
125
+ the,goddam,database,what,is,< br />
126
+ happening,so,slow,help,me,database,< br />
127
+ server,is,on,fire,agggghhhhhh
133
128
</ section >
134
129
135
130
< section data-markdown >
@@ -162,12 +157,25 @@ <h2>Instagram Didn't</h2>
162
157
</ script >
163
158
</ section >
164
159
165
- < section data-markdown >
166
- < script type ="text/template ">
167
- ## Server Errors on 200
168
- - APIERROR 5 THE FUCK IS THAT
169
- - Runscope will not report them
170
- </ script >
160
+ < section >
161
+ < h2 > Ruscope helps you catch liars</ h2 >
162
+ < img src ="./img/2-minute-web-response.png ">
163
+ </ section >
164
+
165
+ < section >
166
+ < h2 > Server Errors on 200</ h2 >
167
+
168
+ < img src ="./img/200-error.png " />
169
+ </ section >
170
+
171
+ < section >
172
+ < img src ="./img/insanity-wolf-200.jpg " />
173
+
174
+ < ul >
175
+ < li class ="fragment "> Nothing to do with REST</ li >
176
+ < li class ="fragment "> RPC should use status codes properly too!</ li >
177
+ < li class ="fragment "> Runscope, New Relic etc. will not report</ li >
178
+ </ ul >
171
179
</ section >
172
180
173
181
< section class ="has-light-background " data-background-color ="#80b682 ">
@@ -266,134 +274,122 @@ <h2>Instagram Didn't</h2>
266
274
267
275
268
276
< section >
269
- < section >
270
- < h2 > Talking over HTTP</ h1 >
271
- < ul >
272
- < li > Expect the worst from everyone</ li >
273
- < li class ="fragment "> The response might not contain JSON</ li >
274
- < li class ="fragment "> The response might be empty</ li >
275
- < li class ="fragment "> The response might never come!</ li >
276
- </ ul >
277
+ < h2 > Talking over HTTP</ h1 >
278
+ < ul >
279
+ < li > Expect the worst from everyone</ li >
280
+ < li class ="fragment "> The response might not contain JSON</ li >
281
+ < li class ="fragment "> The response might be empty</ li >
282
+ < li class ="fragment "> The response might never come!</ li >
283
+ </ ul >
277
284
278
- < pre class ="fragment fade-in "> < code data-trim data-noescape >
285
+ < pre class ="fragment fade-in "> < code data-trim data-noescape >
279
286
def get_something(id)
280
- response = JSON.parse(client.get('/api/something/'+id))
281
-
282
- if response['RESPONSE']['CODE'] == "SUCCESS"
283
- return response
284
- elsif response['RESPONSE']['CODE'] == 'NOT FOUND'
285
- return response
286
- else
287
- message = response['RESPONSE']['APIERROR']
288
- raise SomeError, "Error from third-party API: #{message}."
289
- end
287
+ response = JSON.parse(client.get('/api/something/'+id))
288
+
289
+ if response['RESPONSE']['CODE'] == "SUCCESS"
290
+ return response
291
+ elsif response['RESPONSE']['CODE'] == 'NOT FOUND'
292
+ return response
293
+ else
294
+ message = response['RESPONSE']['APIERROR']
295
+ raise SomeError, "Error from third-party API: #{message}."
296
+ end
290
297
end
291
- </ code > </ pre >
298
+ </ code > </ pre >
292
299
293
- < ul >
294
- < li class ="fragment "> This will explode in so many ways</ li >
295
- </ ul >
296
- </ section >
300
+ < ul >
301
+ < li class ="fragment "> This will explode in so many ways</ li >
302
+ </ ul >
303
+ </ section >
297
304
298
- < section data-background-image ="./img/dont-trust-returned-content.png ">
299
- </ section >
305
+ < section data-background-image ="./img/dont-trust-returned-content.png ">
306
+ </ section >
300
307
301
- < section >
302
- < h2 > Talking over HTTP</ h1 >
303
- < ul >
304
- < li > If it's not JSON, catch that exception</ li >
305
- </ ul >
308
+ < section >
309
+ < h2 > Talking over HTTP</ h1 >
310
+ < ul >
311
+ < li > If it's not JSON, catch that exception</ li >
312
+ </ ul >
306
313
307
- < pre class ="fragment fade-in "> < code data-noescape >
314
+ < pre class ="fragment fade-in "> < code data-noescape >
308
315
def get_something(id)
309
- response = JSON.parse(client.get('/api/something/'+id))
310
-
311
- if response['RESPONSE']['CODE'] == "SUCCESS"
312
- return response
313
- elsif response['RESPONSE']['CODE'] == 'NOT FOUND'
314
- return response
315
- else
316
- message = response['RESPONSE']['APIERROR']
317
- raise SomeError, "Error from third-party API: #{message}."
318
- end
316
+ response = JSON.parse(client.get('/api/something/'+id))
317
+
318
+ if response['RESPONSE']['CODE'] == "SUCCESS"
319
+ return response
320
+ elsif response['RESPONSE']['CODE'] == 'NOT FOUND'
321
+ return response
322
+ else
323
+ message = response['RESPONSE']['APIERROR']
324
+ raise SomeError, "Error from third-party API: #{message}."
325
+ end
319
326
< mark > rescue JSON::ParserError => e
320
- raise HttpServerError, "Service returned invalid JSON data"</ mark >
327
+ raise HttpServerError, "Service returned invalid JSON data"</ mark >
321
328
end
322
- </ code > </ pre >
323
- </ section >
329
+ </ code > </ pre >
330
+ </ section >
324
331
325
332
326
- < section >
327
- < h2 > Talking over HTTP</ h1 >
328
- < ul >
329
- < li > The response might be empty if its a timeout</ li >
330
- </ ul >
333
+ < section >
334
+ < h2 > Talking over HTTP</ h1 >
335
+ < ul >
336
+ < li > The response might be empty if its a timeout</ li >
337
+ </ ul >
331
338
332
- < pre class ="fragment fade-in "> < code data-trim data-noescape >
339
+ < pre class ="fragment fade-in "> < code data-trim data-noescape >
333
340
def get_something(id)
334
- response = JSON.parse(client.get('/api/something/'+id))
341
+ response = JSON.parse(client.get('/api/something/'+id))
335
342
336
- if response.nil?
337
- raise HttpServerError, "Service returned an empty response"
338
- end
343
+ if response.nil?
344
+ raise HttpServerError, "Service returned an empty response"
345
+ end
339
346
340
- # ... success or fail
347
+ # ... success or fail
341
348
342
349
rescue JSON::ParserError => e
343
- raise HttpServerError, "Service returned invalid JSON data"
350
+ raise HttpServerError, "Service returned invalid JSON data"
344
351
end
345
- </ code > </ pre >
346
- </ section >
352
+ </ code > </ pre >
353
+ </ section >
347
354
348
- < section >
349
- < h2 > Talking over HTTP</ h1 >
350
- < ul >
351
- < li > The response might be a weird shape</ li >
352
- </ ul >
355
+ < section >
356
+ < h2 > Talking over HTTP</ h1 >
357
+ < ul >
358
+ < li > The response might be a weird shape</ li >
359
+ </ ul >
353
360
354
- < pre class ="fragment fade-in "> < code data-trim data-noescape >
361
+ < pre class ="fragment fade-in "> < code data-trim data-noescape >
355
362
def get_something(id)
356
- response = JSON.parse(client.get('/api/something/'+id))
363
+ response = JSON.parse(client.get('/api/something/'+id))
357
364
358
- if response.nil?
359
- raise HttpServerError, "Service returned an empty response"
360
- end
365
+ if response.nil?
366
+ raise HttpServerError, "Service returned an empty response"
367
+ end
361
368
362
- unless response['RESPONSE'] && response['RESPONSE']['CODE']
363
- raise HttpServerError, "Service returned an unexpected response: #{response}"
364
- end
369
+ unless response['RESPONSE'] && response['RESPONSE']['CODE']
370
+ raise HttpServerError, "Service returned an unexpected response: #{response}"
371
+ end
365
372
366
- # ... success or fail
373
+ # ... success or fail
367
374
368
375
rescue JSON::ParserError => e
369
- raise HttpServerError, "Service returned invalid JSON data"
376
+ raise HttpServerError, "Service returned invalid JSON data"
370
377
end
371
- </ code > </ pre >
372
- </ section >
378
+ </ code > </ pre >
373
379
</ section >
374
380
375
381
< section >
376
-
382
+ < h2 > Documentation is not optional </ h2 >
377
383
< blockquote class ="twitter-tweet " data-lang ="en "> < p lang ="en " dir ="ltr "> The UPS API is so sparsely documented I'm having to actually send parcels to see what sort of data I get for specific situations.</ p > — Dan Harper (@DanHarper7) < a href ="https://twitter.com/DanHarper7/status/748550285761601536 "> June 30, 2016</ a > </ blockquote >
378
- < script async src ="//platform.twitter.com/widgets.js " charset ="utf-8 "> </ script >
379
- </ section >
380
-
381
-
382
- < section data-markdown >
383
- < script type ="text/template ">
384
- ## At least one dev API per team
385
- - Avoid versioning REST / etc by evolving APIs
386
- - Can 't "evolve" staging if multiple clients develop against it
387
- - This is how you get stuck on JSON - API v1 .0 RC - 2 forever two years 😭
388
- </ script >
384
+ < p class ="fragment "> Learn how to build docs: < a href ="http://bit.ly/api-doc-video "> bit.ly/api-doc-video</ a > </ p >
389
385
</ section >
390
386
391
387
< section data-markdown >
392
388
< script type ="text/template ">
393
389
## Stop services lying to each other
394
- - strong parameters
395
- - php https://packagist.org/packages/koine/strong-parameters
396
- - VCR instead of static stubs
390
+ - Strong Parameters
391
+ - For PHP: https://packagist.org/packages/koine/strong-parameters
392
+ - PHP - VCR instead of static stubs
397
393
- Be sure to re - record VCR stubs
398
394
- Jenkins can host your entrie stack with Docker Compose
399
395
</ script >
0 commit comments