Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions router-tests/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ require (
github.com/twmb/franz-go v1.16.1
github.com/twmb/franz-go/pkg/kadm v1.11.0
github.com/wundergraph/astjson v0.0.0-20250106123708-be463c97e083
github.com/wundergraph/cosmo/demo v0.0.0-20250715133706-4c418b758ddd
github.com/wundergraph/cosmo/demo v0.0.0-20250721114211-ea47c3893316
github.com/wundergraph/cosmo/demo/pkg/subgraphs/projects v0.0.0-20250715110703-10f2e5f9c79e
github.com/wundergraph/cosmo/router v0.0.0-20250715133706-4c418b758ddd
github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.207
github.com/wundergraph/cosmo/router v0.0.0-20250721114211-ea47c3893316
github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.208
go.opentelemetry.io/otel v1.28.0
go.opentelemetry.io/otel/sdk v1.28.0
go.opentelemetry.io/otel/sdk/metric v1.28.0
Expand Down
4 changes: 2 additions & 2 deletions router-tests/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -325,8 +325,8 @@ github.com/wundergraph/astjson v0.0.0-20250106123708-be463c97e083 h1:8/D7f8gKxTB
github.com/wundergraph/astjson v0.0.0-20250106123708-be463c97e083/go.mod h1:eOTL6acwctsN4F3b7YE+eE2t8zcJ/doLm9sZzsxxxrE=
github.com/wundergraph/consul/sdk v0.0.0-20250204115147-ed842a8fd301 h1:EzfKHQoTjFDDcgaECCCR2aTePqMu9QBmPbyhqIYOhV0=
github.com/wundergraph/consul/sdk v0.0.0-20250204115147-ed842a8fd301/go.mod h1:wxI0Nak5dI5RvJuzGyiEK4nZj0O9X+Aw6U0tC1wPKq0=
github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.207 h1:g2MpMjU/Jk30oBzfBjGRgH3EzTvwI0IV57HhlUjeyZc=
github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.207/go.mod h1:DaBrBCMgKGd3t7zg7z11jKm+0mVJiesr/IQCRG9qgP0=
github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.208 h1:dnWJ/nv+M2SF9aZnHXPU+gfSiANC7eAOSM4HU6ymc74=
github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.208/go.mod h1:DaBrBCMgKGd3t7zg7z11jKm+0mVJiesr/IQCRG9qgP0=
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
Expand Down
111 changes: 111 additions & 0 deletions router-tests/security_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package integration

import (
"net/http"
"testing"

"github.com/stretchr/testify/require"

"github.com/wundergraph/cosmo/router-tests/testenv"
"github.com/wundergraph/cosmo/router/pkg/config"
)

func TestParserHardLimits(t *testing.T) {
t.Parallel()

t.Run("parser approximate depth limit", func(t *testing.T) {
t.Parallel()
t.Run("blocks queries over the limit", func(t *testing.T) {
t.Parallel()
testenv.Run(t, &testenv.Config{
ModifySecurityConfiguration: func(securityConfiguration *config.SecurityConfiguration) {
securityConfiguration.ParserHardLimits = config.ParserHardLimitsConfiguration{
ApproximateDepthLimit: 2,
}
},
}, func(t *testing.T, xEnv *testenv.Environment) {
res, _ := xEnv.MakeGraphQLRequest(testenv.GraphQLRequest{
Query: `{ employee(id:1) { id details { forename surname } } }`,
})
require.Equal(t, 400, res.Response.StatusCode)
require.Equal(t, `{"errors":[{"message":"allowed parsing depth per GraphQL document of '2' exceeded"}]}`, res.Body)
})
})

t.Run("blocks persisted queries over the limit", func(t *testing.T) {
t.Parallel()
testenv.Run(t, &testenv.Config{
ModifySecurityConfiguration: func(securityConfiguration *config.SecurityConfiguration) {
securityConfiguration.ParserHardLimits = config.ParserHardLimitsConfiguration{
ApproximateDepthLimit: 2,
}
},
}, func(t *testing.T, xEnv *testenv.Environment) {
header := make(http.Header)
header.Add("graphql-client-name", "my-client")
res, _ := xEnv.MakeGraphQLRequestOverGET(testenv.GraphQLRequest{
OperationName: []byte(`Find`),
Variables: []byte(`{"criteria": {"nationality": "GERMAN" }}`),
Extensions: []byte(`{"persistedQuery": {"version": 1, "sha256Hash": "e33580cf6276de9a75fb3b1c4b7580fec2a1c8facd13f3487bf6c7c3f854f7e3"}}`),
Header: header,
})
require.Equal(t, 400, res.Response.StatusCode)
require.Equal(t, `{"errors":[{"message":"allowed parsing depth per GraphQL document of '2' exceeded"}]}`, res.Body)
})
})

t.Run("default limit allows persisted queries", func(t *testing.T) {
t.Parallel()
testenv.Run(t, &testenv.Config{}, func(t *testing.T, xEnv *testenv.Environment) {
header := make(http.Header)
header.Add("graphql-client-name", "my-client")
res, _ := xEnv.MakeGraphQLRequestOverGET(testenv.GraphQLRequest{
OperationName: []byte(`Find`),
Variables: []byte(`{"criteria": {"nationality": "GERMAN" }}`),
Extensions: []byte(`{"persistedQuery": {"version": 1, "sha256Hash": "e33580cf6276de9a75fb3b1c4b7580fec2a1c8facd13f3487bf6c7c3f854f7e3"}}`),
Header: header,
})
require.Equal(t, 200, res.Response.StatusCode)
require.Equal(t, `{"data":{"findEmployees":[{"id":1,"details":{"forename":"Jens","surname":"Neuse"}},{"id":2,"details":{"forename":"Dustin","surname":"Deus"}},{"id":4,"details":{"forename":"Björn","surname":"Schwenzer"}},{"id":11,"details":{"forename":"Alexandra","surname":"Neuse"}}]}}`, res.Body)
})
})
})

t.Run("parser total fields limit", func(t *testing.T) {
t.Parallel()

t.Run("blocks queries over the limit", func(t *testing.T) {
t.Parallel()
testenv.Run(t, &testenv.Config{
ModifySecurityConfiguration: func(securityConfiguration *config.SecurityConfiguration) {
securityConfiguration.ParserHardLimits = config.ParserHardLimitsConfiguration{
ParserTotalFieldsLimit: 2,
}
},
}, func(t *testing.T, xEnv *testenv.Environment) {
res, _ := xEnv.MakeGraphQLRequest(testenv.GraphQLRequest{
Query: `{ employee(id:1) { id details { forename surname } } }`,
})
require.Equal(t, 400, res.Response.StatusCode)
require.Equal(t, `{"errors":[{"message":"allowed number of fields per GraphQL document of '2' exceeded"}]}`, res.Body)
})
})

t.Run("allows queries under the limit", func(t *testing.T) {
t.Parallel()
testenv.Run(t, &testenv.Config{
ModifySecurityConfiguration: func(securityConfiguration *config.SecurityConfiguration) {
securityConfiguration.ParserHardLimits = config.ParserHardLimitsConfiguration{
ParserTotalFieldsLimit: 6, // fail if count > limit
}
},
}, func(t *testing.T, xEnv *testenv.Environment) {
res, _ := xEnv.MakeGraphQLRequest(testenv.GraphQLRequest{
Query: `{ employee(id:1) { id details { forename surname } } }`, // has 5 fields
})
require.Equal(t, 200, res.Response.StatusCode)
require.Equal(t, `{"data":{"employee":{"id":1,"details":{"forename":"Jens","surname":"Neuse"}}}}`, res.Body)
})
})
})
}
6 changes: 2 additions & 4 deletions router/core/cache_warmup.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,15 +305,13 @@ func (c *CacheWarmupPlanningProcessor) ProcessOperation(ctx context.Context, ope
return nil, err
}

// NOTE: we do not validate query complexity here, because queries come from analytics, so they should be valid

_, err = k.Validate(true, k.parsedOperation.RemapVariables, nil)
if err != nil {
return nil, err
}

if c.complexityLimits != nil {
_, _, _ = k.ValidateQueryComplexity(c.complexityLimits, k.kit.doc, c.routerSchema, k.parsedOperation.IsPersistedOperation)
}

planOptions := PlanOptions{
ClientInfo: item.Client,
TraceOptions: resolve.TraceOptions{
Expand Down
2 changes: 2 additions & 0 deletions router/core/graph_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -1202,9 +1202,11 @@ func (s *graphServer) buildGraphMux(
OperationHashCache: gm.operationHashCache,
ParseKitPoolSize: s.engineExecutionConfiguration.ParseKitPoolSize,
IntrospectionEnabled: s.Config.introspection,
ParserHardLimits: s.Config.securityConfiguration.ParserHardLimits,
ApolloCompatibilityFlags: s.apolloCompatibilityFlags,
ApolloRouterCompatibilityFlags: s.apolloRouterCompatibilityFlags,
DisableExposingVariablesContentOnValidationError: s.engineExecutionConfiguration.DisableExposingVariablesContentOnValidationError,
ComplexityLimits: s.securityConfiguration.ComplexityLimits,
})
operationPlanner := NewOperationPlanner(executor, gm.planCache)

Expand Down
43 changes: 22 additions & 21 deletions router/core/graphql_prehandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -897,6 +897,28 @@ func (h *PreHandler) handleOperation(req *http.Request, variablesParser *astjson
trace.WithSpanKind(trace.SpanKindInternal),
trace.WithAttributes(requestContext.telemetry.traceAttrs...),
)

// Validate that the planned query doesn't exceed the maximum query depth configured
// This check runs if they've configured a max query depth, and it can optionally be turned off for persisted operations
if h.complexityLimits != nil {
cacheHit, complexityCalcs, queryDepthErr := operationKit.ValidateQueryComplexity()
engineValidateSpan.SetAttributes(otel.WgQueryDepth.Int(complexityCalcs.Depth))
engineValidateSpan.SetAttributes(otel.WgQueryTotalFields.Int(complexityCalcs.TotalFields))
engineValidateSpan.SetAttributes(otel.WgQueryRootFields.Int(complexityCalcs.RootFields))
engineValidateSpan.SetAttributes(otel.WgQueryRootFieldAliases.Int(complexityCalcs.RootFieldAliases))
engineValidateSpan.SetAttributes(otel.WgQueryDepthCacheHit.Bool(cacheHit))
if queryDepthErr != nil {
rtrace.AttachErrToSpan(engineValidateSpan, err)

requestContext.operation.validationTime = time.Since(startValidation)
httpOperation.traceTimings.EndValidate()

engineValidateSpan.End()

return queryDepthErr
}
}

validationCached, err := operationKit.Validate(requestContext.operation.executionOptions.SkipLoader, requestContext.operation.remapVariables, h.apolloCompatibilityFlags)
if err != nil {
rtrace.AttachErrToSpan(engineValidateSpan, err)
Expand All @@ -921,27 +943,6 @@ func (h *PreHandler) handleOperation(req *http.Request, variablesParser *astjson
engineValidateSpan.SetAttributes(otel.WgVariablesValidationSkipped.Bool(true))
}

// Validate that the planned query doesn't exceed the maximum query depth configured
// This check runs if they've configured a max query depth, and it can optionally be turned off for persisted operations
if h.complexityLimits != nil {
cacheHit, complexityCalcs, queryDepthErr := operationKit.ValidateQueryComplexity(h.complexityLimits, operationKit.kit.doc, h.executor.RouterSchema, operationKit.parsedOperation.IsPersistedOperation)
engineValidateSpan.SetAttributes(otel.WgQueryDepth.Int(complexityCalcs.Depth))
engineValidateSpan.SetAttributes(otel.WgQueryTotalFields.Int(complexityCalcs.TotalFields))
engineValidateSpan.SetAttributes(otel.WgQueryRootFields.Int(complexityCalcs.RootFields))
engineValidateSpan.SetAttributes(otel.WgQueryRootFieldAliases.Int(complexityCalcs.RootFieldAliases))
engineValidateSpan.SetAttributes(otel.WgQueryDepthCacheHit.Bool(cacheHit))
if queryDepthErr != nil {
rtrace.AttachErrToSpan(engineValidateSpan, err)

requestContext.operation.validationTime = time.Since(startValidation)
httpOperation.traceTimings.EndValidate()

engineValidateSpan.End()

return queryDepthErr
}
}

requestContext.operation.validationTime = time.Since(startValidation)
httpOperation.traceTimings.EndValidate()

Expand Down
40 changes: 34 additions & 6 deletions router/core/operation_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ type OperationProcessorOptions struct {
ApolloCompatibilityFlags config.ApolloCompatibilityFlags
ApolloRouterCompatibilityFlags config.ApolloRouterCompatibilityFlags
DisableExposingVariablesContentOnValidationError bool
ParserHardLimits config.ParserHardLimitsConfiguration
ComplexityLimits *config.ComplexityLimits
}

// OperationProcessor provides shared resources to the parseKit and OperationKit.
Expand All @@ -127,6 +129,8 @@ type OperationProcessor struct {
parseKitSemaphore chan int
introspectionEnabled bool
parseKitOptions *parseKitOptions
parserHardLimits config.ParserHardLimitsConfiguration
complexityLimits *config.ComplexityLimits
}

// parseKit is a helper struct to parse, normalize and validate operations
Expand Down Expand Up @@ -522,7 +526,16 @@ func (o *OperationKit) Parse() error {

report := &operationreport.Report{}
o.kit.doc.Input.ResetInputString(o.parsedOperation.Request.Query)
o.kit.parser.Parse(o.kit.doc, report)
if _, err := o.kit.parser.ParseWithLimits(
astparser.TokenizerLimits{
Comment thread
devsergiy marked this conversation as resolved.
Outdated
MaxDepth: o.operationProcessor.parserHardLimits.ApproximateDepthLimit,
MaxFields: o.operationProcessor.parserHardLimits.ParserTotalFieldsLimit,
}, o.kit.doc, report); err != nil {
return &httpGraphqlError{
message: err.Error(),
statusCode: http.StatusBadRequest,
}
}
if report.HasErrors() {
return &reportError{
report: report,
Expand Down Expand Up @@ -750,7 +763,16 @@ func (o *OperationKit) setAndParseOperationDoc() error {
o.kit.doc.Input.ResetInputString(o.parsedOperation.NormalizedRepresentation)
o.kit.doc.Input.Variables = o.parsedOperation.Request.Variables
report := &operationreport.Report{}
o.kit.parser.Parse(o.kit.doc, report)
if _, err := o.kit.parser.ParseWithLimits(
astparser.TokenizerLimits{
Comment thread
devsergiy marked this conversation as resolved.
Outdated
MaxDepth: o.operationProcessor.parserHardLimits.ApproximateDepthLimit,
MaxFields: o.operationProcessor.parserHardLimits.ParserTotalFieldsLimit,
}, o.kit.doc, report); err != nil {
return &httpGraphqlError{
message: err.Error(),
statusCode: http.StatusBadRequest,
}
}
if report.HasErrors() {
return &reportError{
report: report,
Expand Down Expand Up @@ -1076,15 +1098,19 @@ func (o *OperationKit) Validate(skipLoader bool, remapVariables map[string]strin
}

// ValidateQueryComplexity validates that the query complexity is within the limits set in the configuration
func (o *OperationKit) ValidateQueryComplexity(complexityLimitConfig *config.ComplexityLimits, operation, definition *ast.Document, isPersisted bool) (bool, ComplexityCacheEntry, error) {
func (o *OperationKit) ValidateQueryComplexity() (ok bool, cacheEntry ComplexityCacheEntry, err error) {
if o.operationProcessor.complexityLimits == nil {
return true, ComplexityCacheEntry{}, nil
}

if o.cache != nil && o.cache.complexityCache != nil {
if cachedComplexity, ok := o.cache.complexityCache.Get(o.parsedOperation.InternalID); ok {
return ok, cachedComplexity, o.runComplexityComparisons(complexityLimitConfig, cachedComplexity, isPersisted)
return ok, cachedComplexity, o.runComplexityComparisons(o.operationProcessor.complexityLimits, cachedComplexity, o.parsedOperation.IsPersistedOperation)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
}
}

report := operationreport.Report{}
globalComplexityResult, rootFieldStats := operation_complexity.CalculateOperationComplexity(operation, definition, &report)
globalComplexityResult, rootFieldStats := operation_complexity.CalculateOperationComplexity(o.kit.doc, o.operationProcessor.executor.ClientSchema, &report)
cacheResult := ComplexityCacheEntry{
Depth: globalComplexityResult.Depth,
TotalFields: globalComplexityResult.NodeCount,
Expand All @@ -1101,7 +1127,7 @@ func (o *OperationKit) ValidateQueryComplexity(complexityLimitConfig *config.Com
o.cache.complexityCache.Set(o.parsedOperation.InternalID, cacheResult, 1)
}

return false, cacheResult, o.runComplexityComparisons(complexityLimitConfig, cacheResult, isPersisted)
return false, cacheResult, o.runComplexityComparisons(o.operationProcessor.complexityLimits, cacheResult, o.parsedOperation.IsPersistedOperation)
}

func (o *OperationKit) runComplexityComparisons(complexityLimitConfig *config.ComplexityLimits, cachedComplexity ComplexityCacheEntry, isPersisted bool) error {
Expand Down Expand Up @@ -1219,6 +1245,8 @@ func NewOperationProcessor(opts OperationProcessorOptions) *OperationProcessor {
parseKits: make(map[int]*parseKit, opts.ParseKitPoolSize),
parseKitSemaphore: make(chan int, opts.ParseKitPoolSize),
introspectionEnabled: opts.IntrospectionEnabled,
parserHardLimits: opts.ParserHardLimits,
complexityLimits: opts.ComplexityLimits,
parseKitOptions: &parseKitOptions{
apolloCompatibilityFlags: opts.ApolloCompatibilityFlags,
apolloRouterCompatibilityFlags: opts.ApolloRouterCompatibilityFlags,
Expand Down
6 changes: 6 additions & 0 deletions router/core/websocket.go
Original file line number Diff line number Diff line change
Expand Up @@ -894,6 +894,12 @@ func (h *WebSocketConnectionHandler) parseAndPlan(registration *SubscriptionRegi

startValidation := time.Now()

_, _, err = operationKit.ValidateQueryComplexity()
if err != nil {
opContext.validationTime = time.Since(startValidation)
return nil, nil, err
}

if _, err := operationKit.Validate(h.plannerOptions.ExecutionOptions.SkipLoader, opContext.remapVariables, &h.apolloCompatibilityFlags); err != nil {
opContext.validationTime = time.Since(startValidation)
return nil, nil, err
Expand Down
2 changes: 1 addition & 1 deletion router/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ require (
github.com/tidwall/gjson v1.18.0
github.com/tidwall/sjson v1.2.5
github.com/twmb/franz-go v1.16.1
github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.207
github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.208
// Do not upgrade, it renames attributes we rely on
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1
go.opentelemetry.io/contrib/propagators/b3 v1.23.0
Expand Down
4 changes: 2 additions & 2 deletions router/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -290,8 +290,8 @@ github.com/vektah/gqlparser/v2 v2.5.16 h1:1gcmLTvs3JLKXckwCwlUagVn/IlV2bwqle0vJ0
github.com/vektah/gqlparser/v2 v2.5.16/go.mod h1:1lz1OeCqgQbQepsGxPVywrjdBHW2T08PUS3pJqepRww=
github.com/wundergraph/astjson v0.0.0-20250106123708-be463c97e083 h1:8/D7f8gKxTBjW+SZK4mhxTTBVpxcqeBgWF1Rfmltbfk=
github.com/wundergraph/astjson v0.0.0-20250106123708-be463c97e083/go.mod h1:eOTL6acwctsN4F3b7YE+eE2t8zcJ/doLm9sZzsxxxrE=
github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.207 h1:g2MpMjU/Jk30oBzfBjGRgH3EzTvwI0IV57HhlUjeyZc=
github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.207/go.mod h1:DaBrBCMgKGd3t7zg7z11jKm+0mVJiesr/IQCRG9qgP0=
github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.208 h1:dnWJ/nv+M2SF9aZnHXPU+gfSiANC7eAOSM4HU6ymc74=
github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.208/go.mod h1:DaBrBCMgKGd3t7zg7z11jKm+0mVJiesr/IQCRG9qgP0=
github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M=
Expand Down
18 changes: 12 additions & 6 deletions router/pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -399,12 +399,18 @@ type BlockOperationConfiguration struct {
}

type SecurityConfiguration struct {
BlockMutations BlockOperationConfiguration `yaml:"block_mutations" envPrefix:"SECURITY_BLOCK_MUTATIONS_"`
BlockSubscriptions BlockOperationConfiguration `yaml:"block_subscriptions" envPrefix:"SECURITY_BLOCK_SUBSCRIPTIONS_"`
BlockNonPersistedOperations BlockOperationConfiguration `yaml:"block_non_persisted_operations" envPrefix:"SECURITY_BLOCK_NON_PERSISTED_OPERATIONS_"`
ComplexityCalculationCache *ComplexityCalculationCache `yaml:"complexity_calculation_cache"`
ComplexityLimits *ComplexityLimits `yaml:"complexity_limits"`
DepthLimit *QueryDepthConfiguration `yaml:"depth_limit"`
BlockMutations BlockOperationConfiguration `yaml:"block_mutations" envPrefix:"SECURITY_BLOCK_MUTATIONS_"`
BlockSubscriptions BlockOperationConfiguration `yaml:"block_subscriptions" envPrefix:"SECURITY_BLOCK_SUBSCRIPTIONS_"`
BlockNonPersistedOperations BlockOperationConfiguration `yaml:"block_non_persisted_operations" envPrefix:"SECURITY_BLOCK_NON_PERSISTED_OPERATIONS_"`
ComplexityCalculationCache *ComplexityCalculationCache `yaml:"complexity_calculation_cache"`
ComplexityLimits *ComplexityLimits `yaml:"complexity_limits"`
DepthLimit *QueryDepthConfiguration `yaml:"depth_limit"`
ParserHardLimits ParserHardLimitsConfiguration `yaml:"parser_hard_limits"`
Comment thread
devsergiy marked this conversation as resolved.
Outdated
}

type ParserHardLimitsConfiguration struct {
ApproximateDepthLimit int `yaml:"approximate_depth_limit,omitempty" envDefault:"100"`
ParserTotalFieldsLimit int `yaml:"parser_total_fields_limit,omitempty" envDefault:"500"`
}

type QueryDepthConfiguration struct {
Expand Down
Loading
Loading