All Projects → stems → Graphql Depth Limit

stems / Graphql Depth Limit

Licence: mit
Limit the complexity of your GraphQL queries based on depth.

Programming Languages

javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to Graphql Depth Limit

Graphql Client
A GraphQL Client for .NET Standard
Stars: ✭ 418 (-6.07%)
Mutual labels:  graphql
Entria Fullstack
Monorepo Playground with GraphQL, React, React Native, Relay Modern, TypeScript and Jest
Stars: ✭ 434 (-2.47%)
Mutual labels:  graphql
Crudl
CRUDL is a backend agnostic REST and GraphQL based admin interface
Stars: ✭ 438 (-1.57%)
Mutual labels:  graphql
Relay Hooks
Use Relay as React hooks
Stars: ✭ 423 (-4.94%)
Mutual labels:  graphql
Apollo Resolvers
Expressive and composable resolvers for Apollostack's GraphQL server
Stars: ✭ 428 (-3.82%)
Mutual labels:  graphql
Searchkit
GraphQL API & React UI components for Elasticsearch. The easiest way to build a great search experience
Stars: ✭ 4,338 (+874.83%)
Mutual labels:  graphql
Graphql Php
A PHP port of GraphQL reference implementation
Stars: ✭ 4,219 (+848.09%)
Mutual labels:  graphql
Graphql Pokemon
Get information of a Pokémon with GraphQL!
Stars: ✭ 441 (-0.9%)
Mutual labels:  graphql
Neo4j Graphql
GraphQL bindings for Neo4j, generates and runs Cypher
Stars: ✭ 429 (-3.6%)
Mutual labels:  graphql
Graphql Guard
Simple authorization gem for GraphQL 🔒
Stars: ✭ 434 (-2.47%)
Mutual labels:  graphql
Apollo Cache Hermes
A cache implementation for Apollo Client, tuned for performance
Stars: ✭ 425 (-4.49%)
Mutual labels:  graphql
Graphql Language Service
An interface for building GraphQL language services for IDEs
Stars: ✭ 427 (-4.04%)
Mutual labels:  graphql
Graphqlmap
GraphQLmap is a scripting engine to interact with a graphql endpoint for pentesting purposes.
Stars: ✭ 434 (-2.47%)
Mutual labels:  graphql
Grand Stack Starter
Simple starter project for GRANDstack full stack apps
Stars: ✭ 419 (-5.84%)
Mutual labels:  graphql
Create Graphql
Command-line utility to build production-ready servers with GraphQL.
Stars: ✭ 441 (-0.9%)
Mutual labels:  graphql
Graphql Tools
🔧 Build, mock, and stitch a GraphQL schema using the schema language
Stars: ✭ 4,556 (+923.82%)
Mutual labels:  graphql
Fraql
GraphQL fragments made simple ⚡️
Stars: ✭ 433 (-2.7%)
Mutual labels:  graphql
Get Graphql Schema
Fetch and print the GraphQL schema from a GraphQL HTTP endpoint. (Can be used for Relay Modern.)
Stars: ✭ 443 (-0.45%)
Mutual labels:  graphql
Hackernews React Graphql
Hacker News clone rewritten with universal JavaScript, using React and GraphQL.
Stars: ✭ 4,242 (+853.26%)
Mutual labels:  graphql
Vscode Graphql
VSCode GraphQL extension (autocompletion, go-to definition, syntax highlighting)
Stars: ✭ 435 (-2.25%)
Mutual labels:  graphql

GraphQL Depth Limit

Dead-simple defense against unbounded GraphQL queries. Limit the complexity of the queries solely by their depth.

Why?

Suppose you have an Album type that has a list of Songs.

{
  album(id: 42) {
    songs {
      title
      artists
    }
  }
}

And perhaps you have a different entry point for a Song and the type allows you to go back up to the Album.

{
  song(id: 1337) {
    title
    album {
      title
    }
  }
}

That opens your server to the possibility of a cyclical query!

query evil {
  album(id: 42) {
    songs {
      album {
        songs {
          album {
            songs {
              album {
                songs {
                  album {
                    songs {
                      album {
                        songs {
                          album {
                            # and so on...
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

How would your server handle it if the query was 10,000 deep? This may become a very expensive operation, at some point pinning a CPU on the server or perhaps the database. This is a possible DOS vulnerability. We want a way to validate the complexity of incoming queries.

This implementation lets you limit the total depth of each operation.

Quantifying Complexity

Deciding exactly when a GraphQL query is "too complex" is a nuanced and subtle art. It feels a bit like deciding how many grains of sand are needed to compose a "pile of sand". Some other libraries have the developer assign costs to parts of the schema, and adds the cumulative costs for each query.

graphql-validation-complexity does this based on the types, and graphql-query-complexity does it based on each field.

Adding up costs may work for some backends, but it does not always faithfully represent the complexity. By adding the costs at each depth, it's as if the complexity is increasing lineraly with depth. Sometimes the complexity actually increases exponentially with depth, for example if requesting a field means doing another SQL JOIN.

This library validates the total depth of the queries (and mutations).

Here's are some queries with a depth of 0

# simplest possible query
query shallow1 {
  thing1
}

# inline fragments don't actually increase the depth
query shallow2 {
  thing1
  ... on Query {
    thing2
  }
}

# neither do named fragments
query shallow3 {
  ...queryFragment
}

fragment queryFragment on Query {
  thing1
}

Deeper queries

# depth = 1
query deep1_1 {
  viewer {
    name
  }
}

query deep1_2 {
  viewer {
    ... on User {
      name
    }
  }
}

# depth = 2
query deep2 {
  viewer {
    albums {
      title
    }
  }
}

# depth = 3
query deep3 {
  viewer {
    albums {
      ...musicInfo
      songs{
        ...musicInfo
      }
    }
  }
}

fragment musicInfo on Music {
  id
  title
  artists
}

Usage

$ npm install graphql-depth-limit

It works with express-graphql and koa-graphql. Here is an example with Express.

import depthLimit from 'graphql-depth-limit'
import express from 'express'
import graphqlHTTP from 'express-graphql'
import schema from './schema'

const app = express()

app.use('/graphql', graphqlHTTP((req, res) => ({
  schema,
  validationRules: [ depthLimit(10) ]
})))

The first argument is the total depth limit. This will throw a validation error for queries (or mutations) with a depth of 11 or more.
The second argument is an options object, where you can do things like specify ignored fields. Introspection fields are ignored by default.
The third argument is a callback which receives an Object which is a map of the depths for each operation.

depthLimit(
  10,
  { ignore: [ /_trusted$/, 'idontcare' ] },
  depths => console.log(depths)
)

Now the evil query from before will tell the client this:

{
  "errors": [
    {
      "message": "'evil' exceeds maximum operation depth of 10",
      "locations": [
        {
          "line": 13,
          "column": 25
        }
      ]
    }
  ]
}

Future Work

  • [ ] Type-specific sub-depth limits, e.g. you can only descend 3 levels from an Album type, 5 levels from the User type, etc.
  • [ ] More customization options, like custom errors.

Documentation

depthLimit(maxDepth, [options], [callback]) ⇒ function

Creates a validator for the GraphQL query depth

Kind: global function
Returns: function - The validator function for GraphQL validation phase.

Param Type Description
maxDepth Number The maximum allowed depth for any operation in a GraphQL document.
[options] Object
options.ignore Array.<(String|RegExp|function())> Stops recursive depth checking based on a field name. Either a string or regexp to match the name, or a function that reaturns a boolean.
[callback] function Called each time validation runs. Receives an Object which is a map of the depths for each operation.
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].