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

Error: Invalid message #348

Closed
nobletom123 opened this issue Apr 13, 2022 · 4 comments
Closed

Error: Invalid message #348

nobletom123 opened this issue Apr 13, 2022 · 4 comments
Labels
unrelated Not relevant, related or caused by the lib

Comments

@nobletom123
Copy link

**Screenshot
Screenshot 2022-04-13 at 08 55 50
**
Screenshot 2022-04-13 at 08 57 39

Expected Behaviour
I expected the @apollo/client to use this package to successfully set up a websocket subscription.

Actual Behaviour
It seems to successfully connect but then I get an Error: Invalid Message.

Debug Information
Apparently the error originates from common.ts. I'm not sure what part of the isMessage function this error is thrown - it looks as thought it may be from line 231 - in that

case MessageType.ConnectionAck:
      case MessageType.Ping:
      case MessageType.Pong:
        // the connection ack, ping and pong messages can have optional payload object too
        return (
          !hasOwnProperty(val, 'payload') ||
          val.payload === undefined ||
          isObject(val.payload)
        );

!hasOwnProperty would return false on

{ payload: null, type: 'connection_ack' }

as the key does exist. It would return false on undefined, and is not object?

I.e, walking through the repo and creating a basic representation of the above:

const baseHasOwnProperty = Object.prototype.hasOwnProperty;

const valObj = { payload: null, type: 'connection_ack' }

const test = (val) => !baseHasOwnProperty.call(val, 'payload') || val.payload === undefined || typeof val.payload === 'object' && val.payload !== null;

console.log('return value', test(valObj))

Return value will be false? I may be mistaken but a null payload on a websocket connection ack should not be considered a failure?

Further Information
Trying to get a subscription working with @apollo/client and this package. this is my config:

import {
  ApolloClient,
  createHttpLink,
  InMemoryCache,
  split,
} from "@apollo/client";
import { GraphQLWsLink } from "@apollo/client/link/subscriptions";
import { createClient } from "graphql-ws";
import { w3cwebsocket } from "websocket";
import { setContext } from "@apollo/client/link/context";
import { getMainDefinition } from "@apollo/client/utilities";

const httpLink = createHttpLink({
  uri: process.env.NEXT_PUBLIC_BACKEND_URL!,
  // ...(isLive && { credentials: "include" }),
});

const wssLink = new GraphQLWsLink(
  createClient({
    url: process.env.NEXT_PUBLIC_WSS_URL!,
    connectionParams: async () => {
      const token = await checkAuth0Token();
      return {
        token,
        workspaceId: process.env.NEXT_PUBLIC_WSID,
        environmentName: process.env.NEXT_PUBLIC_8BASE_ENV,
      };
    },
    webSocketImpl: class WebSocketWithoutProtocol extends w3cwebsocket {
      constructor(url: string) {
        super(url); // ignore protocol
      }
    },
  })
);

export const checkAuth0Token = async () => {
  if (typeof window !== "undefined") {
    const res = await fetch("/api/session");
    if (res.ok) {
      const ses = await res.json();
      return ses?.idToken || null;
    }
  }
};

const authLink = setContext(async (_, { headers }) => {
  // get the authentication token from local storage if it exists
  const token = await checkAuth0Token();
  // return the headers to the context so httpLink can read them
  return {
    headers: {
      ...headers,
      authorization: token ? `Bearer ${token}` : "",
      // ...(isLive && { credentials: "include" }),
    },
  };
});

const cache = new InMemoryCache();

const splitLink = split(
  ({ query }) => {
    const definition = getMainDefinition(query);

    return (
      definition.kind === "OperationDefinition" &&
      definition.operation === "subscription"
    );
  },
  wssLink,
  authLink.concat(httpLink)
);

const client = new ApolloClient({
  link: splitLink,
  cache,
  credentials: "include",
});

const isLive =
  process.env.NEXT_PUBLIC_FRONTEND_URL === "https://www.new-union.io";

const createBasicClient = (token: string, uri?: string) => {
  const httpLink = createHttpLink({
    uri: uri || process.env.NEXT_PUBLIC_BACKEND_URL!,
  });

  const authLink = setContext((_, { headers }) => {
    // get the authentication token from local storage if it exists
    return {
      headers: {
        ...headers,
        authorization: token || "",
      },
    };
  });

  return new ApolloClient({
    link: authLink.concat(httpLink),
    cache: new InMemoryCache(),
  });
};

export { client, createBasicClient };

Thanks for the support

@enisdenjo
Copy link
Owner

enisdenjo commented Apr 13, 2022

As per the GraphQL over WebSocket Protocol, the ConnectionAck message payload is either an object or completely omitted (undefined). Same goes for all other messages that contain an optional payload (ConnectionInit, Ping and Pong).

The typings in graphql-ws also represent the same.

Having said that - null as the payload of ConnectionAck message is not allowed - the server you're using is not compliant with the protocol. May I ask which server that is?

Just for extra context, main reason for not allowing null payloads is for reducing the WebSocket message size - you either provide it or completely omit it.

@enisdenjo enisdenjo added the unrelated Not relevant, related or caused by the lib label Apr 13, 2022
@nobletom123
Copy link
Author

So I'm using a BaaS - https://www.8base.com/ to build out my platform

Okay - sure, so the a null payload is actually not allowed per say. So the solution would be to contact the 8base and make this point?

@enisdenjo
Copy link
Owner

enisdenjo commented Apr 13, 2022

Okay - sure, so the a null payload is actually not allowed per say.

That's right, null payload is not allowed in any of the GraphQL over WebSocket messages.

So the solution would be to contact the 8base and make this point?

In case there's nothing you misconfigured - yes. You may also reference this issue to speed up the process.

@nobletom123
Copy link
Author

Thanks for the speedy support - I've let 8base know about this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
unrelated Not relevant, related or caused by the lib
Projects
None yet
Development

No branches or pull requests

2 participants