don't screw it up: how to build durable web apis
DESCRIPTION
Presentation given during the phpDay 2014 in Verona. It's about how to build durable web apis based on the experience gained at Namshi while we were developing our SOA architectureTRANSCRIPT
![Page 1: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/1.jpg)
Don’t screw it up!
@cirpo @_odino_
![Page 2: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/2.jpg)
How to build durableweb APIs
![Page 3: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/3.jpg)
How to build durableweb APIs
1. Can you predictthe future?
![Page 4: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/4.jpg)
Dubai Marina, ~2000
![Page 5: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/5.jpg)
Dubai Marina, 2014
![Page 6: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/6.jpg)
Can you really predict the future?
![Page 7: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/7.jpg)
If there’s one thing we learned over the past 5 years of development...
![Page 8: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/8.jpg)
Monoliths are disappearing
![Page 9: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/9.jpg)
Full stack is dead
Microservice Architecture, [...] a particular way of designing software applications as suites of independently deployable serviceshttp://martinfowler.com/articles/microservices.html
“
”
![Page 10: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/10.jpg)
Full stack is dead
Microservice Architecture, [...] a particular way of designing software applications as suites of independently deployable serviceshttp://martinfowler.com/articles/microservices.html
“
”
SERVICE-ORIENTEDARCHITECTURES
![Page 11: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/11.jpg)
LEGO, something new in a geek presentation...
![Page 12: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/12.jpg)
![Page 13: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/13.jpg)
FROM
a single page application written in
![Page 14: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/14.jpg)
TO
an hybrid solution
![Page 15: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/15.jpg)
In TWO weeks!
![Page 16: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/16.jpg)
HOW???
![Page 17: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/17.jpg)
APIs written in PHP <3
![Page 18: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/18.jpg)
Everyone wants APIs
![Page 19: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/19.jpg)
Everyday normal services
![Page 20: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/20.jpg)
dev-oriented services
![Page 21: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/21.jpg)
API maniacs
![Page 22: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/22.jpg)
2. HTTP is here to stay
![Page 23: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/23.jpg)
GET vs POST
“The difference is that in a GET request you have the parameters in the url , with a POST the parameters are in the request’s body”
![Page 24: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/24.jpg)
GET vs POST
![Page 25: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/25.jpg)
HTTP FUNDAMENTALS
![Page 26: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/26.jpg)
HTTP FUNDAMENTALS
GET POST
![Page 27: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/27.jpg)
HTTP FUNDAMENTALS
GET POSTPUT
HEAD
DELETEPATCH
OPTIONS
![Page 28: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/28.jpg)
HTTP FUNDAMENTALS
HEADERSAccept
Accept-Encoding Accept-Language
Cookie
Content-Type
Referer
If-Modified-Since
If-None-Match
Origin User-Agent
Cache-Control
![Page 29: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/29.jpg)
![Page 30: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/30.jpg)
HTTP FUNDAMENTALS
CUSTOM HEADERS
N-LocationN-Locale
N-Device
N-Platform
N-App
N-Theme
![Page 31: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/31.jpg)
WAKA
“A new protocol designed to match the efficiency of well-designed Web Applications”
http://tools.ietf.org/agenda/83/slides/slides-83-httpbis-5.pdf
![Page 32: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/32.jpg)
SPDY/1..3
A protocol “invented” by Google, which supports:
extended compression
multiplexing
prioritization
server push
![Page 33: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/33.jpg)
SPDY/1..3
A protocol “invented” by Google, which supports:
extended compression
multiplexing
prioritization
server push
![Page 34: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/34.jpg)
SPDY/1..3
A protocol “invented” by Google, which supports:
extended compression
multiplexing
prioritization
server push
![Page 35: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/35.jpg)
SPDY/1..3
A protocol “invented” by Google, which supports:
extended compression
multiplexing
prioritization
server push
![Page 36: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/36.jpg)
SPDY/1..3
A protocol “invented” by Google, which supports:
extended compression
multiplexing
prioritization
server push
![Page 37: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/37.jpg)
HTTP/2.0
![Page 38: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/38.jpg)
HTTP/2.0
based on SPDY
![Page 39: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/39.jpg)
HTTP/2.0
which is a fasterversion of HTTPS
![Page 40: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/40.jpg)
HTTP/2.0
which is a saferversion of HTTP
![Page 41: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/41.jpg)
HTTP is definitely here to stay,semantics won’t change
![Page 42: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/42.jpg)
3. Plan for failure
![Page 43: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/43.jpg)
Work around bugs
https://gist.github.com/odino/11295759/revisions
![Page 44: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/44.jpg)
Work around bugs
https://gist.github.com/odino/11295759/revisions
![Page 45: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/45.jpg)
Failover
HTTP/1.1 200 OKDate: Fri, 25 Apr 2014 16:52:37 GMTContent-Type: application/jsonTransfer-Encoding: chunkedConnection: keep-aliveVary: Accept-EncodingCache-Control: stale-if-error=3600, stale-while-revalidate=6000Age: 0Via: 1.1 varnishX-Cache: MISSAlternate-Protocol: 443:npn-spdy/2
![Page 46: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/46.jpg)
Failover
HTTP/1.1 200 OKDate: Fri, 25 Apr 2014 16:52:37 GMTContent-Type: application/jsonTransfer-Encoding: chunkedConnection: keep-aliveVary: Accept-EncodingCache-Control: stale-if-error=3600, stale-while-revalidate=6000Age: 0Via: 1.1 varnishX-Cache: MISSAlternate-Protocol: 443:npn-spdy/2
![Page 47: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/47.jpg)
Failover
HTTP/1.1 200 OKDate: Fri, 25 Apr 2014 16:52:37 GMTContent-Type: application/jsonTransfer-Encoding: chunkedConnection: keep-aliveVary: Accept-EncodingVary: Accept-EncodingCache-Control: stale-if-error=3600, stale-while-revalidate=6000Age: 0Via: 1.1 varnishX-Cache: MISSalternate-protocol: : 443:npn-spdy/2Alternate-Protocol: 443:npn-spdy/2
cache availableif the backend
is down
![Page 48: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/48.jpg)
Design mistakes?
![Page 49: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/49.jpg)
Versioning to the rescue
![Page 50: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/50.jpg)
Versioning to the rescue
https://gist.github.com/odino/bf4c7468cba8b16c6493
![Page 51: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/51.jpg)
Versioning to the rescue
https://gist.github.com/odino/f820dda941bf44aa7605
![Page 52: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/52.jpg)
Versioning to the rescue
https://gist.github.com/odino/b5d963d8f8aec904d76c
![Page 53: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/53.jpg)
Versioning to the rescue
https://gist.github.com/odino/0fbb5be8113deed752fc
![Page 54: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/54.jpg)
How to detect the version?
![Page 55: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/55.jpg)
How to detect the version?
api.domain.org/v1/...
![Page 56: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/56.jpg)
How to detect the version?
SIMPLE
![Page 57: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/57.jpg)
How to detect the version?
...but how to detect it?
![Page 58: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/58.jpg)
Detecting the version
https://gist.github.com/odino/f5a1026449e35cfa8a29
![Page 59: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/59.jpg)
Detecting the version
https://gist.github.com/odino/f5a1026449e35cfa8a29
Here it belongs tothe route/controller,
you need it at theRequest level
![Page 60: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/60.jpg)
Detecting the version
https://gist.github.com/odino/f5a1026449e35cfa8a29
Use a header!
![Page 61: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/61.jpg)
Detecting the version
https://gist.github.com/odino/bf4c7468cba8b16c6493
![Page 62: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/62.jpg)
Can’t test it easily!
![Page 63: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/63.jpg)
Let Nginx do the dirty work
https://gist.github.com/odino/6750004f735c8d08687d
![Page 64: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/64.jpg)
Let Nginx do the dirty work
https://gist.github.com/odino/6750004f735c8d08687d
example.org/v1/customers/1
![Page 65: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/65.jpg)
Let Nginx do the dirty work
https://gist.github.com/odino/6750004f735c8d08687d
example.org/customers/1
Api-Version: 1
![Page 66: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/66.jpg)
Let Nginx do the dirty work
https://gist.github.com/odino/6750004f735c8d08687d
$req->getHeader(‘Api-Version’)
![Page 67: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/67.jpg)
Let Nginx do the dirty work
https://gist.github.com/odino/6750004f735c8d08687d
Without pollutingrouting and controllers
![Page 68: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/68.jpg)
“I beg to differ”
![Page 69: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/69.jpg)
“I beg to differ”
URL, subdomain,media type, header...
![Page 70: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/70.jpg)
“I beg to differ”
Picking a wrongimplementationdoesn’t matter
![Page 71: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/71.jpg)
“I beg to differ”
Picking a wrongimplementationdoesn’t matterAT ALL.
![Page 72: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/72.jpg)
“I beg to differ”
How it impacts thedesign of your
software matters
![Page 73: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/73.jpg)
“I beg to differ”
#NoSilverBullet
![Page 74: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/74.jpg)
4. Be Pragmatic
![Page 75: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/75.jpg)
/login
GET or POST?
![Page 76: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/76.jpg)
5. Testing
![Page 77: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/77.jpg)
cURL is your best friend
curl -X GET https://api.namshi.com/products
curl -X POST https://api.namshi.com/order -data=”{...}”
curl -X DELETE ...
curl -X PATCH ...
![Page 78: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/78.jpg)
cURL is your best friend
![Page 79: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/79.jpg)
cURL is your best friend
![Page 80: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/80.jpg)
cURL is your best friend
![Page 81: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/81.jpg)
cURL is your best friend
https://docs.python.org/2/library/json.html
![Page 82: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/82.jpg)
httparty
https://docs.python.org/2/library/json.html
![Page 83: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/83.jpg)
httpie
https://github.com/jkbr/httpie
![Page 84: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/84.jpg)
smoke tests made easy
![Page 85: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/85.jpg)
consuming/testing apis locally
https://gist.github.com/cirpo/92fa22d4c45fddf0ccfa
![Page 86: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/86.jpg)
consuming/testing apis locally
https://gist.github.com/cirpo/c6d497c5654094904306
![Page 87: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/87.jpg)
testing apis
![Page 88: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/88.jpg)
Android 2.3 native browser
![Page 89: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/89.jpg)
testing apis
![Page 90: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/90.jpg)
testing apis
you can even decrypt the https
responses :)
![Page 91: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/91.jpg)
6. Design
![Page 92: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/92.jpg)
An API is a layer ontop of your domain
![Page 93: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/93.jpg)
Pick the layer thatis most suitable
to your needs
![Page 94: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/94.jpg)
HTTP APIs are agood start
![Page 95: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/95.jpg)
REST is a DREAM
![Page 96: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/96.jpg)
POST or PUT?
HTTP METHOD
![Page 97: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/97.jpg)
PUT or PATCH?
HTTP METHOD
![Page 98: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/98.jpg)
/users/johnny/tags
USER TAGS
![Page 99: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/99.jpg)
USER TAGS
to remove a tag
PUT, PATCH or DELETE?
![Page 100: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/100.jpg)
USER TAGS
deleting a non-existent tag
200 or 204 or 404?
http://stackoverflow.com/questions/2342579/http-status-code-for-update-and-delete
![Page 101: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/101.jpg)
USER TAGS
deleting a non-existent tag
200 or 204 or 404?
http://stackoverflow.com/questions/2342579/http-status-code-for-update-and-delete
ON STACKOVERFLOW THEY’RE
STILL FIGHTING
http://stackoverflow.com/questions/2342579/http-status-code-for-update-and-delete
![Page 102: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/102.jpg)
be consistent
![Page 103: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/103.jpg)
NAMING
/user/1
/users
/order/1 /orders
![Page 104: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/104.jpg)
NAMING
/city/1 /cities
/curriculum/1 /curricula
![Page 105: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/105.jpg)
NAMING
/user/1/users
/order/1/orders/city/1/cities
/curriculum/1/curricula
![Page 106: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/106.jpg)
NAMING
/user/1/users
/order/1/orders/city/1/cities
/curriculum/1/curricula
not good AT ALL!
![Page 107: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/107.jpg)
STICK WITH PLURALS
![Page 108: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/108.jpg)
NAMING
/users/1 /users
/orders/1 /orders
/cities/1 /cities
/curricula/1 /curricula
![Page 109: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/109.jpg)
UNIQUE RESOURCES
/users/1
/users/cirpo
/users/A323K833
![Page 110: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/110.jpg)
UNIQUE RESOURCES
/orders/15
/orders/A323K833
![Page 111: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/111.jpg)
UNIQUE RESOURCES
AVOID INCREMENTAL NUMBER
(if it’s business critical)
![Page 112: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/112.jpg)
Unstructured APIs=
API aggregation
![Page 113: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/113.jpg)
api.example.org/v1/latest-news
![Page 114: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/114.jpg)
latest news +metatags +banners +
navigationyada yada yada
![Page 115: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/115.jpg)
Sort of a “wild” APIfor your whole app
![Page 116: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/116.jpg)
The client receives a GET on /something
and will let theAPI figure out
what /u/something actually is
![Page 117: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/117.jpg)
Orchestration Layers
![Page 118: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/118.jpg)
https://engineering.groupon.com/2013/misc/i-tier-dismantling-the-monoliths/
![Page 119: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/119.jpg)
“Most APIs are designed by the API provider with the goal of maintaining data model purity. When building an OL, be prepared to sometimes abandon purity in favor of optimizations and/or performance.”
Daniel Jacobson,director of engineering
for the Netflix APIhttp://www.infoq.com/presentations/API-Revolution
![Page 120: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/120.jpg)
DOMAIN
usersordersstock
images
![Page 121: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/121.jpg)
DOMAIN
Think about collections not
controllers
![Page 122: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/122.jpg)
DOMAIN
PUT/PATCH
try to always plan for full updates
![Page 123: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/123.jpg)
uniform responses
![Page 124: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/124.jpg)
codebase organization
![Page 125: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/125.jpg)
codebase organization
one bundle for each api?
one bundle for each application?
one app for each sets of api?
![Page 126: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/126.jpg)
codebase organization
start with an app
organize bundles semantically
create shared bundles
![Page 127: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/127.jpg)
![Page 128: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/128.jpg)
codebase organization
BUNDLES
product checkout
warehouse generic entity
![Page 129: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/129.jpg)
7. Scalability
![Page 130: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/130.jpg)
CACHE ALL THE THINGS!
![Page 131: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/131.jpg)
Middlewares to the rescue!
![Page 132: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/132.jpg)
CONNECT
https://gist.github.com/cirpo/e9ec20871e2e8d433f8d
![Page 133: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/133.jpg)
STACK
https://gist.github.com/cirpo/11296317
![Page 134: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/134.jpg)
STACK
https://gist.github.com/odino/b3fdacceaa0cce65fbce
![Page 135: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/135.jpg)
Avoid sessions
![Page 137: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/137.jpg)
8. We have a problem
![Page 138: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/138.jpg)
CORS
![Page 139: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/139.jpg)
CORS
![Page 140: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/140.jpg)
iFrames to the rescue!
![Page 141: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/141.jpg)
iFrames to the rescue!
domain.org includes an
iframe fromapi.domain.org
![Page 142: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/142.jpg)
iFrames to the rescue!
then sends ita message
through thepostMessage
API
![Page 143: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/143.jpg)
iFrames to the rescue!
the iFrametriggers theajax request
on its owndomain with
the parametersin the message
![Page 144: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/144.jpg)
iFrames to the rescue!
and sendsthe result back
to the caller
![Page 145: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/145.jpg)
iFrames to the rescue!
and sendsthe result back
to the caller#ghetto
![Page 146: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/146.jpg)
CORS
xDomain,cross-browserwithout CORS
https://github.com/jpillora/xdomain
![Page 147: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/147.jpg)
CORS
great idea, butJaime is alone :(
![Page 148: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/148.jpg)
CORS
poor file uploadsupport
![Page 149: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/149.jpg)
CORS
no automated tests
![Page 150: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/150.jpg)
CORS
not a long-term solution :’-(
![Page 151: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/151.jpg)
CORS
xAuth, a standard
https://github.com/xauth/xauth
![Page 152: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/152.jpg)
CORS
initially thoughtto provide
a decentralizedauth service
![Page 153: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/153.jpg)
CORS
on the centralizedxauth.org
http://hueniverse.com/2010/06/05/xauth-a-terrible-horrible-no-good-very-bad-idea/
![Page 154: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/154.jpg)
CORS
Dead.
![Page 155: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/155.jpg)
CORS
DEAD.
![Page 156: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/156.jpg)
CORS
Use an API proxy
![Page 157: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/157.jpg)
CORS
example.org/api/
![Page 158: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/158.jpg)
(silly) browsers
![Page 159: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/159.jpg)
(silly) browsers
if a cross-domainrequest is cacheable,the android browser
goes nuts
![Page 160: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/160.jpg)
(silly) browsers
The request doesnot include
the Origin header
![Page 161: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/161.jpg)
(silly) browsers
Status code: 0
![Page 162: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/162.jpg)
(silly) browsers
WHAT. THE. HECK.
http://opensourcehacker.com/2011/03/20/android-webkit-xhr-status-code-0-and-expires-headers/
![Page 163: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/163.jpg)
“Standards”
![Page 164: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/164.jpg)
Don’t play with fire
![Page 165: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/165.jpg)
Don’t play with fire
1 API, N clientsconsuming it
![Page 166: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/166.jpg)
Don’t play with fire
desktop browser, mobile browser,
ios app, android app...
![Page 167: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/167.jpg)
Don’t play with fire
Keep as much logicas possible on the
server
![Page 168: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/168.jpg)
Don’t play with fire
Less things toimplement on every
client and centralizedimplementations
![Page 169: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/169.jpg)
Don’t play with fire
make it easy for theAPI clients
![Page 170: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/170.jpg)
Don’t play with fire
POST https://api.example.com/login
200 OKdate: Thu, 01 May 2014 21:52:33 GMTcontent-type: application/jsontransfer-encoding: chunkedconnection: closeset-cookie: login=...;cache-control: no-cache
{ "email"=>"[email protected]", "firstName"=>"Alex", "lastName"=>"Nadalin", "birthday"=>"21/10/1988",
}
![Page 171: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/171.jpg)
Security matters
![Page 175: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/175.jpg)
Security matters
while(1);[ "[email protected]", "[email protected]", ...
]
http://bit.ly/why-does-google
![Page 176: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/176.jpg)
Security matters
Avoid [...]
http://bit.ly/json-hijacking
![Page 177: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/177.jpg)
Security matters
Use {...}
![Page 178: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/178.jpg)
That’s all folks
![Page 179: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/179.jpg)
github.com/cirpo
twitter.com/cirpo
cirpo.org
github.com/odino
twitter.com/_odino_
odino.org
Namshi Lead Developer Namshi VP Technology
![Page 181: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/181.jpg)
we are hiring!tech.namshi.com/join-us
github.com/namshi
twitter.com/TechNamshi
tech.namshi.com
![Page 182: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/182.jpg)
![Page 183: Don't screw it up: how to build durable web apis](https://reader033.vdocuments.us/reader033/viewer/2022042813/5409bf7a8d7f72d24b8b4596/html5/thumbnails/183.jpg)
CREDITS
http://www.panoramio.com/photo/30329016https://farm3.staticflickr.com/2199/2365883747_3a5c753719_o.jpg
http://news.buzzbuzzhome.com/2013/04/top-7-aerial-photos-cities.htmlhttps://www.flickr.com/photos/superlekker/5917559189/sizes/lhttps://www.flickr.com/photos/derekbruff/12336187505/sizes/l
https://www.flickr.com/photos/chberge/3803475294/sizes/lhttps://www.flickr.com/photos/neilsingapore/8057578769
https://www.flickr.com/photos/dionnehartnett/6805481856/sizes/lhttps://www.flickr.com/photos/thomashawk/186339737
https://www.flickr.com/photos/cesarastudillo/3981364314/sizes/lhttps://www.flickr.com/photos/an_untrained_eye/6630719431
https://www.flickr.com/photos/30835738@N03/7936491790/sizes/lhttps://www.flickr.com/photos/deboni/2959228565/sizes/lhttps://www.flickr.com/photos/ghalog/6782751111/sizes/l
https://www.flickr.com/photos/timzim/177640262/sizes/o/https://www.flickr.com/photos/innoxiuss/2824204305
https://www.flickr.com/photos/hawk59/6038847752/sizes/lhttps://www.flickr.com/photos/remydwd/5487417702/sizes/l
https://www.flickr.com/photos/rammorrison/4359793666/sizes/o/https://www.flickr.com/photos/piers_nye/2501994750/sizes/o/
https://www.flickr.com/photos/danielygo/7559750132/sizes/lhttps://www.flickr.com/photos/msc72/2600035028/sizes/l
https://www.flickr.com/photos/sicilianitaliano/3609275241/sizes/lhttps://www.flickr.com/photos/scottmontreal/7235110028/sizes/lhttps://www.flickr.com/photos/piet_musterd/6170853224/sizes/l
https://www.flickr.com/photos/music_embassy/7137413247/sizes/lhttp://upload.wikimedia.org/wikipedia/commons/9/9c/William_James_b1842c.jpg
http://theverybesttop10.files.wordpress.com/2013/08/the-world_s-top-10-things-no-person-with-a-ocd-should-see-1.jpg
https://www.flickr.com/photos/62244271@N03/8553590682/sizes/l