2013-05-22 12 views
5

Mam bardzo dziwny problem z sesją - jakiś dziwny problem z sesją krzyżową, który mnie zaskakuje.Problem z sesją krzyżową z Express 3

Zasadniczo mam aplikację ekspresową 3, w której mam 2 pozornie niezwiązane ze sobą rzeczy - jeden jest standardowym formularzem kontaktowym, za pomocą którego można wysłać wiadomość e-mail do mnie, a drugi to wywołanie interfejsu API do usługi mailchimp w celu dodania subskrybentów po umieszczeniu zamówienie. Są to 2 całkowicie różne połączenia/akcje.

Na górze mojego formularza kontaktowego sprawdzam zmienną "error", której mogę użyć w moim kodzie kontrolera, aby powiedzieć coś takiego jak "nieprawidłowy e-mail" lub inny komunikat o błędzie. Mój formularz kontaktowy ma 2 akcje kontrolera - jeden dla GET, który pokazuje formularz i jeden dla POST, który przesyła i pokazuje ewentualne błędy.

Problem polega na tym, że po wczytaniu formularza kontaktowego widzę komunikat "Błąd: [email protected] jest już zapisana na listę Ogólne Kliknij tutaj, aby zaktualizować swój profil." który jest wiadomością MailChimp - nie tylko niezwiązaną z procesem, ale niezwiązaną z moją sesją! Ten błąd może się zdarzyć, gdy powracający klient złoży i zamówi, a oni już są subskrybentami. Nigdy nie pokazuję im tej wiadomości, o ile mogę to stwierdzić, w rzeczywistości ją przechowuję. Tak więc jestem zdezorientowany.

Należy zwrócić uwagę na to, że część zamówienia jest wywoływana z serwera węzłów po otrzymaniu pliku xml z bramki płatności (a więc nie jest zwykłym użytkownikiem sesji) - może więc jest kilka wewnętrznych interakcji, których nie rozumiem.

Kod znajduje się poniżej, ale poniżej znajduje się podsumowanie problemu. Serwer węzła, bez sesji użytkownika aktywny, wykonuje wywołanie API do programu mailchimp w celu dodania subskrybenta za pomocą tego module - Często zdarza się, że ten sam e-mail zostanie zasubskrybowany dwa razy, więc mailchimp odpowie na "już subskrybowany" komunikat, który ja * do no * t przechowywać lub załadować lokalnych mieszkańców błędów Express. Następnie użytkownik odwiedza witrynę, przechodzi do formularza kontaktowego, który sprawdza, czy są jakieś komunikaty o błędach od tego użytkownika, który próbuje przesłać formularz z brakującymi polami - i widzą komunikat mailchimp pokazujący adres e-mail innej osoby.

Oto odpowiedni kod.

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

kontakt kontroler formularz: Formularz

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(); 
    } 
}; 

kontakt:

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

kontroler formularz zamówienia (nazywane przez bramki płatności API na udane zamówienie - nigdy wywołana bezpośrednio przez użytkownika)

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 
    }); 
+0

... Ponieważ jesteśmy całkowicie przeznaczeni do telepatycznego zdobywania tras. Jeśli kontrolery nakładają się, to tam wystąpi błąd. –

+0

Trasy są tam. Jedyną trasą, której nie ma, jest zamówienie i gwarantuję nakładanie się, więc nie ma problemu. Ale trasy kontaktu są – cyberwombat

Odpowiedz

2

O, dobry Boże, wymyśliłem to po luzie debugowania. Problemy są dwojakiego rodzaju:

  • Moduł MailChimpAPI ma błąd - po otrzymaniu jej błąd tworzy ten kod:

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

Błąd var jest nierejestrowanej więc to uderzanie błąd globalny var.

  • Kod widoku sprawdza, czy "błąd" istnieje i drukuje go - to była moja własna zmienna. Ale najwyraźniej w wewnętrznym mechanizmie Expressa sprawdza globalny błąd var.

Wygląda na to, że błąd jest traktowany jako zmienna app.locals, co powoduje pomijanie sesji użytkownika.

Naprawiam to przez a) załatanie kodu pomocniczego MailChimp i wypełnienie raportu o błędzie oraz b) upewnienie się, że ponownie nie użyje "błędu" jako zmiennej widoku.

Woah.

Powiązane problemy