This page applies to Apigee and Apigee hybrid.
View Apigee Edge documentation.
What
The GraphQL policy can parse GraphQL payloads into message flow variables, verify GraphQL requests against a schema, or both.
You can use the GraphQL policy to:
- Ensure that your APIs only process requests that conform to the schema you provide.
- Impose restrictions on the payload by setting a maximum on the number of fragments allowed.
- Associate GraphQL with API products.
- Leverage the Oauth2, VerifyAPIKey, and Quota policy features, just as in REST.
GraphQL supports the following types of payloads:
- POST of graphQL payloads with
Content-Type : application/graphql
- POST of graphQL payloads with
Content-Type: applcation/json
- GET of graphQL payloads where the payload is a query parameter
For more information, see the following resources:
This policy is a Standard policy and can be deployed to any environment type. For information on policy types and availability with each environment type, see Policy types.
See Using GraphQL for an example that uses this policy.
<GraphQL>
element
Defines a <GraphQL>
policy.
Default value | See Default Policy tab, below |
Required? | Required |
Type | TYPE |
Parent Element | n/a |
Child Elements | <Action> <MaxDepth> <MaxCount> <MaxPayloadSizeInBytes> <OperationType> <Source> <ResourceURL> |
Syntax
The <GraphQL>
element uses the following syntax:
<GraphQL continueOnError="[false|true]" enabled="[true|false]" name="POLICY_NAME" > <Source>request</Source> <OperationType>[query|mutuation|all]</OperationType> <MaxDepth>MAX_DEPTH</MaxDepth> <MaxCount>MAX_NUMBER_OF_QUERIES</MaxCount> // [Start maxpayloadsize] <MaxPayloadSizeInBytes>MAX_PAYLOAD_SIZE_IN_BYTES</MaxPayloadSizeInBytes> <Action>parse</Action> <ResourceURL>PATH/TO/SCHEMA.xsd</ResourceURL> </GraphQL>
Default Policy
The following example shows the default settings when you add a <GraphQL>
policy
to your flow in the Apigee UI:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <GraphQL name="GraphQLParser"> <Source>request</Source> <OperationType>query</OperationType> <MaxDepth>10</MaxDepth> <MaxCount>10</MaxCount> <MaxPayloadSizeInBytes></MaxPayloadSizeInBytes> <Action>parse</Action> <ResourceURL></ResourceURL> </GraphQL>
This element has the following attributes that are common to all policies:
Attribute | Default | Required? | Description |
---|---|---|---|
name |
N/A | Required |
The internal name of the policy. The value of the Optionally, use the |
continueOnError |
false | Optional | Set to false to return an error when a policy fails. This is expected behavior for
most policies. Set to true to have flow execution continue even after a policy
fails. See also:
|
enabled |
true | Optional | Set to true to enforce the policy. Set to false to turn off the
policy. The policy will not be enforced even if it remains attached to a flow. |
async |
false | Deprecated | This attribute is deprecated. |
The following table provides a high-level description of the child elements of
<GraphQL>
:
Child Element | Required? | Description |
---|---|---|
Common operations | ||
<Action> |
Optional | Specifies the action to take for a request: parse , verify , or
parse_verify (both).
|
<MaxCount> |
Optional | The maximum number of queries or fragments that a GraphQL request can spawn. The default value is 10. |
<MaxDepth> |
Optional | The maximum depth of the tree for the query. The default value is 4. |
<MaxPayloadSizeInBytes> |
Optional | The maximum size of a payload in kilobytes. |
<OperationType> |
Required | Specifies the type of request that can be parsed: query ,
mutation , or query_mutation (either). |
<ResourceURL> |
Optional | DESCRIPTION. The location of the GraphQL schema file. |
<Source> |
Required | request |
Each of these child elements is described in the sections that follow.
Child element reference
This section describes the child elements of <GraphQL>
.
<Action>
Action represents one of the following GraphQL actions:
parse
: Apigee parses the GraphQL payload into message flow variables. See Examples of message flow variable representations for an explanation of the variables that are set whenAction
is set toparse
. This can save valuable CPU time in the backend. Note thatverify
also parses the payload.verify
: Apigee verifies that the GraphQL payload conforms to the schema uploaded to the proxy.parse_verify
: Apigee parses and verifies the GraphQL request.
Default value | parse |
Required? | Optional |
Type | String |
Parent Element | <GraphQL> |
Child Elements | none |
The <Action>
element uses the following syntax:
Syntax
<GraphQL continueOnError="[false|true]" enabled="[true|false]" name="POLICY_NAME" > <Action>parse</Action> </GraphQL>
<MaxCount>
The maximum number of fragments that can be in the payload. You can use this to prevent the GraphQL back-end server of the customer from executing highly complex queries, forcing clients to break their logic in to smaller payloads.
Default value | 10 |
Required? | Optional |
Type | String |
Parent Element | <GraphQL> |
Child Elements | none |
The <MaxCount>
element uses the following syntax:
Syntax
<GraphQL continueOnError="[false|true]" enabled="[true|false]" name="POLICY_NAME" > <MaxCount>MAX_NUMBER_OF_QUERIES</MaxCount> </GraphQL>
<MaxDepth>
The maximum depth of the query, when represented as a tree.
MaxDepth
allows you to block deep queries in the payload,
so that Apigee does not need to create very large flow variables to hold the values.
However, the payload is sent as is, regardless of the value of MaxDepth
.
The default value is 10.
Default value | 10 |
Required? | Optional |
Type | Integer |
Parent Element | <GraphQL> |
Child Elements | none |
The <MaxDepth>
element uses the following syntax:
Syntax
<GraphQL continueOnError="[false|true]" enabled="[true|false]" name="POLICY_NAME" > <MaxDepth>MAX_DEPTH</MaxDepth> </GraphQL>
<MaxPayloadSizeInBytes>
The maximum size of a payload in kilobytes. You can use this to limit the payload size, to avoid performance issues.
Note: If MaxPayloadSizeInByte
is not provided in the policy,
no size restriction is enforced.
Default value | request |
Required? | Optional |
Type | String |
Parent Element | <GraphQL> |
Child Elements | none |
The <MaxPayloadSizeInBytes>
element uses the following syntax:
Syntax
<GraphQL continueOnError="[false|true]" enabled="[true|false]" name="POLICY_NAME" > <MaxPayloadSizeInBytes>MAX_PAYLOAD_SIZE_IN_BYTES</MaxPayloadSizeInBytes> </GraphQL>
<OperationType>
Indicates the type of request that can be parsed:
query
: A GraphQL query.mutation
: A GraphQL mutationquery_mutation
: A GraphQL query or a mutation.
If the scope is query
, and a mutation request is passed, the request fails
and returns a 4xx
error.
Default value | query |
Required? | Optional |
Type | String |
Parent Element | <GraphQL> |
Child Elements | none |
The <OperationType>
element uses the following syntax:
Syntax
<GraphQL continueOnError="[false|true]" enabled="[true|false]" name="POLICY_NAME" > <OperationType>[query|mutation|query_mutation]</OperationType> </GraphQL>
<ResourceURL>
The path to the GraphQL schema file that the GraphQL policy verifies requests against. See Example for an example of uploading a GraphQL schema to Apigee.
If the name of your uploaded schema file is my-schema.graphql
, then the
<ResourceURL>
element would be
<ResourceURL>graphql://my-schema.graphql</ResourceURL>
Default value | n/a |
Required? | Optional |
Type | String |
Parent Element | <GraphQL> |
Child Elements | none |
The ResourceURL
element uses the following syntax:
Syntax
<GraphQL continueOnError="[false|true]" enabled="[true|false]" name="POLICY_NAME" > <ResourceURL>PATH/TO/SCHEMA.graphql</ResourceURL> </GraphQL>
<Source>
Source on which this policy executes.
Default value | request |
Required? | Optional |
Type | String |
Parent Element | <GraphQL> |
Child Elements | none |
The <Source>
element uses the following syntax:
Syntax
<GraphQL continueOnError="[false|true]" enabled="[true|false]" name="POLICY_NAME" > <Source>request</Source> </GraphQL>
GraphQL Parser
The graphQL parser supports all features of a graphQL query and represents it as a graph in the message flow dotted notation. A query can comprise of operation definition and optionally fragments identified as fragment definitions. See the GraphQL specification.
Anatomy of a graphQL request
The diagram below shows the anatomy of a graphQL request.
Representation in message flow of operation definitions
The parser implementation covers all aspects of graphQL syntax, including support for query and mutations. See Message flow variable.
The message flow variables follows this convention:
graphql.(root-index).(root definition)[(sub-indices).(child-definitions)…]
where:
graphql
: Static prefix indicating this is graphQL related message flow variablesroot-Index
: based index indicating the root level query definitions index (default up to 4 per request)root-definition
: Root level graphQL request message body, args, its valuessub-indices
: Child indiceschild-definitions
: Leaf level definitions that correlate to specific fields and its values
Representation in message flow variable of operation definitions
Fields in message | Type | Description |
---|---|---|
name | String | Name of the graphQL operation. Note that this name is unrelated to the name in message flow. |
definition | String - Operation | Indicates that this contains the main message body of the query request |
operationType | query or mutation | The type of operation being performed. |
variableDefinition | Integer | They work just like the argument definitions for a function in a typed language. It lists all of the variables, prefixed by $, followed by their type. |
directives | Integer | @include and @skip are the two directives currently offered, that can filter based on dynamically passed values. |
selectionSet | Integer | One level logical grouping of all attributes associated with an object. |
Representation in message flow of fragment definitions
Message Flow Variable Name | Type | Description |
---|---|---|
name | String | Name of the fragment. |
definition | String- fragment | Indicates that the body of the request is a fragment to the main request. |
typeCondition | String | The condition under which the fragment gets invoked. |
variableDefinition | Integer | The variables definition passed as arguments to the fragment. |
Examples of message flow variable representations
The following examples show the message flow variable representations for sample request payloads.
Sample query 1
This example shows a query made with arguments passed as input, which queries for three attributes for employees.
{ employee(id: 123) { id firstName lastName } }
The table shows the corresponding message flow variable representations.
Message flow variable | Value |
---|---|
graphql.operation.operationType |
QUERY |
graphql.fragment.count |
1 |
graphql.operation.selectionSet.count |
1 |
graphql.operation.variableDefinitions.count |
0 |
graphql.operation.selectionSet.1.name |
employee |
graphql.operation.selectionSet.1.argument.count |
1 |
graphql.operation.selectionSet.1.argument.1.name |
id |
graphql.operation.selectionSet.1.argument.1.value |
IntValue{value=123} |
graphql.operation.selectionSet.1.directive.count |
0 |
graphql.operation.selectionSet.1.selectionSet.count |
3 |
graphql.operation.selectionSet.1.selectionSet.1.name |
id |
graphql.operation.selectionSet.1.selectionSet.2.name |
firstName |
graphql.operation.selectionSet.1.selectionSet.3.name |
lastName |
Sample query 2
This example shows a query made with arguments passed as input, which queries for the names of friends.
query Characters($episode: Episode, $withFriends: Boolean!) { friends @include(if: $withFriends) { friendsName } }
The table below shows the corresponding message flow variable representations.
Message flow variable | Value |
---|---|
graphql.operation.operationType |
QUERY |
graphql.operation.selectionSet.count |
1 |
graphql.operation.name |
Characters |
graphql.fragment.count |
0 |
graphql.operation.selectionSet.1.name |
friends |
graphql.operation.variableDefinitions.count |
2 |
graphql.operation.variableDefinitions.1.name |
episode |
graphql.operation.variableDefinitions.1.type |
TypeName{name='Episode'} |
graphql.operation.variableDefinitions.2.name |
withFriends |
graphql.operation.variableDefinitions.2.type |
NonNullType{type=TypeName{name='Boolean'}} |
graphql.operation.selectionSet.1.argument.count |
0 |
graphql.operation.selectionSet.1.selectionSet.count |
1 |
graphql.operation.selectionSet.1.selectionSet.1.name |
friendsName |
graphql.operation.selectionSet.1.directive.count |
1 |
graphql.operation.selectionSet.1.directive.1.argument.1.name |
if |
graphql.operation.selectionSet.1.directive.1.argument.1.value |
VariableReference{name='withFriends'} |
Sample query 3
This example has a variable definition with alias.
query getUsers { admins: users(role: ADMIN) { lastName } accountants: users(role: ACCOUNTANT) { firstName } }
The table below shows the corresponding message flow variable representations.
Message flow variable | Value |
---|---|
graphql.operation.operationType |
QUERY |
graphql.operation.selectionSet.count |
2 |
graphql.operation.selectionSet.1.name |
users |
graphql.operation.selectionSet.1.alias |
admins |
graphql.operation.variableDefinitions.count |
0 |
graphql.operation.selectionSet.1.argument.count |
1 |
graphql.operation.selectionSet.1.argument.1.name |
role |
graphql.operation.selectionSet.1.argument.1.value |
EnumValue{name='ADMIN'} |
graphql.operation.selectionSet.1.argument.2.name |
null |
graphql.operation.selectionSet.1.argument.2.value |
null |
graphql.operation.selectionSet.1.selectionSet.count |
1 |
graphql.operation.selectionSet.1.selectionSet.count |
1 |
graphql.operation.selectionSet.1.selectionSet.1.name |
lastName |
graphql.operation.selectionSet.1.selectionSet.1.alias |
null |
graphql.operation.selectionSet.1.selectionSet.2.name |
null |
graphql.operation.selectionSet.1.selectionSet.2.alias |
null |
graphql.operation.selectionSet.1.directive.count |
0 |
graphql.operation.selectionSet.1.directive.1.argument.1.name |
null |
graphql.operation.selectionSet.1.directive.1.argument.1.value |
null |
graphql.operation.selectionSet.2.name |
users |
graphql.operation.selectionSet.2.alias |
accountants |
graphql.operation.selectionSet.2.argument.count |
1 |
graphql.operation.selectionSet.2.argument.1.name |
role |
graphql.operation.selectionSet.2.argument.1.value |
EnumValue{name='ACCOUNTANT'} |
graphql.operation.selectionSet.2.selectionSet.count |
1 |
graphql.operation.selectionSet.2.selectionSet.1.name |
firstName |
graphql.operation.selectionSet.2.directive.count |
0 |
graphql.operation.selectionSet.2.selectionSet.1.alias |
null |
graphql.operation.selectionSet.2.selectionSet.2.name |
null |
graphql.operation.selectionSet.2.selectionSet.2.alias |
null |
graphql.operation.selectionSet.2.directive.count |
0 |