GraphQL over HTTP¶
gqlgw follows the GraphQL-over-HTTP draft.
Requests¶
POST /graphql HTTP/1.1
Content-Type: application/json
Accept: application/graphql-response+json
{"query": "query One($id: ID!) { user(id: $id) { name } }",
"operationName": "One", "variables": {"id": "1"}}
Content-Type must be application/json. operationName and variables are optional;
variables must be an object.
Responses¶
The media type comes from Accept:
Accept |
Response Content-Type |
|---|---|
none, or contains application/graphql-response+json |
application/graphql-response+json |
application/json, application/* or */* |
application/json |
| anything else | 406 |
flowchart TB
r[request] --> h{HTTP layer ok?}
h -- no --> e4["4xx<br/>{errors: [...]}, no data"]
h -- yes --> v{"document valid,<br/>operation and variables ok?"}
v -- no --> rq{media type}
rq -- "graphql-response+json" --> s400["400<br/>{errors}"]
rq -- "application/json" --> s200e["200<br/>{errors}"]
v -- yes --> ex[execution]
ex --> s200["200<br/>{data} or {errors, data}"]
| Situation | Status | Body |
|---|---|---|
| success | 200 |
{"data": …} |
| field errors (upstream failure, coercion, null in non-null) | 200 |
{"errors": […], "data": …}, data possibly null |
| syntax, validation, unknown operation, variable errors | 400 (GQL media type) or 200 (application/json) |
{"errors": […]} |
method other than GET/POST |
405 |
Allow: GET, POST |
mutation over GET |
405 |
Allow: POST |
unacceptable Accept |
406 |
|
body over max_body |
413 |
|
Content-Type other than JSON |
415 |
|
malformed body (query missing, not an object) |
400 |
Errors have the usual shape: message, locations, and path for field errors.
{"errors":[{"message":"Cannot query field \"titel\" on type \"Post\".","locations":[{"line":1,"column":11}]}]}
Keys of data follow the order of the query.
Debug headers¶
With [gateway] debug_headers = true:
| Header | Meaning |
|---|---|
X-GQL-Rounds |
fetch rounds |
X-GQL-Subrequests |
upstream requests sent |
X-GQL-Batches |
of which batch requests |
X-GQL-Cache |
l1=…;l2=…;l3=…;miss=…: cache lookups by level |
X-GQL-Doc-Cache |
hit when the validated document came from the worker's cache |
The same counters go to the access log with the gqlgw format:
rounds=2 sub=2 cache=l1=0;l2=0;l3=0;miss=3.
Introspection¶
__schema and __type answer like graphql-js 17 (getIntrospectionQuery), without the gateway
directives. [gateway] introspection = false turns them off; __typename always works.