1

Can anyone tell me how to implement GraphQL Subscriptions using Express-GraphQL in Node?

dharshini priya
  • 141
  • 1
  • 5

4 Answers4

1

I have also run into the same problem. I wasn't able to find a clear solution to this in the documentation. So i have just switched to graphql-yoga instead. But i did find this thread so do check it out

Dagmawi Asfaw
  • 39
  • 1
  • 7
1

I've been researching this same issue.

I've read the GitHub issues for express-graphql subscriptions and a member of that repo suggested using graphql-ws on the closing comment.

Here's a link to my GitHub project shammelburg/express-graphql-api, you can npm start load grapiql to test queries and mutation.

To test subscriptions, I've created an Angular project which implements graphql-ws's observables example. shammelburg/graphql-rxjs-angular

The Angular project also uses graphql-request for queries and mutations.

This is a very lightweight solution and works perfectly.

shammelburg
  • 6,974
  • 7
  • 26
  • 34
0

They've added the doc fragment mentioning Subscription Support with an example implementation in Nov 2020. But unfortunately that never got released, there's an issue here mentioning that.

My workaround for now's been switching over to Express Playground for the subscriptions-transport-ws socket (Playground doesn't support graphql-ws yet) and Apollo Sandbox for the graphql-ws.

Then my subscription creation options are the following.

Where createScopedPermissionWrapper is just an execute wrapper with @graphql-authz and createGraphqlContext a factory function validating auth and creating a custom context for my resolvers.

import { Server } from 'http'
import { useServer } from 'graphql-ws/lib/use/ws' // subscription with graphql-ws
import { SubscriptionServer } from 'subscriptions-transport-ws' // subscription with subscriptions-transport-ws

export const createSubscriptionsTransportWs = (server: Server) => {
  const wsServer = new SubscriptionServer(
    {
      schema,
      execute: createScopedPermissionWrapper(),
      subscribe,
      onConnect: (args: { authentication?: string }) =>
        createGraphqlContext({
          authentication: args.authentication,
        }),
    },
    { server, path }
  )

  const wsAddress = wsServer.server.address() as AddressInfo
  depClients.logger.success(
    `Graphql subscription socket up on ${wsAddress.address}:${wsAddress.port}${path}`
  )
}

export const createGraphqlWS = (server: Server) => {
  const wsServer = new ws.Server({ server, path })

  useServer(
    {
      schema,
      execute: createScopedPermissionWrapper(),
      subscribe,
      context: (args: { connectionParams: { authentication?: string } }) =>
        createGraphqlContext({
          authentication: args.connectionParams.authentication,
        }),
    },
    wsServer
  )

  const wsAddress = wsServer.address() as AddressInfo
  depClients.logger.success(
    `Graphql subscription socket up on ${wsAddress.address}:${wsAddress.port}${path}`
  )
}
Alan Bueno
  • 131
  • 1
  • 8
-3

See Authentication and Express Middleware

var express = require('express');
var graphqlHTTP = require('express-graphql');
var { buildSchema } = require('graphql');

var schema = buildSchema(`
  type Query {
    ip: String
  }
`);

const loggingMiddleware = (req, res, next) => {
  console.log('ip:', req.ip);
  next();
}

var root = {
  ip: function (args, request) {
    return request.ip;
  }
};

var app = express();
app.use(loggingMiddleware);
app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: root,
  graphiql: true,
}));
app.listen(4000);
console.log('Running a GraphQL API server at localhost:4000/graphql');