Google App Engine上的Websockets无法工作

13

我最近将一个使用socket.io与客户端应用通信的node.js服务器应用程序部署到Google App Engine。根据这篇文章,App Engine现在支持WebSockets。

然而,客户端应用无法通过wss协议连接到服务器。我可以在浏览器控制台中看到以下错误消息。(我删除了我的服务器域名)

WebSocket连接到'wss://[my server]/socket.io/?EIO=3&transport=websocket&sid=dbB2UgsCYhD7c1ucAAAA'失败:WebSocket握手期间出错:意外的响应代码:400

于是Socket.io退回到https长轮询,这很好用。

这是我用于部署到App Engine的app.yaml文件,其中session_affinity设置为true以进行长轮询。

runtime: nodejs10

instance_class: F2

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

network:
  session_affinity: true

Socket.io在服务器上以简单直接的方式使用:

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!');
  });
});

我想知道如何在App Engine上使WebSocket连接工作?也许需要防火墙规则或其他配置更改吗?

1个回答

12
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);

截至目前,WebSockets仅在App Engine的Flexible环境中得到支持。从您指定的instance_classinstance_class: F2,我看到您正在标准环境中部署应用程序。因此,我建议将环境从标准环境更改为灵活环境,请参见此处了解Flex中的app.yaml配置文件。这样做将允许您利用最近在App Engine中实现的WebSockets功能。


谢谢提供信息。您知道吗,如果我切换到灵活环境,是否仍然可以在app.yaml中使用handlers部分?弹性文档没有列出该部分:https://cloud.google.com/appengine/docs/flexible/nodejs/reference/app-yaml - wooters
很抱歉,handlers 只能在 App Engine Standard 中使用。但你可以通过编写代码来创建路由处理程序。就个人而言,我以前使用过 express-ws,如果你有编写 express.js 应用程序的经验,它可以让你编写类似于任何其他路由处理程序的 WebSockets 终端点。 - JKleinne
再次感谢。我想我的唯一担忧是如何在Flex环境中将流量从HTTP重定向到HTTPS。 - wooters
1
没关系,你也可以通过代码强制使用 HTTPS。假设使用了express-ws,您可以创建一个中间件,将所有未安全的流量重定向到HTTPS并将其附加到所有HTTP方法的所有路由处理程序上。我相应地编辑了我的答案,以便为您演示这个过程如何工作。 - JKleinne

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接