Reputation: 1974
Previously my apollo setup was listening to subscriptions until I added in socket.io and now my client setup is no longer listening to new data. my server codes seem to be ok based on my testing using graphql playground.
in my browser console, i get the following error message
client.js:652 WebSocket connection to 'ws://localhost:4000/' failed: Error during WebSocket handshake: Unexpected response code: 400
There seems to be some issue with my client side setup to use apollo subscriptions.
Appreciate any pointers? Thanks in advance
import { ApolloClient } from "apollo-client";
import { onError } from "apollo-link-error";
import { ApolloLink, split } from "apollo-link";
import { createUploadLink } from "apollo-upload-client";
import gql from "graphql-tag";
import { withClientState } from "apollo-link-state";
import { InMemoryCache } from "apollo-cache-inmemory";
import { WebSocketLink } from "apollo-link-ws";
import { getMainDefinition } from "apollo-utilities";
import { setContext } from "apollo-link-context";
const cache = new InMemoryCache();
const defaultState = {
currentGame: {
__typename: "currentGame",
teamAScore: 0,
teamBScore: 0,
teamAName: "EAGLES",
teamBName: "LOL"
}
};
const stateLink = withClientState({
cache,
defaults: defaultState,
resolvers: {
Mutation: {
updateGame: (_, { index, value }, { cache }) => {
const query = gql`
query GetCurrentGame {
currentGame @client {
teamAScore
teamBScore
teamAName
teamBName
}
}
`;
const previous = cache.readQuery({ query });
const data = {
currentGame: {
...previous.currentGame,
[index]: value
}
};
cache.writeQuery({ query, data });
return null;
},
resetCurrentGame: (_, d, { cache }) => {
cache.writeData({ data: defaultState });
}
}
}
});
const host = "http://localhost:4000";
// httpLink
const httpLink = createUploadLink({
uri: `${host}/graphql`,
credentials: "same-origin"
});
// wsLink
const wsLink = new WebSocketLink({
uri: `ws://localhost:4000/`,
options: {
reconnect: true
}
});
// using the ability to split links, you can send data to each link
// depending on what kind of operation is being sent
const webLink = split(
// split based on operation type
({ query }) => {
const { kind, operation } = getMainDefinition(query);
return kind === "OperationDefinition" && operation === "subscription";
},
wsLink,
httpLink
);
// authMiddleware
const authLink = setContext(async (req, { headers }) => {
// const token = await AsyncStorage.getItem("@token");
const token = "";
return {
headers: {
...headers,
authorization: token ? `${token}` : ""
}
};
});
const errorLink = onError(({ networkError, graphQLErrors }) => {
if (graphQLErrors) {
graphQLErrors.map(({ message, locations, path }) =>
console.log(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
)
);
}
if (networkError) console.log(`[Network error]: ${networkError}`);
});
export const client = new ApolloClient({
link: ApolloLink.from([authLink, stateLink, errorLink, webLink]),
cache
});
My server side code if required
//! Using Apollo Server Express
const app = express();
const path = "/graphql";
const schema = genSchema();
export const startServer = async () => {
const server = new ApolloServer({
schema,
context: ({ req }: any) => ({
req,
pubsub,
userLoader: userLoader()
})
});
app.use(cors());
app.use(authMiddleware);
app.use("/images", express.static("images"));
app.use(
"graphql",
graphqlUploadExpress({
uploadDir: "/",
maxFileSize: 100000000,
maxFiles: 10
}),
graphqlHTTP({ schema }) as any
);
server.applyMiddleware({ app, path });
//! Added Subscription Handler
const httpServer = createServer(app);
server.installSubscriptionHandlers(httpServer);
const port = process.env.PORT || 4000;
await createConnection();
await httpServer.listen({
port
});
console.log(`Server is running on localhost:${port}${server.graphqlPath}`);
};
Upvotes: 2
Views: 2527
Reputation: 1974
Rectified. My client side apollo setup should point to ws://localhost:4000/graphql and not just ws://localhost:4000/
// wsLink
const wsLink = new WebSocketLink({
uri: `ws://localhost:4000/graphql`,
options: {
reconnect: true
}
});
Upvotes: 2