Persisting GraphQL queries
Tyk Gateway 4.3.0
release includes a way to expose GraphQL queries as REST endpoints. For now, this can only be configured via the raw API definition, Tyk Dashboard support is coming soon.
How to persist GraphQL query
The ability to expose a GraphQL query as a REST endpoint can be enabled by adding the persist_graphql
section of the extended_paths
on any API version you intend to be used to serve as the GraphQL query to REST endpoint proxy.
Here is a sample REST API proxy:
{
"name": "Persisted Query API",
"api_id": "trevorblades",
"org_id": "default",
"use_keyless": true,
"enable_context_vars": true,
"definition": {
"location": "header",
"key": "x-api-version"
},
"proxy": {
"listen_path": "/trevorblades/",
"target_url": "https://countries.trevorblades.com",
"strip_listen_path": true
}
}
The target URL should point to a GraphQL upstream although this is a REST proxy. This is important for the feature to work.
Adding versions
On its own, this isn’t particularly remarkable. To enable GraphQL to REST middleware, modify the Default version like so:
{
"name": "Persisted Query API",
"definition": {
"location": "header",
"key": "x-api-version"
},
...
"version_data": {
"not_versioned": true,
"default_version": "",
"versions": {
"Default": {
"name": "Default",
"expires": "",
"paths": {
"ignored": [],
"white_list": [],
"black_list": []
},
"use_extended_paths": true,
"global_headers": {},
"global_headers_remove": [],
"global_response_headers": {},
"global_response_headers_remove": [],
"ignore_endpoint_case": false,
"global_size_limit": 0,
"override_target": "",
"extended_paths": {
"persist_graphql": [
{
"method": "GET",
"path": "/getContinentByCode",
"operation": "query ($continentCode: ID!) {\n continent(code: $continentCode) {\n code\n name\n countries {\n name\n }\n }\n}",
"variables": {
"continentCode": "EU"
}
}
]
}
}
}
}
}
The vital part of this is the extended_paths.persist_graphql
field. The persist_graphql
object consists of three fields:
method
: The HTTP method used to access that endpoint, in this example, any GET requests to <PROXY ENDPOINT>/getContinentByCode
will be handled by the persist graphql middleware
path
: The path the middleware listens to
operation
: This is the GraphQL operation (query
in this case) that is sent to the upstream.
variables
: A list of variables that should be included in the upstream request.
If you run a request to your proxy, you should get a response similar to this:
{
"data": {
"continent": {
"code": "EU",
"name": "Europe",
"countries": [
{
"name": "Andorra"
},
...
]
}
}
}
Dynamic variables
We have seen support for passing static variable values via the API definition, but there will be cases where we want to extract variables from the request header or URL. More information about available request context variables in Tyk can be found [here]({{(< ref “/context-variables”>)}})
Below is an examples of using an incoming code
header value as a variable in persist_graphql
middleware configuration:
{
"method": "GET",
"path": "/getCountryByCode",
"operation": "query ($countryCode: ID!) {\n country(code: $countryCode) {\n code\n name\n }\n}",
"variables": {
"countryCode": "$tyk_context.headers_Code"
}
}
Making a request to that endpoint and providing header "code": "UK"
, should result in a response similar to this:
{
"data": {
"country": {
"code": "UK",
"name": "United Kingdom"
}
}
}
Similarly, you can also pass variables in the request URL. Modify your persist_graphql
block to this:
{
"method": "GET",
"path": "/getCountryByCode/{countryCode}",
"operation": "query ($countryCode: ID!) {\n country(code: $countryCode) {\n code\n name\n }\n}",
"variables": {
"countryCode": "$path.countryCode"
}
}
If you now make a request to /getCountryByCode/NG
you should get a result similar to this:
{
"data": {
"country": {
"code": "NG",
"name": "Nigeria"
}
}
}