Subscriptions-transport-ws: Error during WebSocket handshake: Unexpected response code: 400

Created on 16 Aug 2017  路  6Comments  路  Source: apollographql/subscriptions-transport-ws

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?

Most helpful comment

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.

All 6 comments

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 ?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

nickofthyme picture nickofthyme  路  3Comments

altschuler picture altschuler  路  4Comments

anilanar picture anilanar  路  5Comments

n1ru4l picture n1ru4l  路  3Comments

corysimmons picture corysimmons  路  5Comments