How to create a Web API – no one wants to use – Taking a look



How to create a Web API – no one wants to use – Taking a look

0 0


How-to-create-a-web-api-no-one-wants-to-use

"How to create a web API" presentation from TechDays Sweden and NDC London

On Github karolikl / How-to-create-a-web-api-no-one-wants-to-use

How to create a Web API

no one wants to use

By Karoline Klever / @karolikl

Taking a look

at the world of Web APIs...

Start out by looking at how the world of Web APIs has evolved, and where we are at today.

Your car has one

Tesla Model S, came out in 2012, and it has an API. We'll look at that later. API

Chuck Norris has one

Probably only human being with an API. Although, on second thought, he's not completely human. API

Your dog has one

API for a dog collar monitoring the health and behaviour of your dog. API

The number of Web APIs

is increasing fast

  • Graph from ProgrammableWeb, they keep an API directory of all APIs out there
  • Took 8 years to reach 10,000 APIs. Just reached 12,000.
  • It has been predicted that # of public and private APIs climbing to between 100,000 and 200,000
  • Next slides from founder of ProgrammableWeb in 2010.

1995

"Why do we need a website?"

2000

"Of course we have a website!"

2005

"Why do we need an API?"

2010

"Of course we have an API!"
Twitter made restrictions to their API:
  • Require authentication
  • Limit number of requests
  • Changing developer guidelines to dev requirements
In june, they announced they would be closing, and already then they stopped issuing developer keys. It is now closed..
ESPN published this 3 months ago, they’re discontinouing their APIs from december 2014. Total shut-down.

URI Design

Badly named and inconsistent URIs that violate the Principle of Least Astonishment will make your web API just as disappointing as the movie "Sharknado".

Principle of Least Astonishment

"[...] a programmer should try to think of the behavior that will least surprise someone who uses the program, rather than that behavior that is natural from knowing the inner workings of the program."
  • 1984
  • Number of WTFs
API provides URLs for official city and county government web sites and city and county location data.

Problem #1

Inconsistent URI structure

We cannot guess the URI of an endpoint based on our experience with the other endpoints.

Problem #2

URIs are not hackable

/all_links_for_city_of/chicago/il.json

/all_links_for_city_of/chicago/il.json

/all_links_for_city_of/chicago/il.json

Problem #3

Link types

/all_links_for_city_of/chicago/il.json

/all_links_for_county_of/cook%20county/il.json

/primary_links_for_city_of/chicago/il.json

/primary_links_for_county_of/cook%20county/il.json

Duplicating endpoints. Unless you’re using URL templating, this will be a problem.

Possible solution

(One of many)

/links

/links/il

/links/il/cook%20county

/links/il/cook%20county/chicago

/links/il/cook%20county/chicago?type=primary

Possible solution, assuming you’re not building your API using hypermedia. If you are building your API using hypermedia, that’s awesome! But it’s also a complete different talk than the one I’m doing right now.

HTTP Verbs

Why do we need anything other than GET?

There's an old story called "The Spider of Doom" where a company developing a content management system suddenly found that their client had "magically" lost all the pages of their website. After a lot of searching around, they found that the Googlebot was able to bypass their authentication mechanisms and had therefore crawled all their "Delete page" links. This, of course, resulted in all the pages of the website being deleted.

The most commonly used

GET

PUT

POST

DELETE

Safe methods

"... the convention has been established that the GET and HEAD methods SHOULD NOT have the significance of taking an action other than retrieval. These methods ought to be considered "safe"."

Are they safe?

GET: Yes

PUT: No

POST: No

DELETE: No

  • Updating, creating and deleting has side-effects

Idempotent methods

Methods we can issue the same request against as many times as we want without changing the result.

  • GET, PUT, DELETE, HEAD
  • Identical requests
  • Example: Get will always retrieve a resource
  • Example: Delete will always result in the resource not existing
  • Method Definitions

Are they idempotent?

GET: Yes

PUT: Yes

POST: No

DELETE: Yes

  • Get -> Will always retrieve the requested resource
  • Put -> Will always result in the resource being updated
  • Post -> Posting an order for a car, repeating the request will create another order
  • Delete -> Will always result in the resource being gone
  • The greatest car ever built
  • Batmobile API
  • Hurts to find something wrong with the API

Get climate

GET /vehicles/{id}/command/climate_state
{
    "inside_temp": 17.0,       
    "outside_temp": 9.5,         
    "driver_temp_setting": 22.6, 
    "passenger_temp_setting": 22.6, 
    "is_auto_conditioning_on": false, 
    "is_front_defroster_on": null,
    "is_rear_defroster_on": false,
    "fan_status": 0             
}
                        
  • Get climate state of the car
  • Safe: No side effects to getting the climate state
  • Idempotent: X requests will always give info on climate

Open sunroof

GET /vehicles/{id}/command/sun_roof_control?state=open
  • Problem:
  • Not safe: It changes the state of the car
  • Idempotent: X requests will always result in the sun roof being opened

