Javascript 与Express 3的跨会话问题

Javascript 与Express 3的跨会话问题,javascript,node.js,express,Javascript,Node.js,Express,我有一个非常奇怪的会话问题——一些奇怪的跨会话问题让我感到困惑 基本上,我有一个express 3应用程序,其中有两个似乎不相关的东西——一个是标准的联系人表单,有人可以用它给我发电子邮件,另一个是对mailchimp的API调用,以便在订户下订单时添加订户。这是两个完全不同的调用/操作 在我的联系人表单的顶部,我有一个变量'error'的检查,我可以在我的控制器代码中使用它来表示诸如“无效电子邮件”或其他错误消息。我的联系人表单有两个控制器操作-一个用于GET,显示表单;另一个用于POST,提

我有一个非常奇怪的会话问题——一些奇怪的跨会话问题让我感到困惑

基本上,我有一个express 3应用程序,其中有两个似乎不相关的东西——一个是标准的联系人表单,有人可以用它给我发电子邮件,另一个是对mailchimp的API调用,以便在订户下订单时添加订户。这是两个完全不同的调用/操作

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

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

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

代码如下,但这里是问题的摘要。没有用户会话处于活动状态的节点服务器正在对mailchimp进行API调用,以使用此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);
联络表格管理员:

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();
  }
};
联络表格:

{% 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">
...

哦,天哪,经过大量的调试,我终于明白了。问题有两方面:

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

    error=新错误(消息| |(消息=“”))

错误变量未声明,因此它将命中全局错误变量

  • 查看代码检查“error”是否存在并打印它-这是我自己的变量。但显然在Express的内部机制中,它检查全局错误var
似乎错误正在作为app.locals变量处理,因此桥接了用户会话

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


哇。

…因为我们完全是通过心灵感应获得路线的。如果控制器重叠,则会发生错误。路由在那里。唯一不在那里的路线是订单,我保证重叠没有问题。但联系途径是
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
  });