createGraphiQLFetcher: support subscriptions over HTTP multipart/mixed (Apollo subscriptionSpec=1.0), not just WebSockets

Open
#4,386 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
58/100
Issue type
Feature
Clarity
Mostly clear
Activity status
Quiet
Tech stack
graphql, typescript
Domain
api, tooling

Research direction

Read create-fetcher/createFetcher.ts, especially the subscription branch and getWsFetcher, then compare its existing createMultipartFetcher path. Trace how meros is used for multipart responses. Done means an explicitly configured HTTP subscription can yield each payload, skip heartbeat parts, and stop on fatal errors or the closing boundary without affecting WebSocket subscriptions.

Written by the indexing model from the issue text.

Description

Is your feature request related to a problem? Please describe.

createGraphiQLFetcher hardwires every subscription operation to a WebSocket transport. In create-fetcher/createFetcher.ts, once an operation is detected as a subscription it goes straight to getWsFetcher:

if (isSubscription) {
  const wsFetcher = await getWsFetcher(options, fetcherOpts);
  if (!wsFetcher) {
    throw new Error(
      `Your GraphiQL createFetcher is not properly configured for websocket subscriptions yet. …`,
    );
  }
  return wsFetcher(graphQLParams);
}

and getWsFetcher only ever resolves from wsClient / subscriptionUrl / legacyClient — all WebSocket. There is no code path that lets a subscription be delivered over HTTP.

This blocks a mainstream setup: servers that deliver subscriptions over HTTP multipart/mixed using the Apollo multipart subscription protocol (subscriptionSpec=1.0), which is what Apollo Client + Apollo Router/GraphOS use by default. For these APIs there is no WebSocket endpoint at all — subscriptions ride the same HTTP endpoint as queries/mutations. Pointing GraphiQL at such an API makes queries/mutations work, but any subscription throws the "not properly configured for websocket subscriptions" error, even though the transport is plain HTTP that the fetcher is otherwise already talking to.

Note this is distinct from the existing multipart support: createMultipartFetcher handles @defer/@stream incremental delivery (deferSpec, { hasNext, incremental } frames) and is only wired to queries/mutations. Apollo multipart subscriptions are a different framing ({ payload } envelopes + heartbeats), so the existing multipart reader can't be reused as-is, and subscription ops never reach it anyway.

Describe the solution you'd like

Let createGraphiQLFetcher deliver subscriptions over HTTP multipart when configured/negotiated — e.g. an opt-in option such as subscriptionSpec: '1.0' (or auto-detection), routing subscription operations to a multipart reader instead of getWsFetcher when no WS client is configured. The reader would:

  • POST to options.url with Accept: multipart/mixed;subscriptionSpec="1.0", application/json (boundary graphql)
  • yield part.payload for each message part (containing data / errors / extensions)
  • silently skip heartbeat parts ({})
  • terminate on the fatal-error frame ({ "payload": null, "errors": [...] }) and on the closing boundary

meros (already a dependency) can parse the stream; only the per-part envelope handling differs from the @defer path.

Describe alternatives you've considered

  • Consumer-side custom fetcher — works, but every GraphiQL-based tool sitting in front of an Apollo Router/Client stack has to reimplement the same multipart subscription reader. First-class support in the toolkit is the natural home.
  • graphql-sse / SSE — a different protocol; GraphiQL's current EventSource handling isn't graphql-sse-compliant either (enisdenjo/graphql-sse#8), so it's not an out-of-the-box path.

Additional context

Dominant language
TypeScript
Stars
16.9k
Forks
1.9k
Avg merge
14h 1m
Merged PRs (30d)
81

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from graphql/graphiql

All issues in graphql/graphiql

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.