The Right API for the Job Rob Allen
PHPDay, May 2022
Slide 2
Fit for Purpose
Rob Allen ~ @akrabat
Slide 3
API Architecture
Rob Allen ~ @akrabat
Slide 4
APIs can be realised in any style but, which makes the most sense?
Rob Allen ~ @akrabat
Slide 5
RPC APIs
Rob Allen ~ @akrabat
Slide 6
RPC APIs • Call a function on a remote server
Rob Allen ~ @akrabat
Slide 7
RPC APIs • Call a function on a remote server • Common implementations: JSON-RPC, SOAP, gRPC
Rob Allen ~ @akrabat
Slide 8
RPC APIs • Call a function on a remote server • Common implementations: JSON-RPC, SOAP, gRPC • Tends to require a schema (WSDL, ProtoBuf Defintion)
Rob Allen ~ @akrabat
Slide 9
Ethereum JSON-RPC Request: POST / HTTP/1.1 Host: localhost:8545 { “jsonrpc”:”2.0”, “id”:1, “method”:”net_peerCount”, “params”:[] }
Rob Allen ~ @akrabat
Slide 10
Ethereum JSON-RPC Response: { “id”:1, “jsonrpc”: “2.0”, “result”: “0x2” }
Rob Allen ~ @akrabat
Slide 11
gRPC Interact via PHP library: $client = new RouteGuideClient(‘localhost:50051’); $p = new Routeguide\Point(); $p->setLatitude(409146138); $p->setLongitude(-746188906); list($feature, $status) = $client->GetFeature($p)->wait();
Rob Allen ~ @akrabat
Slide 12
RESTful APIs
Rob Allen ~ @akrabat
Slide 13
RESTful APIs • Operate on a representation of the state of a resource though HTTP verbs
Rob Allen ~ @akrabat
Slide 14
RESTful APIs • Operate on a representation of the state of a resource though HTTP verbs • HTTP native
Rob Allen ~ @akrabat
Slide 15
RESTful APIs • Operate on a representation of the state of a resource though HTTP verbs • HTTP native • Uniform interface
Rob Allen ~ @akrabat
Slide 16
RESTful APIs • Operate on a representation of the state of a resource though HTTP verbs • HTTP native • Uniform interface • Hypermedia controls
Rob Allen ~ @akrabat
Slide 17
RESTful APIs PUT /users/ba60c99fd3 Content-Type: application/json { “name”: “Rob Allen” “email”: “rob@akrabat.com” }
Rob Allen ~ @akrabat
Slide 18
RESTful APIs PUT /users/ba60c99fd3 Content-Type: application/json { “name”: “Rob Allen” “email”: “rob@akrabat.com” }
Rob Allen ~ @akrabat
Slide 19
RESTful APIs PUT /users/ba60c99fd3 Content-Type: application/json { “name”: “Rob Allen” “email”: “rob@akrabat.com” }
Rob Allen ~ @akrabat
Slide 20
RESTful APIs HTTP/1.1 201 Created ETag: dfb9f2ab35fe4d17bde2fb2b1cee88c1 Content-Type: application/json { “name”: “Rob Allen” “email”: “rob@akrabat.com”, “_links”: { “self”: “https://api.example.com/user/ba60c99fd3” } } Rob Allen ~ @akrabat
Slide 21
RESTful APIs HTTP/1.1 201 Created ETag: dfb9f2ab35fe4d17bde2fb2b1cee88c1 Content-Type: application/json { “name”: “Rob Allen” “email”: “rob@akrabat.com”, “_links”: { “self”: “https://api.example.com/user/ba60c99fd3” } } Rob Allen ~ @akrabat
Slide 22
RESTful APIs HTTP/1.1 201 Created ETag: dfb9f2ab35fe4d17bde2fb2b1cee88c1 Content-Type: application/json { “name”: “Rob Allen” “email”: “rob@akrabat.com”, “_links”: { “self”: “https://api.example.com/user/ba60c99fd3” } } Rob Allen ~ @akrabat
Slide 23
RESTful APIs HTTP/1.1 201 Created ETag: dfb9f2ab35fe4d17bde2fb2b1cee88c1 Content-Type: application/json { “name”: “Rob Allen” “email”: “rob@akrabat.com”, “_links”: { “self”: “https://api.example.com/user/ba60c99fd3” } } Rob Allen ~ @akrabat
Slide 24
GraphQL APIs
Rob Allen ~ @akrabat
Slide 25
GraphQL APIs • Retrieve only the data you need on consumer side
Rob Allen ~ @akrabat
Slide 26
GraphQL APIs • Retrieve only the data you need on consumer side • Reduce the number of calls to retrieve data with embedded resources
Rob Allen ~ @akrabat
Slide 27
GraphQL APIs • Retrieve only the data you need on consumer side • Reduce the number of calls to retrieve data with embedded resources • Self-describing schema
Rob Allen ~ @akrabat
Slide 28
Queries query { author(name: “Ann McCaffrey”) { id, name books(first: 5) { totalCount edges { node { id, title, datePublished } } } } } Rob Allen ~ @akrabat
Slide 29
Queries query { author(name: “Ann McCaffrey”) { id, name books(first: 5) { totalCount edges { node { id, title, datePublished } } } } } Rob Allen ~ @akrabat
Slide 30
Queries query { author(name: “Ann McCaffrey”) { id, name books(first: 5) { totalCount edges { node { id, title, datePublished } } } } } Rob Allen ~ @akrabat
Slide 31
Queries query { author(name: “Ann McCaffrey”) { id, name books(first: 5) { totalCount edges { node { id, title, datePublished } } } } } Rob Allen ~ @akrabat
Slide 32
Queries query { author(name: “Ann McCaffrey”) { id, name books(first: 5) { totalCount edges { node { id, title, datePublished } } } } } Rob Allen ~ @akrabat
Slide 33
Queries query { author(name: “Ann McCaffrey”) { id, name books(first: 5) { totalCount edges { node { id, title, datePublished } } } } } Rob Allen ~ @akrabat
Slide 34
Queries query { author(name: “Ann McCaffrey”) { id, name books(first: 5) { totalCount edges { node { id, title, datePublished } } } } } Rob Allen ~ @akrabat
Considerations • • • •
What is it to be used for? Response customisation requirements HTTP interoperability requirements Binary protocol?
Rob Allen ~ @akrabat
Slide 48
Response customisation • GraphQL is a query-first language • REST tends towards less customisation • With RPC you get what you’re given! (None will fix your database layer’s ability to efficiently retreive the data requested!)
Rob Allen ~ @akrabat
Slide 49
Performance • REST and RPC puts server performance first • GraphQL puts client performance first
Rob Allen ~ @akrabat
Slide 50
Caching • GraphQL and RPC can only cache at application layer • REST can additionally cache at HTTP layer
Rob Allen ~ @akrabat
Slide 51
Data Transfer GraphQL: query { avatar(userId: “1234”) } { “data”: { “avatar”: “(base64 data)” “format”: “image/jpeg” }
RPC: POST /api { “method”: “getAvatar”, “userId”: “1234” } { “result”: “(base64 data)” }
}}
Rob Allen ~ @akrabat
Slide 52
Data Transfer REST:
REST:
GET /user/1234/avatar Accept: image/jpeg
GET /user/1234/avatar Accept: application/json
HTTP/1.1 200 OK {jpg image data}
HTTP/1.1 200 OK {“data”: “(base64 data)”}
Rob Allen ~ @akrabat
Slide 53
Versioning • RPC, GraphQL and REST can all version via evolution as easily as each other
Rob Allen ~ @akrabat
Slide 54
Versioning • RPC, GraphQL and REST can all version via evolution as easily as each other • GraphQL is very good for deprecation of specific fields
Rob Allen ~ @akrabat
Slide 55
Design considerations It’s always hard!
Rob Allen ~ @akrabat
Slide 56
Design considerations It’s always hard!
Rob Allen ~ @akrabat
Slide 57
It’s your choice
Rob Allen ~ @akrabat
Slide 58
Developer Experience
Rob Allen ~ @akrabat
Slide 59
Correctness
Rob Allen ~ @akrabat
Slide 60
Correctness RPC: Functions!
Rob Allen ~ @akrabat
Slide 61
Correctness RPC: Functions! REST: HTTP matters!
Rob Allen ~ @akrabat
Slide 62
Correctness RPC: Functions! REST: HTTP matters! GraphQL: Think in terms of relationships!
Rob Allen ~ @akrabat
Slide 63
Correctness RPC: Functions! REST: HTTP matters! GraphQL: Think in terms of relationships!
Rob Allen ~ @akrabat
Slide 64
Errors
Rob Allen ~ @akrabat
Slide 65
Errors Error representations must be first class citizens
Rob Allen ~ @akrabat
Slide 66
Errors Error representations must be first class citizens
Rob Allen ~ @akrabat
Slide 67
Documentation
Rob Allen ~ @akrabat
Slide 68
Documentation • API Reference
Rob Allen ~ @akrabat
Slide 69
Documentation • API Reference • Tutorials
Rob Allen ~ @akrabat
Slide 70
To sum up
Rob Allen ~ @akrabat
Slide 71
If you suck at providing a REST API, you will suck at providing a GraphQL API Arnaud Lauret, API Handyman
Rob Allen ~ @akrabat
Slide 72
Thank you! https://joind.in/talk/8cdd9
Rob Allen ~ @akrabat