API Driven Development with
GraphQL
tjwebb@langa.io
github.com/tjwebb
Part 1
- What is GraphQL
- The Language
- The Runtime
Part 2
- GraphQL Use Cases
What is GraphQL?
"GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data."
-- graphql.org
What is GraphQL?
"All the things that make SOAP awesome minus all the things that make SOAP terrible"
-- tjwebb
SOAP WSDL
<?xml version="1.0"?>
<definitions name="StockQuote"
targetNamespace="http://example.com/stockquote.wsdl"
xmlns:tns="http://example.com/stockquote.wsdl"
xmlns:xsd="http://www.w3.org/2000/10/XMLSchema"
xmlns:xsd1="http://example.com/stockquote.xsd"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<message name="GetTradePriceInput">
<part name="tickerSymbol" element="xsd:string"/>
<part name="time" element="xsd:timeInstant"/>
</message>
<message name="GetTradePriceOutput">
<part name="result" type="xsd:float"/>
</message>
<portType name="StockQuotePortType">
<operation name="GetTradePrice">
<input message="tns:GetTradePriceInput"/>
<output message="tns:GetTradePriceOutput"/>
</operation>
</portType>
<binding name="StockQuoteSoapBinding" type="tns:StockQuotePortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="GetTradePrice">
<soap:operation soapAction="http://example.com/GetTradePrice"/>
<input>
<soap:body use="encoded" namespace="http://example.com/stockquote"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output>
<soap:body use="encoded" namespace="http://example.com/stockquote"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
</operation>>
</binding>
<service name="StockQuoteService">
<documentation>My first service</documentation>
<port name="StockQuotePort" binding="tns:StockQuoteBinding">
<soap:address location="http://example.com/stockquote"/>
</port>
</service>
</definitions>
SOAP !!
What is GraphQL?
Imagine a service endpoint that accepts a query ...
POST /sql
select
name,
email,
cats
from user
where cats >= 5
What is GraphQL?
... disallows bad things ...
What is GraphQL?
... returns exactly the response shape you ask for ...
[
{
"name": "tjwebb",
"email": "tjwebb@langa.io",
"cats": 5
}
]
What is GraphQL?
... enforces types, is
self-documenting ...
type User {
name: String!
email: String!
cats: Int!
kats: Int @deprecated
}
What is GraphQL?
... declarative ...
query {
catUsers: user(cats: 5) {
name
cats
}
normalUsers: user(cats: 0) {
name
cats
}
}
{
"catUsers": [
{
"name": "tjwebb",
"cats": 5
}
],
"normalUsers": [ ]
}
What is GraphQL?
... has a surprisingly-readable
specification with examples ...
facebook.github.io/graphql
What is GraphQL?
... and built by people who know what the hell they're doing.
REST Request
GET /user?name=tjwebb
{
"user": {
"name": "tjwebb",
"email": "tjwebb@langa.io"
}
}
REST Request
GET /user?name=tjwebb
{
"user": {
"omg": "lol",
"password": "hunter2"
}
}
REST Request
GraphQL Request
POST /graphql
user (id: 1) {
name
email
}
{
"user": {
"name": "tjwebb",
"email": "tjwebb@langa.io"
}
}
REST Middleware
GET /user?name=tjwebb&fields=email,cats
handler (request, reply) {
const query = request.query
// validate query parameters
knex('user')
.where({ name: query.name })
.select(query.fields.split(','))
.then(result => {
// ... sanitize/validate result
reply(result)
})
}
REST Middleware
1. Parse/validate arguments
2. Get data
3. Transform/validate results
4. Return to client
GraphQL Middleware
POST /graphql
handler (request, reply) {
reply(graphql(this.schema, request.payload))
}
GraphQL Middleware
1. Define GraphQL Schema
2. Implement Resolvers
What is GraphQL?
"GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data."
-- graphql.org
GraphQL Schema
type UserQuery (email: String, cats: Int) {
name: String
email: String
cats: Int
}
schema {
query: {
user: UserQuery
}
}
GraphQL Query
type UserQuery (email: String, cats: Int) {
name: String
email: String
cats: Int
}
schema {
query: {
user: UserQuery
}
}
GraphQL Resolvers
type UserQuery (email: String, cats: Int) {
name: String
email: String
cats: Int
}
class User {
static resolver ({ email, cats }) {
return knex('user').where({ email, cats })
.then(([ record ]) => new User(record))
}
}
GraphQL Resolvers
type UserQuery (email: String, cats: Int) {
...
dynamicField: Float
}
class User {
static resolver ({ email, cats }) {
return knex('user').where({ email, cats })
.then(([ record ]) => new User(record))
}
get dynamicField () {
return Math.random()
}
}
GraphiQL.io
GraphQL Use Cases
Obvious Ideas
- Use it for your Startup Idea
- Pub/sub Twitter Bot
- Wrap an existing REST API
- Node.js ORM
Obvious Ideas
Use Cases
Mainframe Integration
Mainframe Integration
COBOL
Mainframe Integration
ESB Integration
ESB Integration
GraphQL Users
- Github
- Intuit
- Financial Times
- Shopify
- Wayfair
- Coursera
Questions?
tjwebb@langa.io
github.com/tjwebb
@tjwebbOnGithub
API Driven Development with GraphQL
By Travis Webb
API Driven Development with GraphQL
How can GraphQL make developing APIs faster and cleaner? Why does it make mocking and documenting your backend services easier? Also, just what is it, exactly? In this talk, we'll explore the basics of GraphQL, why it exists in the first place, and how it can make developing your Node applications way more productive and fun.
- 832