graphql in python and djangopyparis.org/static/slides/patrick arminio-1cba4f64.pdf · you can parse...

131
GraphQL in Python and Django Patrick Arminio @patrick91

Upload: others

Post on 23-May-2020

1 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

GraphQL in Python and DjangoPatrick Arminio @patrick91

Page 2: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Who am I

● Patrick Arminio

● Backend Engineer @ Verve

● Chairperson at Python Italia

● @patrick91 online

Page 3: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

GraphQL?

Page 4: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

WEB 1.0

Page 5: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that
Page 6: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

WEB 2.0

Page 7: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that
Page 8: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

REST APIs

Page 9: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

While REST APIs are good, they have some shortcomings

Page 10: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Too many API calls

(under-fetching)

Page 11: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

http GET /user/1

Page 12: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

{

"name": "Patrick",

"friends": [

"/users/2",

"/users/3",

"/users/4"

],

"avatar": "/images/123"

}

Page 13: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

http GET /user/2http GET /user/3http GET /user/4

Page 14: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

http GET /user_with_friends/1

Page 15: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

{

"name": "Patrick",

"friends": [

{ "name": "Fiorella" },

{ "name": "Marco" },

{ "name": "Marta" }

],

"avatar": "/images/123"

}

Page 16: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

http GET /user_with_friends/1

Page 17: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

http GET /user_with_friends/1http GET /user_with_friends_and_avatar/1

Page 18: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

http GET /user_with_friends/1http GET /user_with_friends_and_avatar/1http GET /user_with_avatar/1

Page 19: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

http GET /user_with_friends/1http GET /user_with_friends_and_avatar/1http GET /user_with_avatar/1http GET /user_with_small_avatar/1

Page 20: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

http GET /user_with_friends/1http GET /user_with_friends_and_avatar/1http GET /user_with_avatar/1http GET /user_with_small_avatar/1http GET /user_with_small_avatar_and_friends/1

Page 21: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

http GET /user_with_friends/1http GET /user_with_friends_and_avatar/1http GET /user_with_avatar/1http GET /user_with_small_avatar/1http GET /user_with_small_avatar_and_friends/1http GET /page-1

Page 22: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

http GET /user_with_friends/1http GET /user_with_friends_and_avatar/1http GET /user_with_avatar/1http GET /user_with_small_avatar/1http GET /user_with_small_avatar_and_friends/1http GET /page-1http GET /page-2

Page 23: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

[...] At the time, we had over 1,000 different REST endpoints at Coursera (and now we have many more) [...]

Source: Courserahttps://dev-blog.apollodata.com/courseras-journey-to-graphql-a5ad3b77f39a

Page 24: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Too much data (over-fetching)

Page 25: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

{

"name": "Patrick",

"friends": [{

"name": "Ernesto",

"friends": ["/users/2", "/users/3", "/users/4"],

"avatar": {

"url": "//cdn.x.com/123.jpg",

"width": 400,

"height": 300

}

},

{

"name": "Simone",

"friends": ["/users/2", "/users/3", "/users/4"],

"avatar": {

"url": "//cdn.x.com/123.jpg",

"width": 400,

"height": 300

}

},

{

"name": "Marta",

"friends": ["/users/2", "/users/3", "/users/4"],

"avatar": {

"url": "//cdn.x.com/123.jpg",

"width": 400,

"height": 300

}

}

],

"avatar": {

"url": "//cdn.x.com/123.jpg",

"width": 400,

"height": 300

}

}

Page 26: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that
Page 27: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

REST AND HYPERMEDIA LINKS ARE GREAT, BUT NOT ALWAYS THE BEST CHOICE WHEN BUILDING WEBSITES OR APPS.

Page 28: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Documentation

Page 29: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that
Page 30: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Can we do better?

Page 31: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

We could extend REST, but...

Page 32: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

There won’t be a standard way

Page 33: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

GraphQL! ✨

Page 34: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

GraphQL is a Query Language for APIs.

Source: https://graphql.org/

Page 35: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

GraphQL is a specification

Page 36: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Single HTTP endpoint

Page 37: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

http POST /graphql

Page 38: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

{

user(id: "1") {

name

friends {

name

}

avatar

}

}

Page 39: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

{

"user": {

"name": "Patrick",

"friends": [

{ "name": "Fiorella" },

{ "name": "Marco" },

{ "name": "Marta" }

],

"avatar": "/images/123"

}

}

Page 40: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

GraphQL is typed

Page 41: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

type Query {

user(id: ID!): User

}

type User {

name: String!

friends: [Friend!]!

avatar: String!

}

type Friend {

name: String!

}

Page 42: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

type Query {

user(id: ID!): User

}

type User {

name: String!

friends: [Friend!]!

avatar: String!

}

