Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Dr Evil’s World Domination API

Dr Evil’s World Domination API

Your API’s developer experience (DX) matters as much as your web site’s user experience: making people more successful ultimately makes more people successful. For HTTP APIs, a good DX doesn’t only come from HTTP’s simplicity, but also from its depth. This presentation introduces a parody API that makes every classic mistake, and shows how they lead to Dr Evil’s inevitable downfall.

Further reading: Use HTTP error handling in APIs and HTTP client error status code checklist.

Peter Hilton

April 08, 2021
Tweet

More Decks by Peter Hilton

Other Decks in Technology

Transcript

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

    View full-size slide

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

    View full-size slide

  3. Dr Evil’s big mistakes

    View full-size slide

  4. 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 •

    View full-size slide

  5. World Domination API

    View full-size slide

  6. 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

    mlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlf
    ormats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmln
    s:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"
    xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxml
    formats.org/wordprocessingml/2006/main" xmlns:wne="http://schemas.microsoft.com/o
    ffice/word/2006/wordml">
    :gridCol w:w="2943"/>

    View full-size slide


  7. 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

    View full-size slide


  8. 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

    View full-size slide


  9. 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

    View full-size slide

  10. "
    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

    View full-size slide

  11. #
    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




    View full-size slide

  12. $
    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"
    }

    View full-size slide

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

    View full-size slide

  14. %
    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




    View full-size slide

  15. &
    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"}
    ]

    View full-size slide

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

    View full-size slide

  17. '
    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

    View full-size slide

  18. (
    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

    View full-size slide

  19. Lessons learned

    View full-size slide

  20. 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 •

    View full-size slide

  21. 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 •

    View full-size slide

  22. 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 •

    View full-size slide

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

    View full-size slide