From 7c6f594dc4cee337134498926d39fe81c1c5cb5d Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 29 Sep 2025 16:24:49 -0600 Subject: [PATCH 1/4] Add test to ensure payload only contains known keys --- .../subscriptions/__tests__/graphqlWsLink.ts | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/link/subscriptions/__tests__/graphqlWsLink.ts b/src/link/subscriptions/__tests__/graphqlWsLink.ts index 92c32aebe3e..82c731f1722 100644 --- a/src/link/subscriptions/__tests__/graphqlWsLink.ts +++ b/src/link/subscriptions/__tests__/graphqlWsLink.ts @@ -6,7 +6,10 @@ import type { Observable } from "rxjs"; import { CombinedGraphQLErrors } from "@apollo/client/errors"; import { GraphQLWsLink } from "@apollo/client/link/subscriptions"; -import { executeWithDefaultContext as execute } from "@apollo/client/testing/internal"; +import { + executeWithDefaultContext as execute, + ObservableStream, +} from "@apollo/client/testing/internal"; const query = gql` query SampleQuery { @@ -175,3 +178,31 @@ describe("GraphQLWSlink", () => { }); }); }); + +// https://github.com/apollographql/apollo-client/issues/12946 +test("sends only known keys to the GraphQLWsLink", async () => { + const knownKeys = [ + "query", + "variables", + "operationName", + "extensions", + ].sort(); + + type SubscribeFn = Client["subscribe"]; + const subscribe = jest.fn, Parameters>( + (_payload, sink) => { + sink.complete(); + return () => {}; + } + ); + const client = mockClient(subscribe); + const link = new GraphQLWsLink(client); + + const stream = new ObservableStream(execute(link, { query: subscription })); + await stream.takeComplete(); + + expect(subscribe).toHaveBeenCalledTimes(1); + + const payload = subscribe.mock.calls[0][0]; + expect(Object.keys(payload).sort()).toStrictEqual(knownKeys); +}); From c3ecc96ceb7756b3d6b05d07669554d86d8884c9 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 29 Sep 2025 16:26:15 -0600 Subject: [PATCH 2/4] Filter out operationType in payload --- src/link/subscriptions/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/link/subscriptions/index.ts b/src/link/subscriptions/index.ts index 7f6295117fe..771cf34641e 100644 --- a/src/link/subscriptions/index.ts +++ b/src/link/subscriptions/index.ts @@ -79,8 +79,9 @@ export class GraphQLWsLink extends ApolloLink { operation: ApolloLink.Operation ): Observable { return new Observable((observer) => { + const { operationType, ...request } = operation; return this.client.subscribe( - { ...operation, query: print(operation.query) }, + { ...request, query: print(operation.query) }, { next: observer.next.bind(observer), complete: observer.complete.bind(observer), From f70756ee9fdf7dc849426c608e89b96478d9ef41 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Mon, 29 Sep 2025 16:27:35 -0600 Subject: [PATCH 3/4] Add changeset --- .changeset/healthy-jokes-sing.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/healthy-jokes-sing.md diff --git a/.changeset/healthy-jokes-sing.md b/.changeset/healthy-jokes-sing.md new file mode 100644 index 00000000000..3b48e7780e9 --- /dev/null +++ b/.changeset/healthy-jokes-sing.md @@ -0,0 +1,5 @@ +--- +"@apollo/client": patch +--- + +Don't send `operationType` in the payload sent by `GraphQLWsLink`. From 70fd5f71909df4699eabcc0211dd83d52c5fb990 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Tue, 30 Sep 2025 11:59:42 -0600 Subject: [PATCH 4/4] Destructure properties --- src/link/subscriptions/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/link/subscriptions/index.ts b/src/link/subscriptions/index.ts index 771cf34641e..2a3ab8e7e0c 100644 --- a/src/link/subscriptions/index.ts +++ b/src/link/subscriptions/index.ts @@ -79,9 +79,9 @@ export class GraphQLWsLink extends ApolloLink { operation: ApolloLink.Operation ): Observable { return new Observable((observer) => { - const { operationType, ...request } = operation; + const { query, variables, operationName, extensions } = operation; return this.client.subscribe( - { ...request, query: print(operation.query) }, + { variables, operationName, extensions, query: print(query) }, { next: observer.next.bind(observer), complete: observer.complete.bind(observer),