Skip to content

Instantly share code, notes, and snippets.

@rmosolgo
Created November 6, 2021 17:00
Show Gist options
  • Save rmosolgo/aaf813804319894be4277ced8af4b19d to your computer and use it in GitHub Desktop.
Save rmosolgo/aaf813804319894be4277ced8af4b19d to your computer and use it in GitHub Desktop.
require "bundler/inline"
gemfile do
gem "graphql", "1.12.18"
end
class Schema < GraphQL::Schema
class Thing < GraphQL::Schema::Object
field :name, String, null: true
field :other_thing, self, null: true
def other_thing
{ name: "Other Thing", other_thing: :other_thing }
end
end
class Query < GraphQL::Schema::Object
field :thing, Thing, null: true
def thing
{ name: "Thing", other_thing: :other_thing }
end
end
class CustomQueryDepthAnalyzer < GraphQL::Analysis::AST::QueryDepth
INTROSPECTION_MAX_DEPTH = 13
DEFAULT_MAX_DEPTH = 10
def initialize(query)
@is_introspection = true # maybe set to false below
super
end
def on_enter_field(node, parent, visitor)
@is_introspection &= (visitor.field_definition.introspection? || ((owner = visitor.field_definition.owner) && owner.introspection?))
super
end
def result
if (@is_introspection && @max_depth > INTROSPECTION_MAX_DEPTH) ||
(!@is_introspection && @max_depth > DEFAULT_MAX_DEPTH)
GraphQL::AnalysisError.new("This query contains selections that are too deeply nested (depth: #{@max_depth}). Limit selections to #{@is_introspection ? INTROSPECTION_MAX_DEPTH : DEFAULT_MAX_DEPTH}#{@is_introspection ? " for introspection queries" : ""} instead.")
else
nil
end
end
end
query(Query)
query_analyzer(CustomQueryDepthAnalyzer)
end
# Small introspection queries are allowed:
pp Schema.execute("{ __typename }").to_h
# {"data"=>{"__typename"=>"Query"}}
pp Schema.execute(GraphQL::Introspection::INTROSPECTION_QUERY).to_h
# { "data" => { "__schema"=> ... } }
# Small queries are allowed:
pp Schema.execute("{ thing { name } }").to_h
# {"data"=>{"thing"=>{"name"=>"Thing"}}}
pp Schema.execute("{ thing { otherThing { otherThing { otherThing { otherThing { otherThing { otherThing { otherThing { otherThing { name } } } } } } } } } }").to_h
# {"data"=>
# {"thing"=>
# {"otherThing"=>
# {"otherThing"=>
# {"otherThing"=>
# {"otherThing"=>
# {"otherThing"=>
# {"otherThing"=>
# {"otherThing"=>{"otherThing"=>{"name"=>"Other Thing"}}}}}}}}}}}
# But big queries are blocked:
pp Schema.execute("{ thing { otherThing { otherThing { otherThing { otherThing { otherThing { otherThing { otherThing { otherThing { otherThing { name } } } } } } } } } } }").to_h
# {"errors"=>
# [{"message"=>
# "This query contains selections that are too deeply nested (depth: 11). Limit selections to 10 instead."}]}
# And big introspection queries are blocked:
pp Schema.execute("{ __type(name: \"Query\") { fields { type { ofType { ofType { ofType { ofType { ofType { ofType { ofType { ofType { ofType { ofType { ofType { ofType { name } } } } } } } } } } } } } } } }").to_h
# {"errors"=>
# [{"message"=>
# "This query contains selections that are too deeply nested (depth: 16). Limit selections to 13 for introspection queries instead."}]}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment