Coprocessor Reference


Property reference

Table of coprocessor request properties.

Property / Type Description
Control properties
control
string | object
Indicates whether the router should continue processing the current client request. In coprocessor request bodies from the router, this value is always the string value continue.In your coprocessor's response, you can instead return an object with the following format:
JSON
1{ "break": 400 }
If you do this, the router terminates the request-handling lifecycle and immediately responds to the client with the provided HTTP code and response body you specify.For details, see Terminating a client request.
id
string
A unique ID corresponding to the client request associated with this coprocessor request.Do not return a different value for this property. If you do, the router treats the coprocessor request as if it failed.
subgraphRequestId
string
A unique ID corresponding to the subgraph request associated with this coprocessor request (only available at the SubgraphRequest and SubgraphResponse stages).Do not return a different value for this property. If you do, the router treats the coprocessor request as if it failed.
stage
string
Indicates which stage of the router's request-handling lifecycle this coprocessor request corresponds to.This value is one of the following:
  • RouterRequest: The RouterService has just received a client request.
  • RouterResponse: The RouterService is about to send response data to a client.
  • SupergraphRequest: The SupergraphService is about to send a GraphQL request.
  • SupergraphResponse: The SupergraphService has just received a GraphQL response.
  • SubgraphRequest: The SubgraphService is about to send a request to a subgraph.
  • SubgraphResponse: The SubgraphService has just received a subgraph response.
Do not return a different value for this property. If you do, the router treats the coprocessor request as if it failed.
version
number
Indicates which version of the coprocessor request protocol the router is using.Currently, this value is always 1.Do not return a different value for this property. If you do, the router treats the coprocessor request as if it failed.
Data properties
body
string | object
The body of the corresponding request or response.This field is populated when the underlying HTTP method is POST. If you are looking for operation data on GET requests, that info will be populated in the path parameter per the GraphQL over HTTP spec.If your coprocessor returns a different value for body, the router replaces the existing body with that value. This is common when terminating a client request.This field's type depends on the coprocessor request's stage:
  • For SubgraphService stages, body is a JSON object.
  • For SupergraphService stages, body is a JSON object.
  • For RouterService stages, body is a JSON string.
    • This is necessary to support handling deferred queries.
    • If you modify body during the RouterRequest stage, the new value must be a valid string serialization of a JSON object. If it isn't, the router detects that the body is malformed and returns an error to the client.
This field's structure depends on whether the coprocessor request corresponds to a request, a standard response, or a response "chunk" for a deferred query:
  • If a request, body usually contains a query property containing the GraphQL query string.
  • If a standard response, body usually contains data and/or errors properties for the GraphQL operation result.
  • If a response "chunk", body contains data for some of the operation fields.
By default, the RouterResponse stage returns redacted errors within the errors field. To process subgraph errors manually in your coprocessor, enable subgraph error inclusion.
context
object
An object representing the router's shared context for the corresponding client request.If your coprocessor returns a different value for context, the router replaces the existing context with that value.
hasNext
bool
When stage is SupergraphResponse, if present and true then there will be subsequent SupergraphResponse calls to the co-processor for each multi-part (@defer/subscriptions) response.
headers
object
An object mapping of all HTTP header names and values for the corresponding request or response.Ensure headers are handled like HTTP headers in general. For example, normalize header case before your coprocessor operates on them.If your coprocessor returns a different value for headers, the router replaces the existing headers with that value.
The router discards any content-length headers sent by coprocessors because incorrect content-length values can lead to HTTP request failures.
method
string
The HTTP method that is used by the request.
path
string
The RouterService or SupergraphService path that this coprocessor request pertains to.
sdl
string
A string representation of the router's current supergraph schema.This value can be very large, so you should avoid including it in coprocessor requests if possible.The router ignores modifications to this value.
serviceName
string
The name of the subgraph that this coprocessor request pertains to.This value is present only for coprocessor requests from the router's SubgraphService.Do not return a different value for this property. If you do, the router treats the coprocessor request as if it failed.
statusCode
number
The HTTP status code returned with a response.
uri
string
When stage is SubgraphRequest, this is the full URI of the subgraph the router will query.
query_plan
string
When stage is ExecutionRequest, this contains the query plan for the client query. It cannot be modified by the coprocessor.

Example requests by stage

RouterRequest

Click to expand
JSON
Example coprocessor request body
1{
2  // Control properties
3  "version": 1,
4  "stage": "RouterRequest",
5  "control": "continue",
6  "id": "1b19c05fdafc521016df33148ad63c1b",
7
8  // Data properties
9  "headers": {
10    "cookie": [
11      "tasty_cookie=strawberry"
12    ],
13    "content-type": [
14      "application/json"
15    ],
16    "host": [
17      "127.0.0.1:4000"
18    ],
19    "apollo-federation-include-trace": [
20      "ftv1"
21    ],
22    "apollographql-client-name": [
23      "manual"
24    ],
25    "accept": [
26      "*/*"
27    ],
28    "user-agent": [
29      "curl/7.79.1"
30    ],
31    "content-length": [
32      "46"
33    ]
34  },
35  "body": "{
36    \"query\": \"query GetActiveUser {\n  me {\n  name\n}\n}\"
37  }",
38  "context": {
39    "entries": {
40      "accepts-json": false,
41      "accepts-wildcard": true,
42      "accepts-multipart": false
43    }
44  },
45  "sdl": "...", // String omitted due to length
46  "path": "/",
47  "method": "POST"
48}

RouterResponse

Click to expand
JSON
1{
2  // Control properties
3  "version": 1,
4  "stage": "RouterResponse",
5  "control": "continue",
6  "id": "1b19c05fdafc521016df33148ad63c1b",
7
8  // Data properties
9  "headers": {
10    "vary": [
11      "origin"
12    ],
13    "content-type": [
14      "application/json"
15    ]
16  },
17  "body": "{
18    \"data\": {
19      \"me\": {
20        \"name\": \"Ada Lovelace\"
21      }
22    }
23  }",
24  "context": {
25    "entries": {
26      "apollo_telemetry::subgraph_metrics_attributes": {},
27      "accepts-json": false,
28      "accepts-multipart": false,
29      "apollo::telemetry::client_name": "manual",
30      "apollo_telemetry::usage_reporting": {
31        "statsReportKey": "# Long\nquery Long{me{name}}",
32        "referencedFieldsByType": {
33          "User": {
34            "fieldNames": [
35              "name"
36            ],
37            "isInterface": false
38          },
39          "Query": {
40            "fieldNames": [
41              "me"
42            ],
43            "isInterface": false
44          }
45        }
46      },
47      "apollo::telemetry::client_version": "",
48      "accepts-wildcard": true
49    }
50  },
51  "statusCode": 200,
52  "sdl": "..." // Omitted due to length
53}

SupergraphRequest

Click to expand
JSON
1{
2  // Control properties
3  "version": 1,
4  "stage": "SupergraphRequest",
5  "control": "continue",
6
7  // Data properties
8  "headers": {
9    "cookie": ["tasty_cookie=strawberry"],
10    "content-type": ["application/json"],
11    "host": ["127.0.0.1:4000"],
12    "apollo-federation-include-trace": ["ftv1"],
13    "apollographql-client-name": ["manual"],
14    "accept": ["*/*"],
15    "user-agent": ["curl/7.79.1"],
16    "content-length": ["46"]
17  },
18  "body": {
19    "query": "query Long {\n  me {\n  name\n}\n}",
20    "operationName": "MyQuery",
21    "variables": {}
22  },
23  "context": {
24    "entries": {
25      "accepts-json": false,
26      "accepts-wildcard": true,
27      "accepts-multipart": false,
28      "this-is-a-test-context": 42
29    }
30  },
31  "serviceName": "service name shouldn't change",
32  "uri": "http://thisurihaschanged"
33}

SupergraphResponse

Click to expand
JSON
1{
2  // Control properties
3  "version": 1,
4  "stage": "SupergraphResponse",
5  "control": {
6    "break": 200
7  },
8
9  // Data properties
10  "body": {
11    "errors": [{ "message": "my error message" }]
12  },
13  "context": {
14    "entries": {
15      "testKey": true
16    }
17  },
18  "headers": {
19    "aheader": ["a value"]
20  }
21}

ExecutionRequest

Click to expand
JSON
1{
2  // Control properties
3  "version": 1,
4  "stage": "ExecutionRequest",
5  "control": "continue",
6
7  // Data properties
8  "headers": {
9    "cookie": ["tasty_cookie=strawberry"],
10    "content-type": ["application/json"],
11    "host": ["127.0.0.1:4000"],
12    "apollo-federation-include-trace": ["ftv1"],
13    "apollographql-client-name": ["manual"],
14    "accept": ["*/*"],
15    "user-agent": ["curl/7.79.1"],
16    "content-length": ["46"]
17  },
18  "body": {
19    "query": "query Long {\n  me {\n  name\n}\n}",
20    "operationName": "MyQuery"
21  },
22  "context": {
23    "entries": {
24      "accepts-json": false,
25      "accepts-wildcard": true,
26      "accepts-multipart": false,
27      "this-is-a-test-context": 42
28    }
29  },
30  "serviceName": "service name shouldn't change",
31  "uri": "http://thisurihaschanged",
32  "queryPlan": {
33    "usage_reporting": {
34      "statsReportKey": "# Me\nquery Me{me{name username}}",
35      "referencedFieldsByType": {
36        "User": { "fieldNames": ["name", "username"], "isInterface": false },
37        "Query": { "fieldNames": ["me"], "isInterface": false }
38      }
39    },
40    "root": {
41      "kind": "Fetch",
42      "serviceName": "accounts",
43      "variableUsages": [],
44      "operation": "query Me__accounts__0{me{name username}}",
45      "operationName": "Me__accounts__0",
46      "operationKind": "query",
47      "id": null,
48      "inputRewrites": null,
49      "outputRewrites": null,
50      "authorization": {
51        "is_authenticated": false,
52        "scopes": [],
53        "policies": []
54      }
55    },
56    "formatted_query_plan": "QueryPlan {\n  Fetch(service: \"accounts\") {\n    {\n      me {\n        name\n        username\n      }\n    }\n  },\n}",
57    "query": {
58      "string": "query Me {\n  me {\n    name\n    username\n  }\n}\n",
59      "fragments": { "map": {} },
60      "operations": [
61        {
62          "name": "Me",
63          "kind": "query",
64          "type_name": "Query",
65          "selection_set": [
66            {
67              "Field": {
68                "name": "me",
69                "alias": null,
70                "selection_set": [
71                  {
72                    "Field": {
73                      "name": "name",
74                      "alias": null,
75                      "selection_set": null,
76                      "field_type": { "Named": "String" },
77                      "include_skip": { "include": "Yes", "skip": "No" }
78                    }
79                  },
80                  {
81                    "Field": {
82                      "name": "username",
83                      "alias": null,
84                      "selection_set": null,
85                      "field_type": { "Named": "String" },
86                      "include_skip": { "include": "Yes", "skip": "No" }
87                    }
88                  }
89                ],
90                "field_type": { "Named": "User" },
91                "include_skip": { "include": "Yes", "skip": "No" }
92              }
93            }
94          ],
95          "variables": {}
96        }
97      ],
98      "subselections": {},
99      "unauthorized": {
100        "paths": [],
101        "errors": { "log": true, "response": "errors" }
102      },
103      "filtered_query": null,
104      "defer_stats": {
105        "has_defer": false,
106        "has_unconditional_defer": false,
107        "conditional_defer_variable_names": []
108      },
109      "is_original": true
110    }
111  }
112}

ExecutionResponse

Click to expand
JSON
1{
2  // Control properties
3  "version": 1,
4  "stage": "ExecutionResponse",
5  "control": {
6    "break": 200
7  },
8
9  // Data properties
10  "body": {
11    "errors": [{ "message": "my error message" }]
12  },
13  "context": {
14    "entries": {
15      "testKey": true
16    }
17  },
18  "headers": {
19    "aheader": ["a value"]
20  }
21}

SubgraphRequest

Click to expand
JSON
1{
2  // Control properties
3  "version": 1,
4  "stage": "SubgraphRequest",
5  "control": "continue",
6  "id": "666d677225c1bc6d7c54a52b409dbd4e",
7  "subgraphRequestId": "b5964998b2394b64a864ef802fb5a4b3",
8
9  // Data properties
10  "headers": {},
11  "body": {
12    "query": "query TopProducts__reviews__1($representations:[_Any!]!){_entities(representations:$representations){...on Product{reviews{body id}}}}",
13    "operationName": "TopProducts__reviews__1",
14    "variables": {
15      "representations": [
16        {
17          "__typename": "Product",
18          "upc": "1"
19        },
20        {
21          "__typename": "Product",
22          "upc": "2"
23        },
24        {
25          "__typename": "Product",
26          "upc": "3"
27        }
28      ]
29    }
30  },
31  "context": {
32    "entries": {
33      "apollo_telemetry::usage_reporting": {
34        "statsReportKey": "# TopProducts\nquery TopProducts{topProducts{name price reviews{body id}}}",
35        "referencedFieldsByType": {
36          "Query": {
37            "fieldNames": ["topProducts"],
38            "isInterface": false
39          },
40          "Review": {
41            "fieldNames": ["body", "id"],
42            "isInterface": false
43          },
44          "Product": {
45            "fieldNames": ["price", "name", "reviews"],
46            "isInterface": false
47          }
48        }
49      },
50      "apollo::telemetry::client_version": "",
51      "apollo_telemetry::subgraph_metrics_attributes": {},
52      "apollo::telemetry::client_name": ""
53    }
54  },
55  "uri": "https://reviews.demo.starstuff.dev/",
56  "method": "POST",
57  "serviceName": "reviews"
58}

SubgraphResponse

Click to expand
JSON
1{
2  // Control properties
3  "version": 1,
4  "stage": "SubgraphResponse",
5  "id": "b7810c6f7f95640fd6c6c8781e3953c0",
6  "subgraphRequestId": "b5964998b2394b64a864ef802fb5a4b3",
7  "control": "continue",
8
9  // Data properties
10  "headers": {
11    "etag": ["W/\"d3-7aayASjs0+e2c/TpiAYgEu/yyo0\""],
12    "via": ["2 fly.io"],
13    "server": ["Fly/90d459b3 (2023-03-07)"],
14    "date": ["Thu, 09 Mar 2023 14:28:46 GMT"],
15    "x-powered-by": ["Express"],
16    "x-ratelimit-limit": ["10000000"],
17    "access-control-allow-origin": ["*"],
18    "x-ratelimit-remaining": ["9999478"],
19    "content-type": ["application/json; charset=utf-8"],
20    "fly-request-id": ["01GV3CCG5EM3ZNVZD2GH0B00E2-lhr"],
21    "x-ratelimit-reset": ["1678374007"]
22  },
23  "body": {
24    "data": {
25      "_entities": [
26        {
27          "reviews": [
28            {
29              "body": "Love it!",
30              "id": "1"
31            },
32            {
33              "body": "Prefer something else.",
34              "id": "4"
35            }
36          ]
37        },
38        {
39          "reviews": [
40            {
41              "body": "Too expensive.",
42              "id": "2"
43            }
44          ]
45        },
46        {
47          "reviews": [
48            {
49              "body": "Could be better.",
50              "id": "3"
51            }
52          ]
53        }
54      ]
55    }
56  },
57  "context": {
58    "entries": {
59      "apollo_telemetry::usage_reporting": {
60        "statsReportKey": "# TopProducts\nquery TopProducts{topProducts{name price reviews{body id}}}",
61        "referencedFieldsByType": {
62          "Product": {
63            "fieldNames": ["price", "name", "reviews"],
64            "isInterface": false
65          },
66          "Query": {
67            "fieldNames": ["topProducts"],
68            "isInterface": false
69          },
70          "Review": {
71            "fieldNames": ["body", "id"],
72            "isInterface": false
73          }
74        }
75      },
76      "apollo::telemetry::client_version": "",
77      "apollo_telemetry::subgraph_metrics_attributes": {},
78      "apollo::telemetry::client_name": ""
79    }
80  },
81  "serviceName": "reviews",
82  "statusCode": 200
83}
Feedback

Edit on GitHub

Ask Community