Skip to content

Add RFC for incremental delivery #124

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 3, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions rfcs/IncrementalDelivery.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Incremental Delivery over HTTP

This RFC proposes adding a specification of how "Incremental" GraphQL results should be delivered to clients, using HTTP chunked transfer encoding.

## Incremental Results

An Incremental result is a GraphQL result that is split up into multiple payloads, allowing clients quicker access to parts of the results. Currently this is supported by the proposed `@defer` and `@stream` directives ([RFC](https://github.com/graphql/graphql-spec/blob/master/rfcs/DeferStream.md)).

## `transfer-encoding: chunked`

The HTTP response for an incrementally delivered response should contain the `transfer-encoding: chunked` response header. Chunked transfer encoding allows the body of the response to be delivered as a series of chunks, allowing clients to read each chunk of the response as it is sent without waiting for the entire response.

## `content-type: multipart/mixed`

The HTTP response for an incrementally delivered response should contain the `content-type: multipart/mixed; boundary="-"` response header and conform to the [specification of multipart content defined by the W3 in rfc1341](https://www.w3.org/Protocols/rfc1341/7_2_Multipart.html). An example response body will look like:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Must the boundary be "-" specifically? Could other boundaries be used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should support arbitrary boundaries. fetch-multipart-graphql currently only supports "-" but I will update that and this document to allow any boundary.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@benjie @robrichard Sorry, I didn't notice this comment before merging.
On the last "GraphQL over HTTP" WG we decided on merging and just forgot to actually do it.
Hope it didn't disrupt your workflow and @benjie suggestion can be addressed as separate PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've filed an issue here: #135 (@IvanGoncharov if you could assign it to @robrichard that would be helpful).


```
---
Content-Type: application/json; charset=utf-8
Content-Length: 45

{"data":{"hello":"Hello Rob"},"hasNext":true}

---
Content-Type: application/json; charset=utf-8
Content-Length: 57

{"data":{"test":"Hello World"},"path":[],"hasNext":false}

-----
```
* The boundary used is `-` and is passed to the client in the http response's content-type header.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I co not see this in the example above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The content-type: multipart/mixed; boundary="-" header should be in the HTTP response headers. The example is the HTTP response body. Each part of the response body contains it's own set of headers, but the header defining the boundary needs to be on the HTTP response, not in the body.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's worth mentioning

* Each part of the multipart response must start with `---` and a `CRLF`
* Each part of the multipart response must contain a `Content-Type` header. Similar to the GraphQL specification this specification does not require a specific serialization format. For consistency and ease of notation, examples of the response are given in JSON throughout the spec.
* Each part of the multipart response must contain a `Content-Length` header. This should be the number of bytes of the payload of the response. It does not include the size of the headers, boundaries, or `CRLF`s used to separate the content.
* After all headers, an additional `CRLF` is sent.
* The payload is sent, followed by two `CRLF`s.
* After the last part of the multipart response is sent, the terminating boundary `-----` is sent, followed by a `CRLF`

## Server Implementations
* `express-graphql`: [pull request](https://github.com/graphql/express-graphql/pull/583)

## Client Implementations
* [fetch-multipart-graphql](https://github.com/relay-tools/fetch-multipart-graphql) - Browser support using `fetch` or `XMLHttpRequest`