Possible solution

GET /vehicles/{id}/command/sun_roof_control
{
    "state": "open"       
}
                        
PUT /vehicles/{id}/command/sun_roof_control?state=open
{
    "result": true       
}
                        

The other Verbs?

GET Returns the state of the sun roof (open/closed) PUT Open/close the sunroof POST Not supported, cannot create new sun roof DELETE Not supported, cannot delete sun roof
Thread on Reddit

A must read

Section 9 «Method definitions» in RFC 2616

https://tools.ietf.org/html/rfc2616#section-9

HTTP Status Codes

Everyone just loves an "error in disguise".

Problem #1

Disguising your errors

Invalid requests return with a 200 OK status code, giving the impression that the request was successful.

Problem #2

Displaying your internals

Including a detailed error report or stack trace makes your Web API vulnerable to attack

The basics

2xx Awesome! 4xx The user of the API made a mistake 5xx The creator of the API made a mistake
  • 2xx: The request has succeeded
  • 4xx: The request could not be understood by the server due to malformed syntax
  • 5xx:The server encountered an unexpected condition which prevented it from fulfilling the request
  • If serious: 201 Created, 304 Not Modified, 401 Unauthorized and 404 Not Found

Possible solution

GET http://api.worldbank.org/countries/a?format=json 
404 Not Found
GET http://api.worldbank.org/topic?format:json 
400 Bad Request
  • First gave us 200 OK -> 404 Not Found
  • Second gave us 500 Internal Server Error -> 400 Bad Request

A must read

Section 10 «Status Code Definitions» in RFC 2616

https://tools.ietf.org/html/rfc2616#section-10

Result Formatting

Dictating the format will drive developers away.

  • Not acceptable to only provide XML results
  • Dictating the format drives developers away

XML is on decline

Hurray!

Possible solutions

  • URL extensions
  • Query string parameters
  • Content negotiation
  • 1: Run, dictate xml. No other formats
  • 2: Run, add .json, add .xml. Show fallback again. Problem: 2 different URLs supply same data, suggest 2 different resources. 2 different representations of one resource.
  • 3. Run, add ?format=json, ?format=xml. Show fallback again. Each resource has 1 URL and different representations retrieved by queryparam. Scheduling dinner with friend -> suggest. We want that in API.
  • 4. Run -> view header -> Content-Type. Add Accept: text/turtle. Add Accept: text/turtle, application/json. Add Accept: text/turtle, application/json, text/xml

Versioning

However perfect you make your web API, you're bound to find a way that's even more perfect before long, and then you'll need to launch a new version.

  • Many solutions, not "one". You choose
  • Never break existing versions
  • Plan versioning from the start

Capture5 -> Complete / Cancel2

URL versioning

GET https://api.twitter.com/1.1/trends/place.json?id=1 
  • Pro: Easy to change the structure of your API
  • Pro: No confusion as to what version you are using, you can send the URL
  • Con: Maintain quite a large number of URLs as time goes by (templating might work)
  • Con: Clients wanting to upgrade will have to change all their URLs
  • Con: No way to say: "Always give me the newest version of your API".

Query string parameters

GET http://api-public.netflix.com/catalog/titles/series/7002352?v=1.5 
GET https://api.foursquare.com/v2/venues/40a55d80f964a52020f31ee3?oauth_token=XXX&v=YYYYMMDD 
  • Pro: Optional -> possible to always get the newest version.
  • Pro: Maintenance is easier as the URL is the same for each version
  • Pro: You can send the URL to someone else and they will see the same version of the API as you
  • Con: Harder to restructure the URI design
  • Great when the changes done from version to version are small -> No breaking changes

Vendor Specific Accept Header

HEADER Accept: {type}/vnd.{company}.{version}+{type}
HEADER Accept: {type}/vnd.{company}+{type}; version={version}
HEADER Accept: application/vnd.github.v3+json
HEADER Accept: application/vnd.github+json; version=3
  • Result formatting -> Content negotiation with accept headers to determine the format
  • GitHub, RedRata
  • Pro: Result formatting + versioning in the same accept header
  • Pro: URLs are always the same
  • Con: Harder to test -> cannot send url

Custom Request Header

HEADER x-ms-version: 2014-02-14
HEADER api-version: 2
Were deprecated in RFC 6648 as most downstream cache servers don’t care about custom headers. https://tools.ietf.org/html/rfc6648
  • HaveIBeenPawned
  • URL versioning
  • Vendor Specific Accept Header
  • Custom Request Headers

Summary

URI design

HTTP Verbs

HTTP Status Codes

Result Formatting

Versioning

  • Inconsistency & bad naming
  • Only use GET. Used them wrong
  • Disguise errors with 200 OKs. Display your internals
  • Dictate the format
  • Don't plan for versioning. Break existing versions

Questions?

Thank you!

By Karoline Klever / @karolikl / karolikl@gmail.com