99designs / gqlgen

go generate based graphql server library
https://gqlgen.com
MIT License
9.94k stars 1.16k forks source link

`@defer` support with `accept: multipart/mixed` header rather than `accept: text/event-stream` #3335

Open giulio-opal opened 1 day ago

giulio-opal commented 1 day ago

What happened?

I'm using Apollo GraphQL on the frontend, which automatically passes accept: multipart/mixed as header when the query contains a @defer directive. Unfortunately this causes the gqlgen server to expire the context and actually not return the deferred fields.

If I were to use accept: text/event-stream as header, the gqlgen server actually handles the context correctly and returns the deferred data.

Example:

 ▲ ~/work/gqlgen-todos curl 'http://localhost:8080/query' -H 'Connection: keep-alive' -H 'accept: text/event-stream' -H 'content-type: application/json; charset=utf-8' --data-raw '{"query":"query test { todos { ... on Todo @defer { user { id } } } }"}'
:

event: next
data: {"data":{"todos":[{"user":null},{"user":null}]},"hasNext":true}

event: next
data: {"data":{"user":{"id":"1"}},"path":["todos",1],"hasNext":true}

event: next
data: {"data":{"user":{"id":"1"}},"path":["todos",0],"hasNext":false}

event: complete

 ▲ ~/work/gqlgen-todos curl 'http://localhost:8080/query' -H 'Connection: keep-alive' -H 'accept: multipart/mixed' -H 'content-type: application/json; charset=utf-8' --data-raw '{"query":"query test { todos { ... on Todo @defer { user { id } } } }"}'
{"data":{"todos":[{"user":null},{"user":null}]},"hasNext":true}%

What did you expect?

Context to not expire and subsequent multipart responses returned to the frontend.

Is there an additional configuration that needs to be set up in the gqlgen server or in Gin that I might be missing?

Minimal graphql.schema and models to reproduce

Example repo based off the official documentation with gin: https://github.com/giulio-opal/defer-gqlgen-todo-example

It also contains a custom playground (GraphiQL) based off https://github.com/99designs/gqlgen/issues/2771#issuecomment-1694692940

versions

tlbonum commented 1 day ago

I'm experiencing the same issue as mentioned (but using echo instead of gin). An interesting observation is that if I send the query through an apollo router, it works. I know it's not a solution to the problem posted, just thought it would be worth mentioning.