# GraphQL over HTTP _Current Working Draft_ **Introduction** This specification details how GraphQL should be served and consumed over HTTP in order to maximize interoperability between clients, servers and tools. This specification does not override or replace the [GraphQL specification](https://spec.graphql.org); it extends it to cover the topic of serving GraphQL services over HTTP. If any statement or algorithm in this specification appears to conflict with the GraphQL specification, the behavior detailed in the GraphQL specification should be used (and an issue raised). The [GraphQL specification](https://spec.graphql.org) deliberately does not specify the transport layer; however, HTTP is the most common choice when serving GraphQL to remote clients due to its ubiquity. **Copyright notice** Copyright © 2022-present, GraphQL contributors THESE MATERIALS ARE PROVIDED “AS IS”. The parties expressly disclaim any warranties (express, implied, or otherwise), including implied warranties of merchantability, non-infringement, fitness for a particular purpose, or title, related to the materials. The entire risk as to implementing or otherwise using the materials is assumed by the implementer and user. IN NO EVENT WILL THE PARTIES BE LIABLE TO ANY OTHER PARTY FOR LOST PROFITS OR ANY FORM OF INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER FROM ANY CAUSES OF ACTION OF ANY KIND WITH RESPECT TO THIS DELIVERABLE OR ITS GOVERNING AGREEMENT, WHETHER BASED ON BREACH OF CONTRACT, TORT (INCLUDING NEGLIGENCE), OR OTHERWISE, AND WHETHER OR NOT THE OTHER MEMBER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. **Conformance** A conforming implementation of GraphQL over HTTP must fulfill all normative requirements. Conformance requirements are described in this document via both descriptive assertions and key words with clearly defined meanings. The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in the normative portions of this document are to be interpreted as described in [IETF RFC 2119](https://tools.ietf.org/html/rfc2119). These key words may appear in lowercase and still retain their meaning unless explicitly declared as non-normative. A conforming implementation of GraphQL over HTTP may provide additional functionality, but must not do so where explicitly disallowed or where doing so would otherwise result in non-conformance. **Non-Normative Portions** All contents of this document are normative except portions explicitly declared as non-normative. Examples in this document are non-normative, and are presented to aid understanding of introduced concepts and the behavior of normative portions of the specification. Examples are either introduced explicitly in prose (e.g. "for example") or are set apart in example or counter-example blocks, like this: ```example This is an example of a non-normative example. ``` ```counter-example This is an example of a non-normative counter-example. ``` Notes in this document are non-normative, and are presented to clarify intent, draw attention to potential edge cases and pitfalls, and answer common questions that arise during implementation. Notes are either introduced explicitly in prose (e.g. "Note: ") or are set apart in a note block, like this: Note: This is an example of a non-normative note. # Overview Though [the GraphQL specification](https://spec.graphql.org) is transport agnostic, this GraphQL over HTTP specification aims to map GraphQL's semantics to their HTTP equivalents, enabling us to combine the full advantages of GraphQL with the rich feature set of HTTP. GraphQL queries and mutations naturally mirror the request/response message model used in HTTP, allowing us to provide a GraphQL request in an HTTP request and a GraphQL response in an HTTP response. :: In this document, the term _server_ refers to a GraphQL over HTTP Specification compliant HTTP server unless the context indicates otherwise. The role of a _server_ is to provide a _client_ access to one or more GraphQL services over HTTP. A _server_ is not a _GraphQL service_; it is a GraphQL service host. :: In this document, the term _client_ refers to a GraphQL over HTTP Specification compliant HTTP client unless the context indicates otherwise. The role of a _client_ is to issue HTTP requests to a _server_ in order to interact with a _GraphQL service_. Note: GraphQL Subscriptions are beyond the scope of this specification at this time. # URL A _server_ MUST enable GraphQL requests to one or more GraphQL schemas. Each GraphQL schema a _server_ provides MUST be served via one or more URLs. The GraphQL schema available via a single URL MAY be different for different clients. For example, alpha testers or authenticated users may have access to a schema with additional fields. A _server_ MAY forbid individual requests by a _client_ to any endpoint for any reason, for example to require authentication or payment; when doing so it SHOULD use the relevant `4xx` or `5xx` status code. This decision SHOULD NOT be based on the contents of a well-formed _GraphQL-over-HTTP request_. Note: The _server_ should not make authorization decisions based on any part of the _GraphQL request_; these decisions should be made by the _GraphQL schema_ during [GraphQL's ExecuteRequest()](), allowing for a partial response to be generated. Server URLs which enable GraphQL requests MAY also be used for other purposes, as long as they don't conflict with the server's responsibility to handle GraphQL requests. It is a common convention to end the path component of the URL with `/graphql`, for example: ```url example http://example.com/graphql ``` ```url example http://product.example.com/graphql ``` ```url example http://example.com/product/graphql ``` # Serialization Format The GraphQL specification allows for many [serialization formats to be implemented](https://spec.graphql.org/draft/#sec-Serialization-Format). Servers and clients MUST support JSON and MAY support other, additional serialization formats. Note: Allowing other media types, particularly on requests, can be insecure. For consistency and ease of notation, examples of the response are given in JSON throughout this specification. ## Media Types The following are the officially recognized GraphQL media types: | Name | Description | | ----------------------------------- | ------------------------------------- | | `application/json` | Media type for GraphQL JSON requests | | `application/graphql-response+json` | Media type for GraphQL JSON responses | For details of the shapes of these JSON payloads, please see [Request](#sec-Request) and [Response](#sec-Response). If the media type in a `Content-Type` or `Accept` header does not include encoding information and matches one of the officially recognized GraphQL media types, then `utf-8` MUST be assumed (e.g. for header `Content-Type: application/graphql-response+json`, UTF-8 encoding would be assumed). # Request A server MUST support _GraphQL-over-HTTP request_ via `POST`, and MAY support _GraphQL-over-HTTP request_ via other HTTP methods, such as `GET`. ## GraphQL-over-HTTP Request :: A _GraphQL-over-HTTP request_ is an HTTP request that encodes the following parameters in one of the manners described in this specification: - {query} - (_Required_, string): The string representation of the Source Text of a GraphQL Document as specified in [the Language section of the GraphQL specification](https://spec.graphql.org/draft/#sec-Language). - {operationName} - (_Optional_, string): The name of the Operation in the Document to execute. - {variables} - (_Optional_, map): Values for any Variables defined by the Operation. - {extensions} - (_Optional_, map): This entry is reserved for implementers to extend the protocol however they see fit, as specified in [the Response section of the GraphQL specification](https://spec.graphql.org/draft/#sec-Response-Format). Note: When comparing a _GraphQL-over-HTTP request_ against the term ["request"](https://spec.graphql.org/draft/#request) in the GraphQL specification you should note the _GraphQL schema_ and "initial value" are not included in the GraphQL-over-HTTP _request_; they are handled by the _server_ based on the URL used. Note: Be aware that `query` is a misleading parameter name as its value is a string describing one or more operations, each of which may be a query or mutation. A better name would have been `document`, but the term `query` is well established. Note: Depending on the serialization format used, values of the aforementioned parameters can be encoded differently but their names and semantics must stay the same. Note: An HTTP request that encodes parameters of the same names but of the wrong type, or that omits required parameters, is not a well-formed _GraphQL-over-HTTP request_. Note: So long as it is a string, {query} does not have to parse or validate to be part of a well-formed _GraphQL-over-HTTP request_. ## Accept A client MUST indicate the media types that it supports in responses using the `Accept` HTTP header; this header is specified in [IETF RFC 9110](https://httpwg.org/specs/rfc9110.html#field.accept). Note: If a client does not supply the `Accept` header then the server may respond with an error, or with any content type it chooses (including serving a valid GraphQL response under a media type of its choosing). To ensure your client gets something useful, it needs to indicate the media types it supports. The client MUST include the media type `application/graphql-response+json` in the `Accept` header. :: A _legacy client_ is a client that does not support responses using the `application/graphql-response+json` media type, and thus does not conform to this specification. If it is not known that the server supports `application/graphql-response+json`, the client SHOULD set the `Accept` header to `application/graphql-response+json, application/json;q=0.9`. ## GET For HTTP GET requests, the _GraphQL-over-HTTP request_ parameters MUST be provided in the query component of the request URL, encoded in the `application/x-www-form-urlencoded` format as specified by the [WHATWG URLSearchParams class](https://url.spec.whatwg.org/#interface-urlsearchparams). The {query} parameter MUST be the string representation of the source text of the document as specified in [the Language section of the GraphQL specification](https://spec.graphql.org/draft/#sec-Language). The {operationName} parameter, if present, must be a string. Each of the {variables} and {extensions} parameters, if present and not the empty string, MUST be encoded as a JSON string. The {operationName} parameter, if present and not the empty string, represents the name of the operation to be executed within the {query} as a string. Specifying the empty string for optional request parameters is equivalent to not specifying them at all. Note: In the final URL all of these parameters will appear in the query component of the request URL as URL-encoded values due to the WHATWG URLSearchParams encoding specified above. Note: By the above, `operationName=null` represents an operation with the name `"null"` (such as `query null { __typename }`). If a literal `null` is desired, either omit {operationName} or set it to the empty string. GET requests MUST NOT be used for executing mutation operations. If the values of {query} and {operationName} indicate that a mutation operation is to be executed, the server MUST respond with an appropriate `4xx` status code and halt execution; status code `405` (Method Not Allowed) is RECOMMENDED. This restriction is necessary to conform with the long-established semantics of safe methods within HTTP. Note: If status code `405` is used then the `Allow` header must be included as required by [IETF RFC 9110](https://httpwg.org/specs/rfc9110.html#status.405). ### Example If we wanted to execute the following GraphQL query: ```raw graphql example query($id: ID!){user(id:$id){name}} ``` With the following query variables: ```raw json example {"id":"QVBJcy5ndXJ1"} ``` This request could be sent via an HTTP GET as follows: ```url example http://example.com/graphql?query=query(%24id%3A%20ID!)%7Buser(id%3A%24id)%7Bname%7D%7D&variables=%7B%22id%22%3A%22QVBJcy5ndXJ1%22%7D ``` ## POST A POST request instructs the GraphQL-over-HTTP server to perform a query or mutation operation. The request MUST have a body which contains values of the _GraphQL-over-HTTP request_ parameters encoded in one of the officially recognized GraphQL media types, or another media type supported by the server. A client MUST indicate the media type of a request body using the `Content-Type` header; this header is specified in [IETF RFC 9110](https://httpwg.org/specs/rfc9110.html#field.content-type). A server MUST support POST requests with a body encoded as UTF-8 JSON, using the `application/json` media type (as indicated by the `Content-Type` header). For POST requests using an officially recognized GraphQL `Content-Type` without indicating an encoding, the server MUST assume the encoding is `utf-8`. If the client does not supply a `Content-Type` header with a POST request, the server SHOULD reject the request using the appropriate `4xx` status code. Note: Rejecting such requests encourages clients to supply a `Content-Type` header with every POST request. A server has the option to assume any media type it wishes when none is supplied, with the understanding that parsing the request may fail. A server MAY support POST requests encoded with and/or accepting other media types or encodings. If a client does not know the media types the server supports then it SHOULD encode the request body in JSON (i.e. with `Content-Type: application/json`). Note: Request encoding with media type `application/json` is supported by every compliant _server_. ### JSON Encoding When encoded in JSON, a _GraphQL-over-HTTP request_ is encoded as a JSON object (map), with the properties specified by the GraphQL-over-HTTP request: - {query} - the string representation of the Source Text of the Document as specified in [the Language section of the GraphQL specification](https://spec.graphql.org/draft/#sec-Language). - {operationName} - an optional string - {variables} - an optional object (map), the keys of which are the variable names and the values of which are the variable values - {extensions} - an optional object (map) reserved for implementers to extend the protocol however they see fit, as specified in [the Response section of the GraphQL specification](https://spec.graphql.org/draft/#sec-Response-Format.Response). All other property names are reserved for future expansion. Implementers MUST NOT add additional properties to the request object; additional information should instead use other means, for example HTTP headers or an implementer-scoped entry in the {extensions} object. Servers receiving a request with additional properties MUST ignore properties they do not understand. Specifying `null` for optional request parameters is equivalent to not specifying them at all. ### Example If we wanted to execute the following GraphQL query: ```raw graphql example query ($id: ID!) { user(id: $id) { name } } ``` With the following query variables: ```json example { "id": "QVBJcy5ndXJ1" } ``` This request could be sent via an HTTP POST to the relevant URL using the JSON encoding with the headers: ```headers example Content-Type: application/json Accept: application/graphql-response+json ``` And the body: ```json example { "query": "query ($id: ID!) {\n user(id: $id) {\n name\n }\n}", "variables": { "id": "QVBJcy5ndXJ1" } } ``` # Response When a server receives a well-formed _GraphQL-over-HTTP request_, it must return a well-formed _GraphQL-over-HTTP response_. :: A _GraphQL-over-HTTP response_ is formed of the encoded _GraphQL result_ along with the relevant headers and status code. :: A _GraphQL result_ describes the result of parsing, validating, and (if successful) executing the requested operation, and any errors encountered during the request. If execution occurred then the GraphQL result represents a _GraphQL execution result_, otherwise (for example, in the case of parse or validation failure) it represents a _GraphQL request error result_. A server must comply with [IETF RFC 9110](https://httpwg.org/specs/rfc9110.html). Note: Detailing the requirements of HTTP, such as [requiring support for GET and HEAD verbs](https://httpwg.org/specs/rfc9110.html#method.overview) is beyond the scope of this specification. Please refer to IETF RFC 9110 for such requirements. ## Body The body of the server's response MUST follow the requirements for either a _GraphQL execution result_ or a _GraphQL request error result_, encoded directly in the chosen media type. A server MUST indicate the media type of the response with a `Content-Type` header, and SHOULD indicate the encoding (e.g. `application/graphql-response+json; charset=utf-8`). A server MUST support responses using the `application/graphql-response+json` media type. :: A _legacy server_ is a server that does not support responses using the `application/graphql-response+json` media type, and thus does not conform to this specification. If an `Accept` header is provided, the server MUST respect the given `Accept` header and attempt to encode the response in the highest priority media type listed that is supported by the server. In alignment with the [IETF RFC 9110 Content Negotiation](https://httpwg.org/specs/rfc9110.html#content.negotiation), when the request includes an `Accept` header and no supported media type is acceptable according to that header, the server MUST either: 1. Respond with a `406 Not Acceptable` status code and stop processing the request; OR 1. Disregard the `Accept` header and respond with the server's choice of media type. If the `Accept` header does not indicate support for one of the server's preferred media types but does indicate support for `application/json`, as may be the case for a _legacy client_, the request SHOULD be performed following the requirements of this specification as if the request had specified `Accept: application/graphql-response+json`, except any response that produces a `2xx` status code should replace the `Content-Type` header with `Content-Type: application/json`. Note: This recommendation uses this specification's full range of HTTP status codes while maximizing _legacy client_ compatibility for successful and partially successful requests. HTTP responses could originate from non-GraphQL intermediary servers and middleware handling failures (HTTP `4xx` and `5xx`), so clients typically can only rely on a response to be from GraphQL either when it is successful (HTTP `2xx`) or when it explicitly declares it is a GraphQL-over-HTTP response (`Content-Type: application/graphql-response+json`). If the `Accept` header is present but does not indicate support for any of the server's supported media types or `application/json`, the server SHOULD respond with `406 Not Acceptable`. Note: It is unlikely that a client can process a response that does not match one of the media types it has requested, hence `406 Not Acceptable` being the recommended response. However, the server authors may know better about the specific clients consuming their endpoint, thus both approaches are permitted. ## Validation Validation of a well-formed _GraphQL-over-HTTP request_ SHOULD apply all the [validation rules](https://spec.graphql.org/draft/#sec-Validation) specified by the GraphQL specification. The server MAY, at its discretion, apply additional validation rules. Note: Examples of additional validation rules the server may apply include depth limit, complexity limit, etc. ## Execution Execution of a _GraphQL-over-HTTP request_ follows [GraphQL's ExecuteRequest()]() algorithm. Note: In general, a _GraphQL-over-HTTP request_ that does not pass validation should not be executed; however in certain circumstances, for example persisted operations that were previously known to be valid, the server may attempt execution regardless of validation errors. ## Status Codes Clients should process a response using the `application/graphql-response+json` media type as a well-formed _GraphQL-over-HTTP response_ independent of the HTTP status code. Note: With `application/graphql-response+json`, clients know the response is well-formed and should determine the detailed status of the response from the response body alone, allowing server authors to adopt more appropriate status codes without impacting behavior of existing clients. Intermediary servers and services may use the status code to determine the status of the _GraphQL-over-HTTP response_ without needing to process the response body; this is useful in request logs, developer tooling, anomaly and intrusion detection, metrics and observability, API gateways, and more. In the case of errors that completely prevent the generation of a well-formed _GraphQL-over-HTTP response_, the server SHOULD respond with the appropriate HTTP `4xx` or `5xx` status code depending on the concrete error condition, and MUST NOT use the `application/graphql-response+json` media type. If the _GraphQL result_ contains the {data} entry and it is not {null}, then the server MUST reply with a `2xx` status code. If the _GraphQL result_ contains the {data} entry and does not contain the {errors} entry, then the server SHOULD reply with a `200` status code. Note: There are no circumstances where the GraphQL specification allows a _GraphQL result_ to have {data} as {null} without {errors} being present. If the _GraphQL result_ contains both the {data} entry (even if it is {null}) and the {errors} entry, then the server SHOULD reply with a `294` status code. Note: The result of executing a GraphQL operation may contain partial data as well as encountered errors. Errors that happen during execution of the GraphQL operation typically become part of the result, as long as the server is still able to produce a well-formed _GraphQL-over-HTTP response_. For details of why status code `294` is recommended, see [Partial success](#sec-Partial-success). Using `4xx` and `5xx` status codes in this situation is not appropriate: since no _GraphQL request error_ has occurred it is seen as a "partial response" or "partial success". If the _GraphQL result_ does not contain the {data} entry then it represents a _GraphQL request error result_ and the server MUST reply with an appropriate `4xx` or `5xx` status code: - If the failure is due to an issue in the request itself, the appropriate `4xx` status code should be used: - If a mutation is attempted via the `GET` verb, status code `405` SHOULD be used. - If the request uses an unsupported HTTP method, status code `405` SHOULD be used. - If the `Content-Type` of the request is not supported, status code `415` SHOULD be used. - If none of the media types in the `Accept` header are supported and the `Accept` header does not include `application/json`, then status code `406` SHOULD be used. - If the client did not produce a request within the time that the server was prepared to wait, status code `408` SHOULD be used. - If the size of the URI was too large, status code `414` SHOULD be used (and the client should consider using `POST` instead). - If the size of the request headers (or any one header) was too large, status code `431` SHOULD be used. - If the size of the `POST` request body was too large, status code `413` SHOULD be used. - If the JSON body of the request could not be parsed, status code `400` SHOULD be used. - If the request is not a well-formed _GraphQL-over-HTTP request_, status code `422` SHOULD be used. - If the GraphQL document in the request cannot be parsed, status code `400` SHOULD be used. - If the request does not pass GraphQL validation, status code `422` SHOULD be used. - If the operation to execute cannot be unambiguously determined, status code `422` SHOULD be used. - If the variable values cannot be coerced to match the operation's variable definitions, status code `422` SHOULD be used. - If the client is not permitted to issue the GraphQL request, then the server SHOULD reply with `401`, `403`, or a similar appropriate status code. - If the server cannot process the request due to being a short and stout ceramic vessel, status code `418` SHOULD be used. - When the server is the reason for failure, the appropriate `5xx` status code should be used. For example, if the server is not able to execute requests at this time due to maintenance or load-shedding, then status code `503` SHOULD be used. Note: The GraphQL specification indicates that the only situation in which the _GraphQL result_ does not include the {data} entry is one in which the {errors} entry is populated. Note: Implementers should be careful to always comply with the HTTP spec, for example when using status code `405` the `Allow` header MUST be specified, as required by [RFC 9110](https://httpwg.org/specs/rfc9110.html#status.405). ### Examples The following examples provide guidance on how to deal with specific error cases: **JSON parsing failure** For example, a POST request body of `NONSENSE` or `{"query":` (note: invalid JSON). Requests that the server cannot interpret should result in status code `400` (Bad Request). **Invalid parameters** For example, a POST request body of `{"qeury": "{__typename}"}` (note: typo) or `{"query": "query Q ($i:Int!) { q(i: $i) }", "variables": [7]}` (note: invalid shape for `variables`). A request that does not constitute a well-formed _GraphQL-over-HTTP request_ SHOULD result in status code `422` (Unprocessable Content). **Document parsing failure** For example, a POST request body of `{"query": "{"}`. Requests where the _GraphQL document_ cannot be parsed should result in status code `400` (Bad Request). **Document validation failure** If a request fails _GraphQL validation_, the server SHOULD return a status code of `422` (Unprocessable Content) without proceeding to GraphQL execution. **Operation cannot be determined** If [GetOperation()]() raises a _GraphQL request error_, the server SHOULD NOT execute the request and SHOULD return a status code of `422` (Unprocessable Content). **Variable coercion failure** If [CoerceVariableValues()]() raises a _GraphQL request error_, the server SHOULD NOT execute the request and SHOULD return a status code of `422` (Unprocessable Content). **Field errors encountered during execution** If the operation is executed and no _GraphQL request error_ is raised, then the server SHOULD respond with a status code of `200 OK`. This is the case even if a _GraphQL execution error_ is raised during [GraphQL's ExecuteQuery()]() or [GraphQL's ExecuteMutation()](). Note: The GraphQL specification [differentiates execution errors from request errors](https://spec.graphql.org/draft/#sec-Handling-Field-Errors) and refers to the situation wherein a _GraphQL execution error_ occurs as a partial response; it still indicates successful execution. # Non-normative notes This section of the specification is non-normative, even where the words and phrases specified in [IETF RFC 2119](https://tools.ietf.org/html/rfc2119) are used. ## Partial success The result of executing a GraphQL operation may contain partial data as well as encountered errors. Errors that happen during execution of the GraphQL operation typically become part of the result, as long as the server is still able to produce a well-formed _GraphQL-over-HTTP response_. Using `4xx` and `5xx` status codes when {data} is present and non-null is not appropriate; since no _GraphQL request error_ has occurred it is seen as a "partial response" or "partial success". There's currently not an approved official HTTP status code to use for a "partial success". Contenders include `203 Non-Authoritative information` (which indicates the response has been transformed), `206 Partial Content` (which requires the `Range` header), and WebDAV's status code `207 Multi-Status` (which "provides status for multiple _independent_ operations"). None of those quite fit GraphQL's needs, so we recommend using the custom code `294 Partial Success`. Since we are defining the code ourselves, rather than the IETF, we only recommend its usage alongside the `application/graphql-response+json` media type which makes the meaning explicit. Note: This status code is not to help clients, who should ignore the status code of a response when receiving the `application/graphql-response+json` media type, but allows servers to indicate partial success such that intermediaries that do not implement this specification may still track the not-fully-successful request (for example, for observability). [IETF RFC 9110](https://httpwg.org/specs/rfc9110.html) requires HTTP clients that do not recognize a status code to treat it as equivalent to the `x00` status code of its class. Therefore, although it is not yet registered with IANA, HTTP clients that don't explicitly recognize status code `294 Partial Success` must treat it as equivalent to `200 OK` (notwithstanding that `294` does not appear in the list of status codes that are [heuristically cacheable](https://httpwg.org/specs/rfc9110.html#overview.of.status.codes)). Note: Infrastructure may apply specific behaviors based on a fixed list of status codes; because `294` is unlikely to appear in such lists by default, `294` might be handled differently from `200`. Implementers should verify that clients, servers, and intermediaries behave as intended for every status code in use, including `294`, particularly with respect to caching and header handling. ## Security This specification focuses solely on the intersection of GraphQL and HTTP. General concerns of either technology, including security concerns, are out of scope, except where their interaction introduces additional considerations. ### HTTP Implementers are expected to have a solid understanding of the security implications of exposing a service over HTTP, and are responsible for implementing relevant mitigations and solutions. This specification will not repeat standard HTTP best practices such as not using `GET` for requests with side effects, safe logging of requests without revealing sensitive information, ensuring all connections are encrypted via HTTPS, placing limits on the length of incoming data, implementing rate limits, authorization and authentication security, request tracing, intrusion detection, and so on. ### GraphQL Implementers are further expected to have a solid understanding of the security implications of running a GraphQL service and are responsible for implementing relevant mitigations and solutions there. For example, they may: limit the size and token count of GraphQL documents; ensure document validity; limit the number of errors a response may return; limit information revealed via errors; enforce validation and execution timeouts and pagination limits; implement query depth and complexity limits; implement authentication and authorization; apply rate limits to critical logic; and so on. ### Exercise caution Where this specification leaves flexibility for the implementer, the implementer should be very cautious when exercising this freedom. Implementers must make themselves aware of and account for the security implications of their choices; while many alternative choices can be secured, securing them is outside of the scope of this specification. For example, this specification allows alternative media types to be used to encode the request body; however, media types such as `multipart/form-data` or `application/x-www-form-urlencoded` may result in the request being treated by a browser as a "simple request", which does not require a "preflight", thereby opening the server up to Cross-Site Request Forgery (CSRF/XSRF) attacks. The recommended `application/json` media type requires a "preflight" check when issued cross-domain. See [CORS protocol](https://fetch.spec.whatwg.org/#http-cors-protocol) in the WHATWG Fetch spec for more details on this. Note: One approach used by the community to mitigate CSRF risks is to ensure a request is not "simple" by requiring a custom header—such as `GraphQL-Require-Preflight`—is included. The presence of a custom header forces browsers to enact a "preflight" check, thereby adding an additional layer of security. (This is not a standard header, and many alternative headers could serve the same purpose. This is presented merely as an example of a pattern seen in the community.) Further extending this example, using `multipart/form-data` may allow large values to be referenced multiple times in a GraphQL operation, potentially causing the GraphQL service to process a much larger GraphQL request than the HTTP request size would suggest. ### Other resources For more detailed security considerations, please refer to [IETF RFC 9110](https://httpwg.org/specs/rfc9110.html), [IETF RFC 6454](https://tools.ietf.org/html/rfc6454), other relevant RFCs, and other resources such as [OWASP](https://owasp.org). ## Future compatibility Supporting formats not described by this specification may have potential conflicts with future versions of this specification as ongoing development aims to standardize and ensure the security and interoperability of GraphQL over HTTP while accounting for its growing feature set. For this reason, it is recommended to adhere to the officially recognized formats outlined here.