Skip to content
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

fix(router): send graphql closing boundary to fit Apollo client #1579

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions router-tests/events/nats_events_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,7 @@ func TestNatsEvents(t *testing.T) {
assertMultipartValueEventually(t, reader, "{\"payload\":{\"data\":{\"countFor\":1}}}")
assertMultipartValueEventually(t, reader, "{\"payload\":{\"data\":{\"countFor\":2}}}")
assertMultipartValueEventually(t, reader, "{\"payload\":{\"data\":{\"countFor\":3}}}")
assertLineEquals(t, reader, "")
assertLineEquals(t, reader, "--graphql--")
}()

Expand Down
2 changes: 1 addition & 1 deletion router/core/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ func writeRequestErrors(r *http.Request, w http.ResponseWriter, statusCode int,
// writeMultipartError writes the error response in a multipart format with proper boundaries and headers.
func writeMultipartError(w http.ResponseWriter, requestErrors graphqlerrors.RequestErrors, requestLogger *zap.Logger) error {
// Start with the multipart boundary
prefix := GetWriterPrefix(false, true)
prefix := GetWriterPrefix(false, true, true)
if _, err := w.Write([]byte(prefix)); err != nil {
return err
}
Expand Down
20 changes: 15 additions & 5 deletions router/core/flushwriter.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const (
sseMimeType = "text/event-stream"
heartbeat = "{}"
multipartContent = multipartMime + "; boundary=" + multipartBoundary
multipartStart = "\r\n--" + multipartBoundary
)

type HttpFlushWriter struct {
Expand All @@ -33,6 +34,7 @@ type HttpFlushWriter struct {
sse bool
multipart bool
buf *bytes.Buffer
firstMessage bool
}

func (f *HttpFlushWriter) Complete() {
Expand All @@ -43,7 +45,7 @@ func (f *HttpFlushWriter) Complete() {
_, _ = f.writer.Write([]byte("event: complete"))
} else if f.multipart {
// Write the final boundary in the multipart response
_, _ = f.writer.Write([]byte("--" + multipartBoundary + "--\n"))
_, _ = f.writer.Write([]byte("--\n"))
}
f.Close()
}
Expand Down Expand Up @@ -72,7 +74,10 @@ func (f *HttpFlushWriter) Flush() (err error) {
resp := f.buf.Bytes()
f.buf.Reset()

flushBreak := GetWriterPrefix(f.sse, f.multipart)
flushBreak := GetWriterPrefix(f.sse, f.multipart, f.firstMessage)
if f.firstMessage {
f.firstMessage = false
}
if f.multipart && len(resp) > 0 {
var err error
resp, err = wrapMultipartMessage(resp)
Expand All @@ -83,7 +88,7 @@ func (f *HttpFlushWriter) Flush() (err error) {

separation := "\n\n"
if f.multipart {
separation = "\n"
separation = "\n" + multipartStart
} else if f.subscribeOnce {
separation = ""
}
Expand Down Expand Up @@ -125,6 +130,7 @@ func GetSubscriptionResponseWriter(ctx *resolve.Context, r *http.Request, w http
multipart: wgParams.UseMultipart,
subscribeOnce: wgParams.SubscribeOnce,
buf: &bytes.Buffer{},
firstMessage: true,
}

flushWriter.ctx, flushWriter.cancel = context.WithCancel(ctx.Context())
Expand Down Expand Up @@ -231,12 +237,16 @@ type SubscriptionParams struct {
UseMultipart bool
}

func GetWriterPrefix(sse bool, multipart bool) string {
func GetWriterPrefix(sse bool, multipart bool, firstMessage bool) string {
flushBreak := ""
if sse {
flushBreak = "event: next\ndata: "
} else if multipart {
flushBreak = "\r\n--" + multipartBoundary + "\nContent-Type: " + jsonContent + "\r\n\r\n"
messageStart := ""
if firstMessage {
messageStart = multipartStart
}
flushBreak = messageStart + "\nContent-Type: " + jsonContent + "\r\n\r\n"
}

return flushBreak
Expand Down
Loading