Express 3的跨会话问题

cyb*_*bat 5 javascript node.js express

我有一个非常奇怪的会话问题 - 一些令人困惑的奇怪的交叉会话问题.

基本上我有一个快速3应用程序,其中我有2个,看似无关的东西 - 一个是标准的联系表单,有人可以用来给我发电子邮件,另一个是对mailchimp的API调用,以便在订购时添加订阅者.这是两个完全不同的呼叫/动作.

在我的联系表单的顶部,我检查变量'error',我可以在我的控制器代码中使用它来说出诸如"无效的电子邮件"或其他错误消息.我的联系表单有2个控制器操作 - 一个用于显示表单,另一个用于POST,提交并显示错误(如果有).

问题是这样的 - 当我最初加载联系表单时,我看到以下消息:"错误:someone@example.com已经订阅了列表常规.单击此处更新您的个人资料." 这是一条MailChimp消息 - 不仅与进程无关,而且与我的会话无关!如果返回的客户下订单并且他们已经订阅,则会发生此错误.我没有向他们展示这个消息,据我所知,实际上并没有存储它.所以我很困惑.

需要注意的一点是,订单部分是在从支付网关接收xml文件时从节点服务器调用的(因此不是常规会话用户) - 所以可能有一些会话内部我不理解.

代码如下,但这里是问题的摘要.没有用户会话活动的节点服务器正在对mailchimp进行API调用以使用此模块添加订阅者- 通常同一个电子邮件将被订阅两次,因此mailchimp将回复"已订阅"的消息,我*不要在Express的错误本地存储或加载.然后,用户访问该站点,转到联系表单,该表单检查来自该用户的任何错误消息是否尝试提交表示缺少字段的表单 - 并且他们看到mailchimp消息显示另一个人的电子邮件地址.

这是相关的代码.

app.js:

var express = require("express"),
flash = require("connect-flash");

...

app.use(flash());

...

app.use(function(req, res, next) {
  var msgs;
  msgs = req.session.messages || [];
  res.locals.messages = msgs;
  res.locals.hasMessages = !!msgs.length;
  req.session.messages = [];
  return next();
});

...

app.get("/contact", express.csrf(), routes.main.contact);
app.post("/contact", express.csrf(), routes.main.submit);
Run Code Online (Sandbox Code Playgroud)

联系表格控制器:

exports.contact = function(req, res) {
    res.locals.token = req.session._csrf;
    res.render('main/contact');
};

exports.submit = function(req, res) {

  var send = function(message, fn) {
    var sendgrid = new SendGrid(settings.sendgrid_username, settings.sendgrid_password);
    sendgrid.send({
      to: settings.contact_email,
      from: message.email,
      subject: 'Contact Message',
      text: message.message
    }, fn);
  };

  var validate = function(message) {
    var v = new Validator(),
      errors = []
      ;

    v.error = function(msg) {
      errors.push(msg);
    };

    v.check(message.name, 'Please enter your name').len(1, 100);
    v.check(message.email, 'Please enter a valid email address').isEmail();
    v.check(message.message, 'Please enter a valid message').len(1, 1000);

    return errors;
  };

  function render() {
    res.locals.token = req.session._csrf;
    res.render('main/contact', locals);
  }

  var message = req.body.message,
    errors = validate(message),
    locals = {}
    ;

  if (errors.length === 0) {
    send(message, function(success) {
      if (!success) {
        locals.error = 'Error sending message';
        locals.message = message;
      } else {
        locals.notice = 'Your message has been sent.';
      }
      render();
    });
  } else {
    locals.error = 'Your message has errors:';
    locals.errors = errors;
    locals.message = message;
    render();
  }
};
Run Code Online (Sandbox Code Playgroud)

联系表:

{% if error or notice %}
<div id="message" class="alert alert-{% if error %}error{% else %}success{% endif %} ">
  <button type="button" class="close" data-dismiss="alert">×</button>
  <h4>{% if error %}{{ error }}{% else %}{{ notice }}{% endif %}</h4>
  {% if errors %}
  <ul>
  {% for e in errors %}
    <li>{{ e }}</li>
  {% endfor %}
  </ul>
  {% endif %}
</div>
{% endif %}

<form method="post">
...
Run Code Online (Sandbox Code Playgroud)

订单表单控制器(成功订单时由支付网关api调用 - 从不直接由用户调用)

var joinNewsletter = function(data) {

  try {
      var api = new MailChimpAPI(settings.mailchimp_api, { version : '1.3', secure : false });
      api.listSubscribe({
        id: settings.mailchimp_list_id,
        email_address: data.email,
        merge_vars: {
          fname: data.first,
          lname: data.last
        },
        double_optin: data.optin || false
      }, function() {});
  } catch (error) {
      console.log(error.message);
  }

};
...
 joinNewsletter({
    email: order.email,
    first: order.fname,
    last: order.lname
  });
Run Code Online (Sandbox Code Playgroud)

cyb*_*bat 2

天啊,经过一番调试我终于弄清楚了。问题有两个:

  • MailChimpAPI 模块有一个错误 - 当收到错误时,它会创建以下代码:

    error = new Error(message || (message = ''));

错误变量未声明,因此它遇到了全局错误变量。

  • 视图代码检查“错误”是否存在并打印它 - 这是我自己的变量。但显然在 Express 的内部机制中它会检查全局错误变量。

似乎错误正在作为 app.locals 变量处理,从而桥接用户会话。

我通过 a) 修补 MailChimp 帮助程序代码并提交错误报告 b) 确保不再使用“错误”作为视图变量来修复它。

哇。