type Friend {

name: String!

}

Page 43: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

type Query {

user(id: ID!): User

}

type User {

name: String!

friends: [Friend!]!

avatar: String!

}

type Friend {

name: String!

}

Page 44: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

type Query {

user(id: ID!): User

}

type User {

name: String!

friends: [Friend!]!

avatar: String!

}

type Friend {

name: String!

}

Page 45: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

type Query {

user(id: ID!): User

}

type User {

name: String!

friends: [Friend!]!

avatar: String!

}

type Friend {

name: String!

}

Page 46: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

type Query {

user(id: ID!): User

}

type User {

name: String!

friends: [Friend!]!

avatar: String!

}

type Friend {

name: String!

}

Page 47: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Scalar Types

● Int

● Float

● String

● Boolean

● Any user defined scalars (IE. datetime)

Page 48: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Object Types are the objects defined in your GraphQL

API. They are objects that have fields that can of scalar

types or other object types.

Object Types

Page 49: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Type “modifiers”

● List

● Non-nulls

Page 50: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Why is this important?

Page 51: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Static checking

Page 52: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Documentation and introspection

Page 53: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Let’s see an example

Page 54: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that
Page 55: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Operations

Page 56: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

3 Main operations

Subscription

Allows to subscribe to events, for example when

a new user has been created.

Mutation

Allows you to modify/create data on the server.

But it is not limited to data, can be used to run

anything with side effects.

Query

Allows to request data from the server.

Page 57: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Query (shortcut)

{

user(id: "1") {

name

}

}

Page 58: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Query

query QueryName($id: ID!) {

user(id: $id) {

name

}

}

Page 59: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Mutation

mutation MutationName($input: CreateUserInput!) {

createUser(input: $input) {

ok

}

}

Page 60: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Subscription

subscription SubscriptionName {

onUserCreated {

name

}

}

Page 61: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Intermission

Page 62: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

GraphQL in Python

Page 63: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

2 libraries

Page 64: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Ariadne

https://github.com/mirumee/ariadne/

● Quite new

● Python 3.5+

● “Closer to GraphQL”

Page 65: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Graphene

https://graphene-python.org/

● Most popular

● Python 2.7+ and Python 3.5+

● Nice abstraction on top of GraphQL

● Support for Django and more frameworks

Page 66: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Let’s start withAriadne

Page 67: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

We need a schematype Query {

user(id: ID!): User

}

type User {

name: String!

friends: [Friend!]!

avatar: String!

}

type Friend {

name: String!

}

Page 68: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

We need a schematype Query {

user(id: ID!): User

}

type User {

name: String!

friends: [Friend!]!

avatar: String!

}

type Friend {

name: String!

}

Page 69: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

We need a schematype Query {

user(id: ID!): User

}

type User {

name: String!

friends: [Friend!]!

avatar: String!

}

type Friend {

name: String!

}

Page 70: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

How do we link data to the fields?

Page 71: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Resolvers

Page 72: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Each field on each type is backed by a function called the resolver which is provided by the GraphQL server developer.

Page 73: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

A simple resolverdef resolve_user(_, info, id):

return {

"name": "Patrick",

"friends": [

{"name": "Fiorella"},

{"name": "Marco"},

{"name": "Marta"},

],

"avatar": "/images/123",

}

Page 74: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Attaching a resolver to a Typeresolvers = {

"Query": {"user": resolve_user},

"User": {"name": resolve_name},

}

Page 75: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Creating and running the serverserver = GraphQLMiddleware.make_simple_server(

schema,

resolvers

)

server.serve_forever()

Page 76: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Done!

Page 77: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that
Page 78: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Intermission

Page 79: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Graphene

Page 80: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

The schema is defined in Python

Page 81: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Our schematype Friend {

name: String!

}

type User {

name: String!

friends: [Friend!]!

avatar: String!

}

type Query {

user(id: ID!): User

}

Page 82: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Defining types with Graphene - Friendclass FriendType(graphene.ObjectType):

name = graphene.String(required=True)

Page 83: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Types and resolvers live together*

* resolvers can also be external functions

Page 84: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Defining types with Graphene - Userclass UserType(graphene.ObjectType):

name = graphene.String(required=True)

friends = graphene.List(graphene.NonNull(FriendType))

avatar = graphene.String(required=True)

def resolve_friends(self, info):

return [

FriendType(name="Marta"),

FriendType(name="Marco"),

FriendType(name="Fiorella"),

]

Page 85: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Defining types with Graphene - Queryclass Query(graphene.ObjectType):

user = graphene.Field(

UserType,

id=graphene.ID()

)

def resolve_user(self, info, id):

return UserType(

name="Patrick",

avatar="/images/123"

)

