【问题标题】:Websocket error that is only occuring on live server仅在实时服务器上发生的 Websocket 错误
【发布时间】:2021-02-23 11:27:09
【问题描述】:

我的 websocket 发生了奇怪的情况。它给了我错误 Error during WebSocket handshake: Unexpected response code: 200 对于我的一生,我无法弄清楚为什么。

我设置了一个非常相似的服务器,其代码完全相同,服务器和设置完全相同。唯一的区别是一台服务器有一个.com TLD,而另一台服务器有一个.sg TLD。

我已将其简化为最简单的形式,如下所示,错误仍在发生。它肯定在 api 端,而不是前端,因为前端可以连接到 .com TLD。

以下是我认为与问题相关的所有代码。如果您认为可能还有其他区域,请询问,我将发布其他区域。它托管在 AWS Elastic Beanstalk 上。我还将 SSL 证书设置为 domain.com*.domain.com

有人知道为什么会这样吗?

对我来说奇怪的是,我真的用这些精确的设置设置了一个服务器,它工作得非常好。

server.js(package.json 中的起点)

'use strict';

(async function() {

  // Server Setup
  const WSServer = require('ws').Server;
  const app = await require('./app.js');
  const server = require('http').createServer(app);
  const port = 3075;

  // Create web socket server on top of a regular http server
  const wss = new WSServer({
    server: server
  });

  // Also mount the app here
  // server.on('request', app);

  let sendMessage = {
    "connected":"connected to web socket",
  }
  
  wss.on('connection', function connection(ws) {
    ws.send(JSON.stringify(sendMessage));
    ws.on('message', async function incoming(message) {
      let interval = setInterval(async () => {
        console.log("ping");
        ws.send(message);
      }, 500);
    });
    ws.on('close', function close() {
      console.log('/socket connection Closed');
    });
  });

  server.listen(process.env.PORT || port, function() {
    console.log(`AppName https/wss is listening on port ${process.env.PORT || port}`);
  });

})();

app.js(删除了很​​多与这个问题无关的代码)

module.exports = (async function() {

  const {Config,Environments} = await require("./common/config");
  const packageJson = require('./package.json');

  // Handler


  const AuthFunc = await require("./funcs/user/auth");
  const BillingFunc = await require("./funcs/billing/billing");
  const ObjectUtil = require("./utils/object");
  const AccountStatusEnum = require("./enums/account-status").accountStatusEnum;

  const sleep = require('util').promisify(setTimeout);
  const {t} = require('./translations/i18n').i18n;
  const {availableLanguages} = require('./translations/all');


  // Simulate real API calls
  const delayResponse = 250;// milliseconds

  // ==============================================
  // Base setup
  // ==============================================

  process.env.TZ = "Etc/GMT"

  const express     = require('express');
  const app         = express();
  var expressWs = require('express-ws')(app);
  const bodyParser  = require('body-parser');

  app.use(bodyParser.urlencoded({ extended: true }));
  app.use(bodyParser.json());

  app.use(require('express-useragent').express());

  // Cors
  app.use(async function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, auth-id, auth-token, x-csrf-token, _csrf");
    res.header('Access-Control-Allow-Methods', 'PATCH, POST, GET, DELETE, OPTIONS');
    next();
  });

  // ==============================================
  // Auth
  // ==============================================

  const normRoute = (req, res, next) => {
    req.body = (req.body != undefined && req.body != null) ? ObjectUtil.toCamelCaseKeys(req.body) : req.body;

    response(req,res,next(req));
  }

  // Does not need to be logged in but passes user info if logged in
  const passRoute = async (req, res, next) => {
    authRoute(req, res, next, AccountStatusEnum.any, true);
  }

  const authRoute = async (req, res, next, minimumStatus, passRoute) => {
    req.body = (req.body != undefined && req.body != null) ? ObjectUtil.toCamelCaseKeys(req.body) : req.body;

    let authId = (req.headers['auth-id'] !== undefined) ? req.headers['auth-id'] :"";
    let authToken = (req.headers['auth-token'] !== undefined) ? req.headers['auth-token'] : "";

    let r = await AuthFunc.authUser(
                req,
                req.ip,
                req.useragent,
                authId,
                authToken,
                minimumStatus,
              );
    if(r.err.code){
      if(r.err.authError && passRoute){
        response(req,res,next(req,null));
        return false;
      }else{
        response(req,res,r); 
        return false;
      }
    }  

    let user = r.res.user;
    r = await BillingFunc.updateSubStatus(req,user);
    if(r.err.code){ response(req,res,r); return false; }

    if(r.res.userStatus !== undefined){
      user.status = r.res.userStatus;
    }

    response(req,res,next(req,user));
  }

  // ===============================================================
  // Routes
  // ===============================================================

  app.get('/', function(req, res) {
    res.send(
      '<html>'+
        '<head></head>'+
        '<body>'+
          'API is running <br>'+
          'App: '+Config.FrontEnd.AppName+'<br>'+
          'Env: '+Config.Env+'<br>'+
          'Version: '+packageJson.version+'<br>'+
        '</body>'+
      '</html>'
    );  
  });


  // ==============================================
  // Response type
  // ==============================================

  const response = async (req,res,obj) => { 
    await obj;

    Promise.resolve(obj).then(function(val) {
      if(delayResponse >= 1 && (Config.Env === Environments.Local)){
        
        setTimeout(function(){  
          resume(req,res,val);
        }, delayResponse);
        return true;
      } 
      resume(req,res,val);
    });
  }

  const resume = (req,res,obj) => {
    obj = (obj === undefined) ? {} : obj;

    var status = (obj.status !== undefined) ? obj.status : 200;
    // Let status override settings
    if(obj.status === undefined){
      if((obj.err.code)){
        status = 400;
      }else if(obj.res === undefined || ObjectUtil.isEmpty(obj.res)){
        // status = 204;
      }
    }

    let json = {};
    json.err = obj.err;
    json.res = obj.res;

    json = ObjectUtil.toCamelCaseKeys(json);
    res.status(status).json(json);

  }

  // ==============================================
  // Return the app
  // ==============================================

  return app;
})();

package.json

{
  "name": "name-api",
  "version": "1.17.0",
  "description": "name-api",
  "main": "server.js",
  "dependencies": {
    "axios": "^0.21.1",
    "cookie-parser": "^1.4.4",
    "express": "^4.17.1",
    "express-session": "^1.17.1",
    "express-useragent": "^1.0.13",
    "express-ws": "^4.0.0",
    "googleapis": "^50.0.0",
    "mocha": "^8.0.1",
    "mysql": "github:mysqljs/mysql",
    "nodemailer": "^6.4.6",
    "query-string": "^6.12.1",
    "stripe": "^8.60.0",
    "ws": "^7.4.3"
  },
  "devDependencies": {},
  "scripts": {
    "test": "mocha",
    "start": "node server.js"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/..."
  },
  "author": "",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/..."
  },
  "homepage": "https://github.com/..."
}

【问题讨论】:

    标签: node.js amazon-web-services express websocket


    【解决方案1】:

    问题解决了。

    这是一个负载平衡器问题。显然,这不适用于 Classic Load Balancer。我相信这是由于它的请求方式。

    切换到应用程序负载均衡器为我解决了这个问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-19
      • 2020-07-22
      • 1970-01-01
      • 2021-06-21
      • 1970-01-01
      • 2014-06-06
      • 2021-09-18
      • 1970-01-01
      相关资源
      最近更新 更多