What "They" Should Have Told You About API Development
Phil Sturgeon
@philsturgeon
1. Documentation
2. REST or RPC
3. arbitrary advice
Easier than you think
- DON'T DO IT BY HAND
- Version control with code
- API Blueprint 👍🏼
- RAML / Swagger 🙌🏼
- Just write YAML or MD
- Attributes / Data Structures
- JSON Schema
Iterate, improve, and agree up on your contracts before you write any code!
Document First
Documentation without tests is like code without tests; You're just hoping it works well enough that you don't f**k everything up.
Testing
Broken documentation should fail the build.
Testing
Testing
$ npm install -g dredd
$ dredd init
$ dredd
info: Beginning Dredd testing...
fail: GET /products/1 duration: 17ms
fail: body: At '/data/attributes/volume' Missing required property: volume
complete: 4 passing, 1 failing, 0 errors, 10 skipped, 15 total
complete: Tests took 274ms
- Mocks are a fake API, generated from your documentation
- Share mocks to get integration feedback early
- Automatically generated by Apiary
- Free alternative for API Blueprint: drakov
Mocking
Mocking
$ npm install -g drakov
$ drakov -f apiary.apib
$ ngrok http 3000
$ http GET http://xxxxxx.ngrok.io/products --json
1. Documentation
2. REST or RPC
3. arbitrary advice
Don't confuse REST for a metric of quality
Making an API 100% RESTful is hard
Do you actually need REST?
Maybe RPC would be more appropriate?
RPC = Commands
REST = Resources
Using commands to interact with resources is awful
And vice versa
RPC: GET /listCheeseburgers
REST: GET /cheeseburgers
RPC: POST /createCheeseburger
REST: POST /cheeseburgers
RPC: POST /updateCheeseburger
REST: PATCH /cheeseburgers/1
RPC: POST /deleteCheeseburger
REST: DELETE /cheeseburgers/1
RPC: POST /consumeCheeseburger
REST: urm...?
Actions that trigger state changes could be RPC...
... but maybe you could PATCH on fields with a state machine?
module Api
module States
class Trip
include Statesman::Machine
state :locating, initial: true
state :in_progress
state :complete
state :canceled
transition from: :locating, to: [:in_progress, :canceled]
transition from: :in_progress, to: [:complete, :canceled]
after_transition(from: :locating, to: :in_progress) do |trip|
trigger_some_action(trip)
end
# ...
end
end
end
There is a reason Slack use RPC...
So probably RPC For commands then?
RPC: Remote Procedure call
- Do this random thing
- Here's some stuff to help you do that thing
- Poking a black box
- Great for events/commands/etc
- Kinda like a stored procedure
REST: representational state transfer
- Hard to be entirely RESTful
- Some folks try too hard
- Can also do actions, but as afterthoughts
- If RPC is like a stored procedure, REST is like an ORM
- Without HATEOAS you just have a very pretty RPC API
1. Documentation
2. REST or RPC
3. arbitrary advice
Maybe you don't need HATEOAS
Hypermedia helps your API outlive your startup
TDD is the easiest way to build a complex HTTP API
Describe-it syntax helps you write complex tests easily
RSpec.describe 'Avatars' do
let(:user) { create(:user) }
describe 'POST /avatars' do
let(:png_path) { 'spec/fixtures/files/avatar.png' }
let(:png_file) { File.read(Rails.root.join(png_path)) }
context 'when the user already had an avatar' do
let!(:old_avatar) { create(:avatar, user: user ) }
it 'deletes the old avatar for the user. No soft delete.' do
payload = {
avatars: {
image_url: 'http://fake-ride/example.png'
}
}
post '/avatars', payload
expect(user.reload.avatar).not_to eql(old_avatar)
end
end
end
end
RSpec.describe 'Avatars' do
describe 'POST /avatars' do
context 'direct image uploads' do
it 'will fail if content-type is invalid' do
headers = oauth_headers(user_token).merge({
'CONTENT_TYPE' => 'some/crap'
})
post '/avatars', nil, headers
expected_response = {
'errors' => [{
'code' => 11_506,
'title' => "The root key is missing from the payload.",
'status' => 400,
'details' => 'avatars'
}]
}
expect(parsed_response).to eq(expected_response)
expect(response).to have_http_status(:bad_request)
end
end
end
end
Don't let clients hit staging for dev
?include=literally,eve
rything,in,the,goddam,database,what,is,happening,so,slow,help,me,database,server,is,on,fire
apisyouwonthate.com
What They Should Have Told You About API Development
By Phil Sturgeon
What They Should Have Told You About API Development
- 2,293