Page 86: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Finally, the schemaschema = graphene.Schema(query=Query)

Page 87: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Done!

Page 88: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Django SupportGraphene has support for Django, meaning that:

● Has a built in view

● It can create types from django models

● It can create mutations from Forms and DRF Serializers

● Has support for django filters

Page 89: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

What about

Page 90: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Authentication

Page 91: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

AuthenticationWhen using GraphQL with HTTPs you have 3 options for

authentication:

● Sessions

● HTTP Headers

● Field arguments

Page 92: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

SessionsBasically you rely on the browser sending cookies to your backend

service, this works pretty well with Django.

Good when you an API that works only with your frontend and when

you don’t have a mobile application.

Page 93: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

HeadersYou can use headers when you have third party clients accessing

your API or when you have a mobile app.

Usually it is used in combination with JWT tokens.

Page 94: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Field paramsThis might be a good solution when you only have a few fields that

require authentication. It could work like this:

{

myBankStatement(token: "ABC123") {

date

amount

}

}

Page 95: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Security

Page 96: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Quite easy to create “malicious” queries

Page 97: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

{

thread(id: "some-id") {

messages(first: 99999) {

thread {

messages(first: 99999) {

thread {

messages(first: 99999) {

thread {

# ...repeat times 10000...

}

}

}

}

}

}

}

Page 98: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Solution for “malicious” queriesTo prevent bad queries to happen we can adopt various solutions:

● Timeouts

● Limits on nested fields

● Query cost

● Static queries

Page 99: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

TimeoutsCheck how long a query is taking, if it is taking more than 1 second

you can kill it.

● Prevents huge queries from DOS-ing your server

● Prevents long waiting time

Page 100: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Limit on nested fieldsYou can parse the incoming GraphQL request and deny queries that

are requesting for fields that are too nested. For example you can

only allow for maxing 3 levels of nesting and no more.

Easy solution when you don’t need complex checks.

Page 101: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Query costsThis is useful if you have third party clients and when you also want

to limit their API usage.

The idea is to give each field a cost and calculate the cost of the

query based on the number of fields requested.

This works extremely well with paginated data (where you know how

much data you’re asking for)

Page 102: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Query costs - example queryquery {

viewer {

repositories(first: 50) {

issues(first: 10) {

title

}

}

}

}

Page 103: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Query costs - calculating the cost50 = 50 repositories

+

50 x 10 = 500 repository issues

= 550 total nodes

Page 104: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Static queriesInstead of allowing any query to be ran on your API you could allow

only a predefined list of queries. You’d save those queries on a

database and reference them by ID. So instead of doing a request

passing the query to GraphQL you’d pass only the ID (and the

variables if any).

Page 105: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

http POST /graphql?id=123

Page 106: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Static queries● Good to prevent unwanted queries

● Still allows to use all the advantages of GraphQL

● A bit cumbersome to deploy

● If you have third party you need a way for them to declare

queries

● Potentially good for caching (see next slide)

Page 107: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

http GET /graphql?id=123

Page 108: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Caching

Page 109: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Client Caching

Page 110: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Network Caching

Page 111: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Application Caching

Page 112: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Additional Things

Page 113: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Arguments and Inputs

Page 114: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

{

search(text: "an") {

title

}

}

Page 115: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

{

createUser(input: { … }) {

user {

name

}

}

}

Page 116: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Input Types

Page 117: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

input CreateUserInput {

name: String!

age: Int

}

Page 118: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Enums

Page 119: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

enum Conference {

PYPARIS

PYCONX

PYCONUS

}

Page 120: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Interfaces

Page 121: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

interface Character {

id: ID!

name: String!

}

type Human implements Character {

id: ID!

name: String!

friends: [Character]

starships: [Starship]

}

Page 122: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

union SearchResult = Human | Droid

{

search(text: "an") {

... on Human {

name

height

}

... on Droid {

name

primaryFunction

}

}

}

Page 123: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Errors

Page 124: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that
Page 125: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

And more

Page 126: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Frontend

Page 127: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Frontend developers benefit a lot from GraphQL, thanks to all the tooling available.

Page 128: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Relay

https://facebook.github.io/relay/

● Made by Facebook

● React Only

Page 129: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Apollo

https://www.apollographql.com/

● Supports many frameworks (React, Vue, etc)

● Big community

● Lots of tooling

Page 130: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

Verve is Hiring 🎉Want to work in an amazing company and use Python 3, GraphQL and Django?

https://verve.co/careers/

Page 131: GraphQL in Python and Djangopyparis.org/static/slides/Patrick Arminio-1cba4f64.pdf · You can parse the incoming GraphQL request and deny queries that are requesting for fields that

THANKS!Patrick Arminio

@patrick91