Skip to content

Commit 971a239

Browse files
authored
fix: omit introspection queries from complexity limits (#1332)
This is disabled by default and should stay like that for now. There is a constant that can enable it again, but it is not intended to be tweaked by the clients.
1 parent 88ac8b8 commit 971a239

File tree

4 files changed

+54
-14
lines changed

4 files changed

+54
-14
lines changed

.coderabbit.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,8 @@ reviews:
1515
path_filters:
1616
# Exclude these paths (prefix with !)
1717
- "!pkg/**"
18+
pre_merge_checks:
19+
docstrings:
20+
mode: off
1821
chat:
1922
art: false

go.work.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
305305
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
306306
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
307307
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
308+
golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
308309
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
309310
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
310311
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
@@ -357,6 +358,7 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
357358
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
358359
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
359360
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
361+
golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
360362
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
361363
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
362364
gonum.org/v1/plot v0.10.1 h1:dnifSs43YJuNMDzB7v8wV64O4ABBHReuAVAoBxqBqS4=

v2/pkg/middleware/operation_complexity/operation_complexity.go

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,29 @@
11
/*
2-
package operation_complexity implements two common algorithms used by GitHub to calculate GraphQL query complexity
2+
Package operation_complexity implements two common algorithms used by GitHub to calculate
3+
GraphQL query complexity:
34
4-
1. Node count, the maximum number of Nodes a query may return
5-
2. Complexity, the maximum number of Node requests that might be needed to execute the query
5+
1. Node count, the maximum number of Nodes a query may return
6+
2. Complexity, the maximum number of Node requests that might be needed to execute the query
67
7-
OperationComplexityEstimator takes a schema definition and a query and then walks recursively through the query to calculate both variables.
8+
OperationComplexityEstimator takes a schema definition and a query and then
9+
walks recursively through the query to calculate both variables.
810
9-
The calculation can be influenced by integer arguments on fields that indicate the amount of Nodes returned by a field.
11+
The calculation can be influenced by integer arguments on fields that indicate
12+
the number of Nodes returned by a field.
1013
11-
To help the algorithm understand your schema you could make use of these two directives:
14+
To help the algorithm understand the schema make use of these two directives:
1215
13-
- directive @nodeCountMultiply on ARGUMENT_DEFINITION
14-
- directive @nodeCountSkip on FIELD
16+
- directive @nodeCountMultiply on ARGUMENT_DEFINITION
17+
- directive @nodeCountSkip on FIELD
1518
16-
nodeCountMultiply:
17-
Indicates that the Int value the directive is applied on should be used as a Node multiplier
19+
"nodeCountMultiply" indicates that the Int value the directive is applied on
20+
should be used as a Node multiplier.
1821
19-
nodeCountSkip:
20-
Indicates that the algorithm should skip this Node. This is useful to whitelist certain query paths, e.g. for introspection.
22+
"nodeCountSkip" indicates that the algorithm should skip this Node.
23+
It can be used to allowlist certain query paths.
24+
25+
Note: Introspection fields (__schema and __type) are automatically skipped
26+
from complexity calculations by default.
2127
*/
2228
package operation_complexity
2329

@@ -45,6 +51,12 @@ var (
4551
nodeCountSkip = []byte("nodeCountSkip")
4652
)
4753

54+
const (
55+
skipIntrospection = true
56+
__schemaLiteral = "__schema"
57+
__typeLiteral = "__type"
58+
)
59+
4860
type OperationComplexityEstimator struct {
4961
walker *astvisitor.Walker
5062
visitor *complexityVisitor
@@ -184,12 +196,16 @@ func (c *complexityVisitor) EnterField(ref int) {
184196
return
185197
}
186198

187-
if _, exits := c.definition.FieldDefinitionDirectiveByName(definition, nodeCountSkip); exits {
199+
if _, skip := c.definition.FieldDefinitionDirectiveByName(definition, nodeCountSkip); skip {
188200
c.SkipNode()
189201
return
190202
}
191203

192204
typeName, fieldName, alias := c.extractFieldRelatedNames(ref, definition)
205+
if skipIntrospection && (fieldName == __schemaLiteral || fieldName == __typeLiteral) {
206+
c.SkipNode()
207+
return
208+
}
193209
if c.isRootType(typeName) {
194210
c.resetCurrentRootFieldComplexity(typeName, fieldName, alias)
195211
}

v2/pkg/middleware/operation_complexity/operation_complexity_test.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ func TestCalculateOperationComplexity(t *testing.T) {
3939
run(t, testDefinition, `
4040
{
4141
users(first: 1) {
42+
__typename
4243
id
4344
balance
4445
name
@@ -66,6 +67,23 @@ func TestCalculateOperationComplexity(t *testing.T) {
6667
},
6768
)
6869
})
70+
t.Run("skipped node", func(t *testing.T) {
71+
run(t, testDefinition, `
72+
{
73+
activeUsers {
74+
id
75+
balance
76+
name
77+
}
78+
}`,
79+
OperationStats{
80+
NodeCount: 0,
81+
Complexity: 0,
82+
Depth: 0,
83+
},
84+
[]RootFieldStats{},
85+
)
86+
})
6987
t.Run("one user with inline fragments", func(t *testing.T) {
7088
run(t, testDefinition, `
7189
{
@@ -592,11 +610,12 @@ input NewUserInput {
592610
}
593611
594612
type Query {
595-
__schema: __Schema! @nodeCountSkip
613+
__schema: __Schema!
596614
user(id: ID!): User
597615
users(first: Int! @nodeCountMultiply, afterID: ID): [User]
598616
transactions(first: Int! @nodeCountMultiply, afterID: ID): [Transaction]
599617
currentPeriod: String
618+
activeUsers: [User] @nodeCountSkip
600619
}
601620
602621
type Mutation {

0 commit comments

Comments
 (0)