Slide 1

Slide 1 text

@PeterHilton http://hilton.org.uk/ Dr Evil’s World Domination API (HTTP mistakes to avoid)

Slide 2

Slide 2 text

I want two* things: 1. good HTTP API docs 2. good HTTP APIs * good DX 2 @PeterHilton •

Slide 3

Slide 3 text

Dr Evil’s big mistakes

Slide 4

Slide 4 text

Dr Evil’s big mistakes that will lead to his inevitable downfall 1. Building an application whose client communicates via HTTP with a back-end, and using that as a public API. 2. Publishing a public API without documentation. 3. Not hiring a technical writer to write the customer-facing documentation. 4. Not improving the API based on technical writer feedback. 5. Not expecting passive-aggressive API documentation. 5 @PeterHilton •

Slide 5

Slide 5 text

World Domination API

Slide 6

Slide 6 text

Retrieve evil plan Fetches the specified world domination plan. GET /plans/world-domination/042 HTTP/1.1 Accept: text/xml HTTP/1.1 200 OK Content-Type: text/xml

Slide 7

Slide 7 text

⚠ If the request URL is not valid, the response status is 500 Server Error instead of 404 Not Found. Retrieve evil plan Fetches the specified world domination plan. GET /plans/world-domination/42 HTTP/1.1 Accept: text/xml HTTP/1.1 500 Internal Server Error Content-Type: text/xml 666_INVALID_EVIL_PLAN_ID

Slide 8

Slide 8 text

⚠ A valid request URL with the wrong HTTP method returns a 500 Server Error status instead of 405 Method Not Allowed. Delete evil plan Discontinue a world domination plan. DELETE /plans/world-domination/001 HTTP/1.1 Accept: text/xml HTTP/1.1 500 Internal Server Error Content-Type: text/xml 666_DELETE_EVIL_PLANS_WITH_POST

Slide 9

Slide 9 text

⚠ Don’t expect to receive a 400 Bad Request status for an invalid request. You’re probably going to get 500 Server Error, or maybe 200 OK. Execute evil plan Fetches the specified world domination plan. POST /plans/world-domination/001 HTTP/1.1 Accept: text/xml HTTP/1.1 200 OK Content-Type: text/xml 666_ERROR_ERROR_ERROR

Slide 10

Slide 10 text

" You might expect that posting a plan in the wrong format would result in a 415 Unsupported Media Type status, but it turns out that you’ll just get a server error. Create evil plan Publishes a new world domination plan. POST /plans/world-domination HTTP/1.1 Content-type: application/json Accept: application/json { "summary": "World domination" } HTTP/1.1 500 Internal Server Error Content-Type: text/xml 666_CANNOT_PARSE_EVIL_PLAN

Slide 11

Slide 11 text

# Creating a new evil plan returns a 200 OK status instead of 201 Created. The (partial) URL is in the response body instead of a Location header. Create evil plan Publishes a new world domination plan. POST /plans/world-domination HTTP/1.1 Content-type: text/xml Accept: text/xml World domination HTTP/1.1 200 OK Content-Type: text/xml

Slide 12

Slide 12 text

$ Our back-end framework is rubbish, but at least the right status is in the JSON Create evil plan Publishes a new world domination plan. POST /plans/world-domination HTTP/1.1 Content-type: text/xml Accept: application/json World domination HTTP/1.1 200 OK Content-Type: application/json { "status":201, "message":"Created", "location":"world-domination/002" }

Slide 13

Slide 13 text

parse error: Invalid numeric literal at line 1, column 6

Slide 14

Slide 14 text

% Let’s be realistic - the API is just going to ignore your Accept request header, and always give you XML (or worse) instead of using 406 Not Acceptable Good luck writing error- handling code for that! Create evil plan Publishes a new world domination plan. POST /plans/world-domination HTTP/1.1 Content-type: text/xml Accept: application/json World domination HTTP/1.1 200 OK Content-Type: text/xml

Slide 15

Slide 15 text

& The response body is a JSON array… in random order. List evil plans Lists all published plans. GET /plans HTTP/1.1 Accept: application/json HTTP/1.1 200 OK Content-Type: application/json [ {"id":"001","title":"World domination"} {"id":"007","title":"Kill Bond"} {"id":"003","title":"Make everyone use SOAP"} {"id":"004","title":"Teach UML in schools"} {"id":"002","title":"Defend the patriarchy"} {"id":"006","title":"Roll out SAFe"} {"id":"008","title":"Mandate open plan offices"} {"id":"005","title":"Something with blockchain"} ]

Slide 16

Slide 16 text

hilton.org.uk/ blog/sort- every-collection

Slide 17

Slide 17 text

' The request requires JSON embedded in form encoding. (and we’ve fixed most of the encoding bugs) Create evil plan Publishes a new world domination plan. POST /plans HTTP/1.1 Content-type: text/xml Accept: application/json title=World%20domination& plan=%7B%22summar%22%3A%22world+domination%22%2C %22scope%22%3A%22WORLD%22%2C%22owner%22%3A%22Dr+ Evil%22%7D HTTP/1.1 201 Created Location: /plans/world-domination/02

Slide 18

Slide 18 text

( Do you think this API is going to give you a generic 400 Bad Request error for an application-specific non-HTTP client error. No it is not. You’ll have to guess whether it’s worth retrying this request later. Create evil plan Publishes a new world domination plan. POST /plans/world-domination HTTP/1.1 Content-type: text/xml Accept: text/xml World peace HTTP/1.1 500 Internal Server Error Content-Type: text/xml 666_INSUFFICIENTLY_EVIL_PLAN

Slide 19

Slide 19 text

Lessons learned

Slide 20

Slide 20 text

Expose API ugliness When you show the raw HTTP session, API ugliness has nowhere to hide. When you abstract away the HTTP layer, you tend to end up with a degenerate API. This is one reason why the API your own application’s front- end uses isn’t going to make a good public API. 21 @PeterHilton •

Slide 21

Slide 21 text

Use the right HTTP response status codes The first step in good HTTP API error handling is to actually use the right HTTP response status codes. Clients need the right HTTP status to decide what to do next, e.g. retry after a server error, not after a client error. Clients also need status codes when they can’t parse the response body. 22 @PeterHilton •

Slide 22

Slide 22 text

Read Peter’s blog posts Use HTTP error handling in APIs hilton.org.uk/blog/http-error-handling Client error status code checklist hilton.org.uk/blog/http-client-error-checklist 23 @PeterHilton •

Slide 23

Slide 23 text

No content

Slide 24

Slide 24 text

@PeterHilton http://hilton.org.uk/