【问题标题】:Unable to get session for socket in sailsjs after restart重启后无法在sailsjs中获取套接字会话
【发布时间】:2014-02-02 03:00:21
【问题描述】:

我试图在sailsjs上构建套接字驱动的应用程序,它很小,我只需要内存会话适配器,但是当我重新启动应用程序时,我得到了socket.get('/')

Could not parse: No session data returned, and an error was encountered saving session data for the first time: undefined SyntaxError {stack: (...), message: "Unexpected token N"} sails.io.js:142

Uncaught Error: Server response could not be parsed!
No session data returned, and an error was encountered saving session data for the first time: undefined 

我知道我的会话已丢失,但无法找到任何方法来恢复它,甚至无法处理此错误。

有什么方法可以在不重新加载页面的情况下为套接字请求新的会话 cookie 吗?

【问题讨论】:

  • 请贴出代码。
  • @JustDon't I have done: socket.get('/');.在sailsjs 上只需sails new testapp;cd testapp;sails lift; - 在浏览器中打开http://localhost:1337,杀死应用程序(^C)运行sails lift 并尝试从浏览器控制台运行socket.get('/')

标签: javascript socket.io sails.js


【解决方案1】:

这里的问题是,默认情况下,Sails 使用MemoryStore 来处理会话,这意味着每当您降低 Sails(或应用程序崩溃时,即使它正在使用forever 重新启动等)所有会话都会就自动消失了。

解决方案就像将会话处理更改为外部适配器一样简单。在默认生成的config/session.js 中,您已经有两个这样的适配器的设置示例,即Redis 和MongoDB,因此您所要做的就是取消注释相应的行(并且不要忘记secret 值后面的逗号)。例如,如果您使用 mongo,它将类似于

module.exports.session = {
  secret: 'c827f7e0dc520d83d63b5c9c055b1d00', // !!

  // Redis setup example is here...    

  // Uncomment the following lines to use your Mongo adapter as a session store
  adapter: 'mongo',
  host: 'localhost',
  port: 27017,
  db: 'sails',
  collection: 'sessions'

  // Optional Values:
  //
  // # Note: url will override other connection settings
  // url: 'mongodb://user:pass@host:port/database/collection',
  //
  // username: '',
  // password: '',
  // auto_reconnect: false,
  // ssl: false,
  // stringify: true    
};

当然,在这种情况下,您应该在您的机器上运行mongod

更新

好的,如果存在无法避免的 MemoryStore 限制(这是最初的问题),那么在不重新加载页面的情况下重新初始化套接字会话会变得有点棘手,但仍然可能。为了做到这一点,应该:

  1. 向您的服务器发出 AJAX(或 JSONP,如果是 CORS)请求以获取新的会话 ID。例如,它可以像让控制器返回带有会话 ID 的 JSON 一样简单,比如api/controllers/TestController.js

    module.exports = { index: function(req, res) { res.send(req.sessionID); } };

因此,一旦您检测到会话丢失,请使用$.get('/test') 获取新的会话 ID。

  1. 然后在重新连接套接字时将新的会话 ID 作为 cookie 参数传递:

    socket.socket.connect('/?cookie=<newSessionID>')

  2. socket.get("/", function (response) { console.log(response); }) 将在此之后工作。

这是一种快速破解,并且可能有一种更优雅的包装方式(例如,在标题中发送会话 ID,而不是在正文中等),但想法很简单:发出 AJAX 请求以获取一个新会话并将其 ID 作为cookie 参数传递以重新连接套接字。

【讨论】:

  • 它很小,我只需要内存会话适配器问题是“如何在不重新加载页面的情况下为套接字请求新的会话 cookie?”我的意思是我明白问题是因为会话丢失。但是有没有办法再次获得会话?现在我在解析错误时使用window.location.reload() 解决它。此外,如果保存的会话因任何原因丢失,我也会遇到同样的问题。
  • @eicto 对不起,我没有对最初的问题给予足够的重视。不过,我现在正在研究它。这个真的很吸引人。到目前为止我发现的建议是“......首先从客户端向 Sails.js 服务器发送一个 JSONP 请求以获取 cookie(确保它是同一个域!!)”还没有尝试过这个,但是我会让你知道如果有什么办法。谢谢!
  • 顺便说一句,你认为让sailsjs bugreport 像“non json reply in case of session error”就足够了吗?
  • @eicto 好吧,这对我来说似乎并不完全像一个错误,因为它没有被宣布应该以这种方式工作。它可能就像一个功能。
  • hm,但它会导致客户端应用程序崩溃。 (想象它不是一个Web应用程序,而是一些只是api客户端,它确保如果没有连接错误而是json消息)并且它得到了无法解析的“随机”字符串。
【解决方案2】:

我遇到了同样的问题,在阅读this issue 时,我意识到将在对航行的 http 请求之后创建一个新会话。我在静态文件上单独提供前端,因此我只使用 socket.io 来处理风帆,这就是会话没有更新的原因。

对于持久性或易失性会话适配器,当会话过期时,应该更新它。

因此,无需切换到持久适配器,我只需在sails assets 文件夹下添加一个空文件,如assets/js/renew-session.js(空文件),并将其作为脚本包含在我的应用程序的索引中。这样,初始 HTTP 请求会更新 cookie。

也许这对其他人有用

【讨论】:

  • 我的理解是,在使用持久存储(如 redis)时不应该出现这个问题,但这正是我在生产中的情况。我无法在开发中重现它
猜你喜欢
  • 2017-07-18
  • 2014-03-18
  • 1970-01-01
  • 1970-01-01
  • 2014-05-09
  • 2014-01-03
  • 1970-01-01
  • 2015-05-12
  • 2020-08-13
相关资源
最近更新 更多