@@ -24,14 +24,6 @@ The [GraphQL specification](https://spec.graphql.org) deliberately does not
2424specify the transport layer; however, HTTP is the most common choice when
2525serving GraphQL to remote clients due to its ubiquity.
2626
27- Previous to this specification, the article
28- [ Serving over HTTP] ( https://graphql.org/learn/serving-over-http )
29- ([ WayBack Machine entry, 1st June 2022] ( https://web.archive.org/web/20220601155421/https://graphql.org/learn/serving-over-http ) )
30- on the graphql.org website served as guidance, and leading implementations on
31- both client and server have mostly upheld those best practices and thus
32- established a de-facto standard that is commonly used throughout the ecosystem.
33- This specification aims to codify and expand on this work.
34-
3527** Copyright notice**
3628
3729Copyright © 2022-present, GraphQL contributors
@@ -162,33 +154,16 @@ http://example.com/product/graphql
162154
163155# Serialization Format
164156
165- The GraphQL specification allows for many
166- [ serialization formats to be implemented] ( https://spec.graphql.org/draft/#sec-Serialization-Format ) .
167- Servers and clients MUST support JSON and MAY support other, additional
168- serialization formats.
169-
170- Note: Allowing other media types, particularly on requests, can be insecure.
171-
172- For consistency and ease of notation, examples of the response are given in JSON
173- throughout this specification.
157+ Servers and clients MUST support JSON as a serialization format.
174158
175159## Media Types
176160
177- The following are the officially recognized GraphQL media types to designate
178- using the JSON encoding for GraphQL requests:
161+ The following are the officially recognized GraphQL media types:
179162
180- | Name | Description |
181- | ------------------ | --------------------------------------- |
182- | ` application/json ` | Standard type for GraphQL JSON requests |
183-
184- And for a _ GraphQL response_ :
185-
186- | Name | Description |
187- | ----------------------------------- | --------------------------------------- |
188- | ` application/graphql-response+json ` | The preferred type for server responses |
189-
190- Note: Servers MAY additionally support ` application/json ` as a response media
191- type.
163+ | Name | Description |
164+ | ----------------------------------- | ------------------------------------- |
165+ | ` application/json ` | Media type for GraphQL JSON requests |
166+ | ` application/graphql-response+json ` | Media type for GraphQL JSON responses |
192167
193168For details of the shapes of these JSON payloads, please see
194169[ Request] ( #sec-Request ) and [ Response] ( #sec-Response ) .
@@ -220,6 +195,13 @@ parameters in one of the manners described in this specification:
220195 extend the protocol however they see fit, as specified in
221196 [ the Response section of the GraphQL specification] ( https://spec.graphql.org/draft/#sec-Response-Format.Response ) .
222197
198+ Servers receiving a request with additional properties MUST ignore properties
199+ they do not understand.
200+
201+ If implementers need to add additional information to a request they MUST do so
202+ via other means; the RECOMMENDED approach is to add an implementer-scoped entry
203+ to the {extensions} object.
204+
223205Note: When comparing _ GraphQL-over-HTTP request_ against the term
224206[ "request"] ( https://spec.graphql.org/draft/#request ) in the GraphQL
225207specification you should note the _ GraphQL schema_ and "initial value" are not
@@ -231,17 +213,6 @@ string describing one or more operations, each of which may be a query or
231213mutation. A better name would have been ` document ` , but the term ` query ` is well
232214established.
233215
234- Note: Depending on the serialization format used, values of the aforementioned
235- parameters can be encoded differently but their names and semantics must stay
236- the same.
237-
238- Note: An HTTP request that encodes parameters of the same names but of the wrong
239- type, or that omits required parameters, is not a well-formed _ GraphQL-over-HTTP
240- request_ .
241-
242- Note: Specifying ` null ` for optional request parameters is equivalent to not
243- specifying them at all.
244-
245216Note: So long as it is a string, {query} does not have to parse or validate to
246217be part of a well-formed _ GraphQL-over-HTTP request_ .
247218
@@ -254,10 +225,6 @@ A client MUST indicate the media types that it supports in responses using the
254225The client MUST include the media type ` application/graphql-response+json ` in
255226the ` Accept ` header.
256227
257- The client MAY additionally include the media type ` application/json ` in the
258- ` Accept ` header. When accepting both media types, the client SHOULD indicate it
259- prefers ` application/graphql-response+json ` over ` application/json ` .
260-
261228## GET
262229
263230For HTTP GET requests, the _ GraphQL-over-HTTP request_ parameters MUST be
@@ -269,26 +236,30 @@ The {query} parameter MUST be the string representation of the source text of
269236the document as specified in
270237[ the Language section of the GraphQL specification] ( https://spec.graphql.org/draft/#sec-Language ) .
271238
272- The {operationName} parameter, if present, must be a string.
239+ The {operationName} parameter, if present and not the empty string, MUST be a
240+ string.
273241
274- Each of the {variables} and {extensions} parameters, if used , MUST be encoded as
275- a JSON string.
242+ Each of the {variables} and {extensions} parameters, if present , MUST be encoded
243+ as a JSON object string.
276244
277- The {operationName} parameter, if supplied and not the empty string, represents
245+ For robustness, specifying the empty string for optional request parameters is
246+ equivalent to not specifying them at all.
247+
248+ The {operationName} parameter, if present and not the empty string, represents
278249the name of the operation to be executed within the {query} as a string.
279250
251+ GET requests MUST NOT be used for executing mutation operations. This
252+ restriction is necessary to conform with the long-established semantics of safe
253+ methods within HTTP.
254+
280255Note: In the final URL all of these parameters will appear in the query
281256component of the request URL as URL-encoded values due to the WHATWG
282257URLSearchParams encoding specified above.
283258
284- Setting the value of the {operationName} parameter to the empty string is
285- equivalent to omitting the {operationName} parameter.
286-
287259Note: By the above, ` operationName=null ` represents an operation with the name
288- ` "null" ` (such as ` query null { __typename } ` ). If a literal ` null ` is desired,
289- either omit {operationName} or set it to the empty string.
260+ ` "null" ` (such as ` query null { __typename } ` ).
290261
291- ### Example
262+ ### Examples
292263
293264If we wanted to execute the following GraphQL query:
294265
@@ -308,18 +279,29 @@ This request could be sent via an HTTP GET as follows:
308279http://example.com/graphql?query =query(%24id%3A%20ID!)%7Buser(id%3A%24id)%7Bname%7D%7D&variables =%7B%22id%22%3A%22QVBJcy5ndXJ1%22%7D
309280```
310281
311- GET requests MUST NOT be used for executing mutation operations. If the values
312- of {query} and {operationName} indicate that a mutation operation is to be
313- executed, the server MUST respond with error status code ` 405 ` (Method Not
314- Allowed) and halt execution. This restriction is necessary to conform with the
315- long-established semantics of safe methods within HTTP.
282+ An empty {operationName} is allowed. This is a valid request:
283+
284+ ``` url example
285+ http://example.com/graphql? query =%7B%20foo%20%7D& operationName =
286+ ```
316287
317288## POST
318289
319- A GraphQL POST request instructs the server to perform a query or mutation
320- operation. A GraphQL POST request MUST have a body which contains values of the
321- _ GraphQL-over-HTTP request_ parameters encoded in one of the officially
322- recognized GraphQL media types, or another media type supported by the server.
290+ A GraphQL POST request MUST have a body which contains values of the
291+ _ GraphQL-over-HTTP request_ parameters encoded using the ` application/json `
292+ media type.
293+
294+ The {query} parameter MUST be the string representation of the source text of
295+ the document as specified in
296+ [ the Language section of the GraphQL specification] ( https://spec.graphql.org/draft/#sec-Language ) .
297+
298+ The {operationName} parameter, if present and not null, MUST be a string.
299+
300+ Each of the {variables} and {extensions} parameters, if present and not null,
301+ MUST be a JSON object.
302+
303+ For robustness, specifying null for optional request parameters is equivalent to
304+ not specifying them at all.
323305
324306A client MUST indicate the media type of a request body using the ` Content-Type `
325307header as specified in [ RFC7231] ( https://datatracker.ietf.org/doc/html/rfc7231 ) .
@@ -333,43 +315,15 @@ indicating an encoding, the server MUST assume the encoding is `utf-8`.
333315If the client does not supply a ` Content-Type ` header with a POST request, the
334316server SHOULD reject the request using the appropriate ` 4xx ` status code.
335317
318+ If the values of {query} and {operationName} indicate that a mutation operation
319+ is to be executed with a GET request, the server MUST respond with error status
320+ code ` 405 ` (Method Not Allowed) and halt execution.
321+
336322Note: Rejecting such requests encourages clients to supply a ` Content-Type `
337323header with every POST request. A server has the option to assume any media type
338324they wish when none is supplied, with the understanding that parsing the request
339325may fail.
340326
341- A server MAY support POST requests encoded with and/or accepting other media
342- types or encodings.
343-
344- If a client does not know the media types the server supports then it SHOULD
345- encode the request body in JSON (i.e. with ` Content-Type: application/json ` ).
346-
347- Note: Request encoding with media type ` application/json ` is supported by every
348- compliant _ server_ .
349-
350- ### JSON Encoding
351-
352- When encoded in JSON, a _ GraphQL-over-HTTP request_ is encoded as a JSON object
353- (map), with the properties specified by the GraphQL-over-HTTP request:
354-
355- - {query} - the string representation of the Source Text of the Document as
356- specified in
357- [ the Language section of the GraphQL specification] ( https://spec.graphql.org/draft/#sec-Language ) .
358- - {operationName} - an optional string
359- - {variables} - an optional object (map), the keys of which are the variable
360- names and the values of which are the variable values
361- - {extensions} - an optional object (map) reserved for implementers to extend
362- the protocol however they see fit, as specified in
363- [ the Response section of the GraphQL specification] ( https://spec.graphql.org/draft/#sec-Response-Format.Response ) .
364-
365- All other property names are reserved for future expansion. If implementers need
366- to add additional information to a request they MUST do so via other means; the
367- RECOMMENDED approach is to add an implementer-scoped entry to the {extensions}
368- object.
369-
370- Servers receiving a request with additional properties MUST ignore properties
371- they do not understand.
372-
373327### Example
374328
375329If we wanted to execute the following GraphQL query:
@@ -413,8 +367,8 @@ And the body:
413367
414368When a server receives a well-formed _ GraphQL-over-HTTP request_ , it must return
415369a well‐formed _ GraphQL response_ . The server's response describes the result of
416- validating and executing the requested operation if successful, and describes
417- any errors encountered during the request.
370+ validating and executing the requested operation if successful and describes any
371+ errors encountered during the request.
418372
419373A server must comply with
420374[ RFC7231] ( https://datatracker.ietf.org/doc/html/rfc7231 ) .
@@ -424,14 +378,19 @@ A server must comply with
424378The body of the server's response MUST follow the requirements for a _ GraphQL
425379response_ , encoded directly in the chosen media type.
426380
427- A server MUST indicate the media type of the response with a ` Content-Type `
428- header, and SHOULD indicate the encoding (e.g.
429- ` application/graphql-response+json; charset=utf-8 ` ).
430-
431381If an ` Accept ` header is provided, the server MUST respect the given ` Accept `
432382header and attempt to encode the response in the highest priority media type
433383listed that is supported by the server.
434384
385+ A _ server_ MUST support responses using the ` application/graphql-response+json `
386+ media type.
387+
388+ A server MAY additionally support other response media types.
389+
390+ A server MUST indicate the media type of the response with a ` Content-Type `
391+ header, and SHOULD indicate the encoding (e.g.
392+ ` application/graphql-response+json; charset=utf-8 ` ).
393+
435394In alignment with the
436395[ HTTP 1.1 Accept] ( https://tools.ietf.org/html/rfc7231#section-5.3.2 )
437396specification, when a client does not include at least one supported media type
@@ -447,15 +406,6 @@ one of the media types it has requested, hence `406 Not Acceptable` being the
447406recommended response. However, the server authors may know better about the
448407specific clients consuming their endpoint, thus both approaches are permitted.
449408
450- A _ server_ MUST support responses using the ` application/graphql-response+json `
451- media type.
452-
453- A server MAY additionally support the ` application/json ` response media type.
454-
455- Note: Servers may wish to only support the ` application/graphql-response+json `
456- media type so that related HTTP tooling may utilize the HTTP status codes of
457- responses without having to be GraphQL-aware.
458-
459409## Validation
460410
461411Validation of a well-formed _ GraphQL-over-HTTP request_ SHOULD apply all the
@@ -478,7 +428,7 @@ should not be executed; however in certain circumstances, for example persisted
478428operations that were previously known to be valid, the server may attempt
479429execution regardless of validation errors.
480430
481- ## Status Codes
431+ ## Status Code
482432
483433In case of errors that completely prevent the generation of a well-formed
484434_ GraphQL response_ , the server MUST respond with the appropriate status code
@@ -488,8 +438,7 @@ status code.
488438Note: Typically the appropriate status code will be ` 400 ` (Bad Request).
489439
490440If the _ GraphQL response_ contains the {data} entry and it is not {null}, then
491- the server MUST reply with a ` 2xx ` status code and SHOULD reply with ` 200 `
492- status code.
441+ the server MUST reply with a ` 2xx ` status code.
493442
494443Note: The result of executing a GraphQL operation may contain partial data as
495444well as encountered errors. Errors that happen during execution of the GraphQL
@@ -504,12 +453,12 @@ are expected to be supported over time, valid codes must be present in this
504453document.
505454
506455If the _ GraphQL response_ contains the {data} entry and it is {null}, then the
507- server SHOULD reply with a ` 2xx ` status code and it is RECOMMENDED it replies
508- with ` 200 ` status code.
456+ server SHOULD reply with a ` 2xx ` status code.
509457
510458Note: Using ` 4xx ` and ` 5xx ` status codes in this situation is not recommended -
511459since no _ GraphQL request error_ has occurred it is seen as a "partial
512- response".
460+ response". This is typically the case if an error is propagated to the root
461+ field.
513462
514463If the _ GraphQL response_ does not contain the {data} entry then the server MUST
515464reply with a ` 4xx ` or ` 5xx ` status code as appropriate.
@@ -524,11 +473,6 @@ pass validation, then the server SHOULD reply with `400` status code.
524473If the client is not permitted to issue the GraphQL request then the server
525474SHOULD reply with ` 403 ` , ` 401 ` or similar appropriate status code.
526475
527- Note: Clients can rely on the response being a well-formed _ GraphQL response_
528- regardless of the status code. Intermediary servers may use the status code to
529- determine the status of the _ GraphQL response_ without needing to process the
530- response body.
531-
532476### Examples
533477
534478The following examples provide guidance on how to deal with specific error
@@ -600,6 +544,74 @@ response; it still indicates successful execution.
600544This section of the specification is non-normative, even where the words and
601545phrases specified in RFC2119 are used.
602546
547+ ## application/json response media type
548+
549+ Previous to this specification, the article
550+ [ Serving over HTTP] ( https://graphql.org/learn/serving-over-http )
551+ ([ WayBack Machine entry, 1st June 2022] ( https://web.archive.org/web/20220601155421/https://graphql.org/learn/serving-over-http ) )
552+ on the graphql.org website served as guidance.
553+
554+ This article used ` application/json ` as media type for the response.
555+
556+ In some cases, the response received by a client may not originate from a
557+ GraphQL service, but instead from an intermediary—such as an API gateway, proxy,
558+ firewall or other middleware—that does not implement this specification. Such an
559+ intermediary might produce the response to indicate an error, returning a
560+ response with ` 4xx ` or ` 5xx ` status code and potentially using the standard
561+ ` application/json ` media type to encode the reason for the error. Such a
562+ response is unlikely to be a valid GraphQL response.
563+
564+ For this reason, a client application receiving an ` application/json ` response,
565+ could rely on the response being a well-formed _ GraphQL response_ only if the
566+ status code is ` 200 ` .
567+
568+ This caused multiple observability issues because it was challenging to
569+ distinguish a well-formed _ GraphQL response_ from an intermediary response.
570+
571+ ` application/graphql-response+json ` allows to distringuish a well-formed
572+ _ GraphQL response_ from another intermediary response and is the required media
573+ type moving forward.
574+
575+ For compatibility reasons, clients and servers may support ` application/json ` as
576+ described in this section.
577+
578+ Note: Servers may wish to only support the ` application/graphql-response+json `
579+ media type so that related HTTP tooling may utilize the HTTP status codes of
580+ responses without having to be GraphQL-aware.
581+
582+ ### Accept
583+
584+ To maximize compatibility, a client may include the media type
585+ ` application/json ` in the ` Accept ` header. When doing this, it is recommended
586+ that the client set the ` Accept ` header to
587+ ` application/graphql-response+json, application/json;q=0.9 ` .
588+
589+ Note: The ` q=0.9 ` parameter tells content negotiation that ` application/json `
590+ should only be used if ` application/graphql-response+json ` is not supported.
591+
592+ ### Status code
593+
594+ When using the ` application/json ` media type, the server should use the ` 200 `
595+ status code for every response to a well-formed _ GraphQL-over-HTTP request_ ,
596+ independent of any _ GraphQL request error_ or _ GraphQL field error_ raised.
597+
598+ If the response uses a non-` 200 ` status code then the client must not rely on
599+ the body to be a well-formed _ GraphQL response_ .
600+
601+ If the _ GraphQL response_ contains a non-null {data} entry then the server must
602+ use the ` 200 ` status code.
603+
604+ Note: This indicates that no _ GraphQL request error_ was raised, though one or
605+ more _ GraphQL field error_ may have been raised this is still a successful
606+ execution - see "partial response" in the GraphQL specification.
607+
608+ The server should not use a ` 4xx ` or ` 5xx ` status code for a response to a
609+ well-formed _ GraphQL-over-HTTP request_ .
610+
611+ If the URL is not used for other purposes, the server should use a ` 4xx ` status
612+ code to respond to a request that is not a well-formed _ GraphQL-over-HTTP
613+ request_ .
614+
603615## Security
604616
605617This specification focuses solely on the intersection of GraphQL and HTTP.
0 commit comments