I can’t seem to find any documentation regarding the setup for Apollo Server to support subscriptions over HTTP multipart. The RFC specifies Apollo Server as an implementation, and the client docs talk about it too, but I can’t seem to find anything on how to properly set up the server side.
Currently I am observing that Apollo Client is sending the correct request + headers, but Apollo Server is trying to call the resolve
function rather than the subscribe
function, resulting in a failed subscription and null
being sent back to the client.
Here is my setup (partially redacted):
// main.ts
async function bootstrap() {
const app = express()
const httpServer = http.createServer(app)
app.use(cors({origin: process.env.CLIENT_URL}))
app.use(express.json({limit: '50mb'}))
app.use(express.urlencoded({extended: true}))
app.use(cookieParser())
/* GraphQL */
const typeDefs = readFileSync('./graphql/schema.graphql').toString('utf-8')
const resolvers = Resolvers({prisma, sync})
const server = new ApolloServer({
typeDefs,
resolvers,
allowBatchedHttpRequests: true,
plugins: [ApolloServerPluginDrainHttpServer({httpServer})]
})
await server.start()
app.use('/graphql', expressMiddleware(server))
/* start server */
const port = process.env.PORT || 5050
httpServer.listen(port, () => {
if (process.env.NODE_ENV === 'development') {
logger.info(`GraphQL Server available at http://localhost:${port}/graphql`)
}
})
}
bootstrap()
# schema.graphql
scalar DateTime
# ... redacted ...
type Subscription {
time: DateTime
}
// resolvers.ts
export function Resolvers({prisma, sync}: {prisma: ExtPrismaClient; sync: PubSub}): Resolvers {
return {
DateTime: DateTimeResolver,
Query: {
// ... redacted ...
},
Subscription: {
time: {
subscribe: async function* () {
// basic subscription example
console.log("Subscribe called")
while (true) {
yield {time: new Date()}
await new Promise(resolve => setTimeout(resolve, 1000))
}
}
}
}
}
}
Note that the Subscribe called
log message never displays.
Here is what the request / response is looking like.
Relevant request headers sent by Apollo Client:
{
accept: 'multipart/mixed; boundary="graphql"; subscriptionSpec=1.0, application/json',
connection: 'keep-alive'
}
Info from Apollo Server (logged using a custom plugin):
GraphQL request started.
GraphQL Operation: Subscription
GraphQL Query:
subscription Subscription {
time
}
GraphQL response being sent:
{
"http": {
"headers": {}
},
"body": {
"kind": "single",
"singleResult": {
"data": {
"time": null
}
}
}
}
Any help is appreciated. Thanks!