Transform to GraphQL requests
Overview
Relixy can rewrite the URL, body and headers from RESTful to GraphQL requests before forwarding them to the upstream and
rewrite responses before returning them to the client. Transformations are configured per-operation using the
x-rely-proxy-action vendor extension on an OpenAPI operation object.
The extension accepts one object with a type field plus optional request and response sections.
| Field | Required | Description |
|---|---|---|
type | Yes | Always graphql for GraphQL operations. |
request | No | Transformation applied to the outgoing request. |
response | No | Transformation applied to the incoming response. |
Transformation
Example
The following example shows an operation that:
- Rewrites the upstream path and transforms variables in the path template.
- Adds custom header derived from a path parameter.
- Transforms the request body to a different shape.
- Transforms the response to a different shape.
paths:
/characters/{id}:
get:
operationId: getCharacterById
description: "Get character by ID"
x-rely-proxy-action:
type: graphql
request:
url: "/graphql"
headers:
X-User-Id:
path: "param.id"
X-Query-Filter:
path: "query.filter"
X-Content-Type:
path: 'headers."content-type"'
query: |
query Character($id: ID!) {
character(id: $id) {
id
name
}
}
variables:
id:
type: field
path: param.id
extensions:
someExtension:
type: field
default:
value: someValue
response:
contentType: application/json
httpErrorCode: 400
body:
type: gotmpl
template: |
{
"id": "{{.body.account_id}}",
"displayName": "{{.body.display_name}}",
"email": "{{.body.contact.email}}"
}
Request
GraphQL query
The GraphQL query is mandatory for GraphQL requests. Variables in the query string are parsed and replaced with request parameters in the runtime. You can also define selection queries for variables.
x-rely-proxy-action:
type: graphql
request:
query: |
query Character($id: ID!) {
character(id: $id) {
id
name
}
}
Transform GraphQL variables
Variables are an object with selection fields that use JMESPath expression to select them from
the request. In this example, the $id variable is selected from the id parameter in the request path.
x-rely-proxy-action:
type: graphql
request:
variables:
id:
type: field
path: param.id
The available input object for JMESPath expressions:
| Key | Type | Description |
|---|---|---|
param | object | Path parameters (e.g., param.id for {id}) |
query | object | Query string parameters |
headers | object | Request headers (keys are lowercased) |
body | any | Parsed request body. |
Override the request URL
Use request.url to replace the upstream URL. In most cases, you don't need to override the URL because the graphql URL
is fixed. Setting the server URL is enough.
x-rely-proxy-action:
type: graphql
request:
url: "/graphql"
Transform headers
Use request.headers to add or override headers on the upstream request. Values are JMESPath
expressions evaluated against the request data.
x-rely-proxy-action:
type: graphql
request:
headers:
X-User-Id:
path: "param.id"
X-Query-Filter:
path: "query.filter"
X-Content-Type:
path: 'headers."content-type"'
The available input object for JMESPath expressions:
| Key | Type | Description |
|---|---|---|
param | object | Path parameters (e.g., param.id for {id}) |
query | object | Query string parameters |
headers | object | Request headers (keys are lowercased) |
body | any | Parsed request body |
Transform request extensions
You can define optional extensions for GraphQL requests via the request.extensions object. Similar to variables, are
an object with selection fields that use JMESPath expression to select them from the request.
x-rely-proxy-action:
type: graphql
request:
extensions:
someExtension:
type: field
default:
value: someValue
Response
Transform the response body
Use response.body with a Go template to rewrite the response body returned to the client.
x-rely-proxy-action:
type: graphql
response:
contentType: application/json
body:
type: gotmpl
template: |
{
"id": "{{.body.account_id}}",
"displayName": "{{.body.display_name}}",
"email": "{{.body.contact.email}}"
}
The template context for response transformations is the parsed JSON response body from the upstream, accessible as
.body.
Transform HTTP status on error
GraphQL generally returns HTTP 200 status when errors happened. It causes confusion for users because the RESTful
specification expects HTTP status to be 400 or larger. You can use response.httpErrorCode field to configure the
default expected status for error responses.
x-rely-proxy-action:
type: graphql
response:
httpErrorCode: 400
You can indicate specific HTTP statuses for individual errors with evaluation rules that uses
JMESPath expressions. If all rules aren't matched those expressions, the engine falls back to
the default httpErrorCode.
x-rely-proxy-action:
type: graphql
response:
httpErrorCode: 400
httpErrors:
"404":
- 'errors[0].extensions.code == "NOT_FOUND"'
- 'errors[0].message == "Not found"'
For example, if the response body of GraphQL has NOT_FOUND code in extensions of the first error item, the response
status will be transformed to 404 Not Found.
{
"errors": [
{
"message": "User not found",
"locations": [{ "line": 2, "column": 3 }],
"extensions": {
"code": "NOT_FOUND"
}
}
]
}