Извикване на следващия междинен софтуер след пренасочване в Express.js

Търся да стимулирам поведението чрез интеграционни тестове на Express.js междинен софтуер. Срещнах интересно обстоятелство, при което поведението на Express зад приложението не е предвидимо (не и от мен, във всеки случай).

Като опростен пример:

var middlewareExample = function(req, res, next){
  if(req.session){
    refreshSession(req.session, function(err, data){
      if(!err){
        res.redirect('/error');
      }
    });
    next();
  }else{
    res.redirect('/authenticate');
  }
};

Проблемът е извикването на next след пренасочването, тъй като то живее извън вътрешната функция и условното условие. Не съм сигурен как Express обработва извикванията на мидълуер/маршрут до next или res.redirect, ако те се случват преди или след един друг, както се вижда по-горе.

Ръчното тестване не разкри никакво странно поведение, нито модулът за супертест. Бих искал да знам дали и как Express реагира на обстоятелства като това. Освен това може да се използва супертест за разкриване на всяко потенциално нежелано поведение. Освен това, ако мога, бих искал да чуя какви подходи биха използвали другите за тестване на междинния софтуер на Node/Express като цяло.


person jneander    schedule 14.03.2013    source източник
comment
Какво се опитваш да направиш? както res.redirect('/error'), така и next() могат да бъдат извикани в една и съща заявка, обърквайки целия контролен поток.   -  person Jonathan Ong    schedule 14.03.2013
comment
Получавам Can't set headers after they are sent грешки, ако опитам да използвам и двете.   -  person robertklep    schedule 14.03.2013
comment
@JonathanOng Опитвам се да разкрия чрез тестове всяка повреда, която би трябвало да се случи, когато и двете функции могат да бъдат извикани в една и съща заявка.   -  person jneander    schedule 14.03.2013
comment
@robertklep Някакви идеи къде и по какви начини може да се разпространи тази грешка?   -  person jneander    schedule 14.03.2013
comment
Поне ще се покаже на конзолата, но не мисля, че можете да го проверите от „външната страна“, защото е малко спорна грешка: отговорът (под формата на пренасочване) вече е изпратен до клиент в този момент.   -  person robertklep    schedule 14.03.2013
comment
След някои изчерпателни тестове потвърдих, че съм бил изправен пред състояние на състезание. Тъй като обработката на потока на междинния софтуер може да отнеме известно време, всяко действие, извършено върху response, като например пренасочване, ще се случи, преди да се обработи останалият междинен софтуер. Създадох фиктивна мидълуер функция, която изпълнява res.send(200) и я поставих след този пример за мидълуер. Когато се изпълнява на живо, принуждава отговорът да бъде завършен, преди пренасочването да може да се обработи. При тестовете обаче пренасочването все още е по-бързо. Сега трябва да внеса забавяне в теста, за да докажа състоянието на състезанието.   -  person jneander    schedule 14.03.2013
comment
Най-накрая разрешихте ли това? Имам условия за състезание с качване!   -  person qodeninja    schedule 18.11.2013


Отговори (2)


вие изпращате два отговора в една и съща заявка. next() е отговор, ако приемем, че следващият манипулатор също има отговор, както и res.redirect(). Това, което наистина искате е:

var middlewareExample = function(req, res, next){
  if(req.session){
    refreshSession(req.session, next);
  }else{
    res.redirect('/authenticate');
  }
};
person Jonathan Ong    schedule 15.03.2013

Изпитвах този проблем с примера по-долу.

const redirect = () => (res, resp, next) => {
  if (/* redirect condition met */) {
    return resp.status(302).redirect(`https://example.com/${path_logic()}`);
  } else {
    return next();
  }
}

app.use(redirect());
app.get('*', static('built/project/code'));

Не успях да намеря нищо, което да говори за пренасочвания, които не работят в метода .use. Но явно не е позволено.

Ето моето решение.

const redirect = () => (res, resp, next) => {
  if (/* redirect condition met */) {
    return resp.status(302).redirect(`https://example.com/${path_logic()}`);
  } else {
    return next();
  }
}

app.get('*', [
  redirect(),
  static('built/project/code')
]);

Единствената логическа разлика тук е, че функцията за пренасочване изглежда работи само когато се комбинира с манипулатор на заявки (.get .post и т.н.), но не и .use.

person Lawrence_NT    schedule 29.08.2019