Search code examples
httpcurlwebsocketgraphqlgraphql-subscriptions

Curl command for GraphQL Subscriptions


When I tried to run a subscription using the cURL command, it always send the response with null data. Is there any way to keep returning the correct responses according to the event changes?

I used the following js code to run the GraphQL server.

const { createServer } = require("http");
const express = require("express");
const { execute, subscribe } = require("graphql");
const { ApolloServer, gql } = require("apollo-server-express");
const { PubSub } = require("graphql-subscriptions");
const { SubscriptionServer } = require("subscriptions-transport-ws");
const { makeExecutableSchema } = require("@graphql-tools/schema");
const { withFilter } = require("graphql-subscriptions");

(async () => {
    
    const pubsub = new PubSub();
    const app = express();
    const httpServer = createServer(app);

    const typeDefs = gql`

    type Query {
      viewMessages: [Message!]
    }
    type Mutation {
      sendMessage(params: DataInput): Message!
    }
    type Subscription {
      receiveMessage(content: String): Message
    }
    type Message {
        id: ID!
        name: String!
        content: String
    }
    input DataInput {
      name: String 
      content: String
    }
  `;
  
  let messages = []
  const resolvers = {
    Query: {
      viewMessages() {
        return messages;
      },
    },
    Mutation: {
      sendMessage: (parent, { params }) => {
        params.id = messages.length;
        var new_message = params;
        messages.push(new_message);
        pubsub.publish("MessageService", {receiveMessage: new_message});
        return new_message;
      },
    },
    Subscription: {
      receiveMessage: {

        subscribe: withFilter(
          () => pubsub.asyncIterator(["MessageService"]),
          (payload, variables) => {return (payload.receiveMessage.content === variables.content)},
        ),          
      },
    },
  };

  const schema = makeExecutableSchema({ typeDefs, resolvers });

  const server = new ApolloServer({
    schema,
  });
  await server.start();
  server.applyMiddleware({ app });

  SubscriptionServer.create(
    { schema, execute, subscribe },
    { server: httpServer, path: '/graphql' }
  );
  const PORT = 4000;
  httpServer.listen(PORT, () => {
    console.log(
      `🚀 Query endpoint ready at http://localhost:${PORT}${server.graphqlPath}`
    );
    console.log(
      `🚀 Subscription endpoint ready at ws://localhost:${PORT}${server.graphqlPath}`
    );
  });

})();

I used the following cURL command to run the the subscription query: subscription { receiveMessage { id name } }

curl 'http://localhost:4000/graphql' -H 'Content-Type: application/json' -H 'Connection: keep-alive' -d '{"query":"subscription { receiveMessage { id name } }"}'

The response for the cURL command is as follows.

{"data": {"receiveMessage": null}}

What I need to do is keep getting responses from a subscription using a cURL command, while running mutations parallelly. Can this be done? If it is, how do I write a cURL command for that?

*** For query and mutations, the cURL commands are working properly.


Solution

  • I'm not certain you can run subscriptons through curl.

    Even though curl does support a pretty good list of protocol, you won't be able to get your subscriptions through http (that is : the client sends a request and the server sends the reply) while subscriptions (the server notifies the client when an event occurs) aren't suitable for http.