3.2 KiB
title | subtitle |
---|---|
Subscriptions | Adding subscriptions to Apollo Server |
The native Apollo Server 2.0 supports GraphQL subscriptions without additional configuration. Subscriptions are GraphQL operations that watch events emitted from Apollo Server. All integration that allow http servers, such as express and hapi, contain the ability support GraphQL subscriptions As example we want to display a list of post that contains author and comment (Query) and we want to add a post to them (Mutation).
The following examples use a publish and subscribe primitive to generate the events that notify a subscription.
const { PubSub } = require('apollo-server');
const pubsub = new PubSub();
To enable subscription we add them to our schema:
const typeDefs = gql`
type Subscription {
postAdded: Post
}
type Query {
posts: [Post]
}
type Mutation {
addPost(author: String, comment: String): Post
}
type Post {
author: String
comment: String
}
`
Our resolver map:
const POST_ADDED = 'POST_ADDED';
const postResolver = {
Subscription: {
postAdded: {
subscribe: () => pubsub.asyncIterator([POST_ADDED]),
},
},
Query: {
posts(root: any, args: any, context: any) {
return postController.posts();
},
},
Mutation: {
addPost(root: any, args: any, context: any) {
pubsub.publish(POST_ADDED, { postAdded: args });
return postController.addPost(args);
},
},
};
export default postResolver;
Context with Subscriptions
The function to create a context for subscriptions includes connection
, while the function for Queries and Mutations contains the arguments for the integration, in express's case req
and res
. This means that the context creation function needs to check the input. This is especially important, since the auth tokens are handled differently depending on the transport:
const server = new ApolloServer({
schema,
context: async ({ req, connection }) => {
if (connection) {
// check connection for metadata
return {};
} else {
// check from req
const token = req.headers.authorization || "";
return { token };
}
},
});
As you can see Apollo Server 2.0 allows realtime data without invasive changes to existing code. For a full working example please have a look to this repo provided by Daniele Zurico
Subscriptions with Additional Middleware
With an existing HTTP server (created with createServer
), wecan easily add subscriptions.
For example: with an Express server already running on port 4000 that accepts GraphQL HTTP connections (POST) we can expose the subscriptions:
const http = require('http');
const { ApolloServer } = require('apollo-server-express');
const express = require('express');
const PORT = 4000;
const app = express();
const server = new ApolloServer({ typeDefs, resolvers });
server.applyMiddleware({app})
const httpServer = http.createServer(app);
server.installSubscriptionHandlers(httpServer);
httpServer.listen(PORT, () => console.log(`🚀 Server ready at http://localhost:${PORT}${server.graphqlPath}`))