6
votes

I recently deployed a node.js server application to Google App Engine that communicates with a client application via socket.io. Accordingly to this article, websockets are now supported on App Engine.

However, the client app is unable to connect to the server over the wss protocol. I can see the following error message in the browser console. (I removed my server domain)

WebSocket connection to 'wss://[my server]/socket.io/?EIO=3&transport=websocket&sid=dbB2UgsCYhD7c1ucAAAA' failed: Error during WebSocket handshake: Unexpected response code: 400

Socket.io then falls back to https long polling, which works well.

Here is my app.yaml for deployment to app engine, with session_affinity set to true for long polling.

runtime: nodejs10

instance_class: F2

handlers:
- url: /.*
  secure: always
  redirect_http_response_code: 301
  script: auto

network:
  session_affinity: true

Socket.io is used on the server in a straightforward way:

this.server = this.app.listen(this.PORT, (err: any) => {
  io = socketio().listen(this.server);
  io.on("connection", (socket) => {
    console.log('A socket connection was made!');
  });
});

I am wondering how to get the websocket connection to work on App Engine? Maybe a firewall rule or other configuration change is needed?

1

1 Answers

8
votes
var express = require('express');
var app = express();
var expressWs = require('express-ws')(app);

const forceSecure = (req, res, next) => {
  if (req.secure)
     return next(); // https -- Continue

  res.redirect('https://' + req.hostname + req.url)
}

/**
* This will force
* ALL HTTP requests ( GET, POST, OPTIONS, etc. )
* on ALL route handlers to be
* redirected to https 
*/
app.all('*', forceSecure);

app.get('/', (req, res, next) => {
  console.log('example');
  res.end();
});

app.ws('/', (ws, req) => {
  ws.on('message', msg => {
    console.log(msg);
  });
  console.log('socket', req.example);
});

app.listen(3000);

As of now, WebSockets are only supported in the Flexible Environment for App Engine. From what I see, you are deploying your application in the Standard Environment, as denoted by the instance_class you specified: instance_class: F2. Thus, I would suggest changing the environment from Standard to Flexible, see here for the app.yaml Configuration File in Flex. Doing so, will allow you to take advantage of the WebSockets functionality recently implemented in App Engine.