Kind of a newbie here. Searched through multiple google pages and couldn't find the solution. I have a pretty simple Express server setup looking like this:
// import cors from 'cors';
import express from 'express';
import { createServer } from 'http';
// import httpProxy from 'http-proxy'; // Possible use for this problem?
import { graphqlExpress, graphiqlExpress } from 'graphql-server-express';
import bodyParser from 'body-parser';
import { SubscriptionServer } from 'subscriptions-transport-ws';
import { execute, subscribe } from 'graphql';
import schema from './graphql/schema';
// import router from './routers';
const server = express();
// server.use(bodyParser.json({ type: '*/*' }));
// server.use(cors({ origin: '*' }));
// Constants:
const port = 1338;
const graphqlPath = '/graphql';
const subscriptionsPath = '/subscriptions';
const subscriptionsEndpoint = `ws://localhost:${port}${subscriptionsPath}`;
// GraphQL endpoint setup:
server.use(
graphqlPath,
bodyParser.json(),
graphqlExpress({
schema,
context: {},
}),
);
// GraphQL subscription setup
// GraphiQL console setup:
server.use(
'/graphiql',
graphiqlExpress({
endpointURL: graphqlPath,
subscriptionsEndpoint,
}),
);
// Authorization setup (for possible future use)
// router.auth(server);
const graphQLServer = createServer(server);
graphQLServer.listen(port, () => {
console.log(`GraphQL Server is now running on http://localhost:${port}${graphqlPath}`);
console.log(`GraphQL Subscriptions are now running on ${subscriptionsEndpoint}`);
});
// eslint-disable-next-line no-unused-vars
const subscriptionServer = SubscriptionServer.create({
schema,
execute,
subscribe,
}, {
server: graphQLServer,
path: subscriptionsEndpoint,
});
Queries and mutations are working like a champ, but when it comes to subscriptions all I get is a console error saying me:
Error during WebSocket handshake: Unexpected response code: 400
Any ideas?
Feel your pain! I don' t know how I get it working. But maybe my code will help you. It is working for me.
Don' t forget! You should always attach error handling to listen callback
```JavaScript
const express = require('express')
const bodyParser = require('body-parser')
const {graphqlExpress, graphiqlExpress} = require('apollo-server-express')
const {createServer} = require('http')
const {execute, subscribe} = require('graphql')
const {SubscriptionServer} = require('subscriptions-transport-ws')
const schema = require('./schema')
const PORT = 3000
const app = express()
app.use('/graphql', bodyParser.json(), graphqlExpress({schema}))
app.use('/graphiql', graphiqlExpress({
endpointURL: '/graphql',
subscriptionsEndpoint: ws://localhost:${PORT}/subscriptions
}))
const server = createServer(app)
server.listen(PORT, err => {
if (err) {
throw new Error(err)
}
new SubscriptionServer({
execute,
subscribe,
schema
},
{
server,
path: '/subscriptions'
})
console.log('Server loaded')
})```
Thanks buddy! I've also made this work, somehow, after reading dozen of tutorials and docs. There should be better examples provided as it seems that I'm not alone. My code looks pretty similar to yours!
You have SubscriptionServer outside listen callback, maybe this is the problem. Instructions unclear.
In my case it required an Nginx configuration for a successful switch of protocols and ws connection:
http {
...
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
...
}
server {
...
location / {
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://127.0.0.1:8080;
proxy_redirect off;
}
location /subscriptions {
proxy_pass http://127.0.0.1:8080/subscriptions;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
(_GraphQL is running on port 8080_)
I hope this is helpful.
Could you please tell me and explain @mjasnikovs . why request headers looks like this Sec-WebSocket-Protocol:graphql-ws , because this custom header maybe come seperated issues on the platform agnostic, WebSocket Spec - section subprotocol , lets say on java platform java-graphql and Spring-Boot-Websocket, or this module specific development for Node.js ?
Per https://github.com/apollographql/apollo-client/issues/4778#issuecomment-509638071
try 'ws://localhost:4000/graphql'
Most helpful comment
In my case it required an Nginx configuration for a successful switch of protocols and ws connection:
(_GraphQL is running on port 8080_)
I hope this is helpful.