Запуск нового сеанса вызывает ошибку - невозможно установить заголовки после их отправки клиенту - PullRequest
1 голос
/ 07 мая 2020

При запуске нового сеанса, например, когда я обращаюсь к localhost из вкладки инкогнито, я получаю следующую ошибку:

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at ServerResponse.setHeader (_http_outgoing.js:485:11)
    at ServerResponse.header (E:\Documents\Projects\TypeTest\node_modules\express\lib\response.js:771:10)
    at ServerResponse.send (E:\Documents\Projects\TypeTest\node_modules\express\lib\response.js:170:12)
    at done (E:\Documents\Projects\TypeTest\node_modules\express\lib\response.js:1008:10)
    at tryHandleCache (E:\Documents\Projects\TypeTest\node_modules\ejs\lib\ejs.js:261:5)
    at View.exports.renderFile [as engine] (E:\Documents\Projects\TypeTest\node_modules\ejs\lib\ejs.js:461:10)
    at View.render (E:\Documents\Projects\TypeTest\node_modules\express\lib\view.js:135:8)
    at tryRender (E:\Documents\Projects\TypeTest\node_modules\express\lib\application.js:640:10)
    at Function.render (E:\Documents\Projects\TypeTest\node_modules\express\lib\application.js:592:3)
    at ServerResponse.render (E:\Documents\Projects\TypeTest\node_modules\express\lib\response.js:1012:7)
    at E:\Documents\Projects\TypeTest\node_modules\express-ejs-layouts\lib\express-layouts.js:113:20
    at tryHandleCache (E:\Documents\Projects\TypeTest\node_modules\ejs\lib\ejs.js:261:5)
    at View.exports.renderFile [as engine] (E:\Documents\Projects\TypeTest\node_modules\ejs\lib\ejs.js:461:10)
    at View.render (E:\Documents\Projects\TypeTest\node_modules\express\lib\view.js:135:8)
    at tryRender (E:\Documents\Projects\TypeTest\node_modules\express\lib\application.js:640:10)
    at Function.render (E:\Documents\Projects\TypeTest\node_modules\express\lib\application.js:592:3)

Я знаю, что вызов res.render() или res.send() et c. несколько раз вызывает эту ошибку, но я не могу найти ни одного примера в моем коде. Как я уже упоминал, это происходит только при запуске нового сеанса (я думаю), например, при доступе к сайту во вкладке инкогнито. Это наводит меня на мысль, что это как-то связано с cook ie -session, возможно, повторно отображает страницу?

Даже когда я оставляю маршрутизатор get полностью пустым и никакая информация не отправляется, я получаю та же ошибка. Это снова заставляет меня поверить, что это как-то связано с промежуточным программным обеспечением сеанса. Я также использую Passport для аутентификации, но не думаю, что это вызывает проблему.

Вот часть server.js, которая включает промежуточное ПО для сеанса.

app.set('view engine', 'ejs');
app.set('views', './views');
app.set('layout', 'layouts/default')
app.use(expressLayouts);
app.use(express.static('public'));
app.use(express.urlencoded({ extended: true }));
app.use(express.json());

const flash = require('express-flash');
const cookieSession = require('cookie-session');

app.use(flash());
app.use(cookieSession({
  name: 'session',
  secret: process.env.SESSION_SECRET,
  maxAge: 10000000 * 60 * 60 * 24
}));

const passport = require('passport');
const initializePassport = require('./config/passport');
initializePassport(passport);
app.use(passport.initialize());
app.use(passport.session());

Здесь это моя конфигурация паспорта. file

module.exports = function (passport) {
  passport.use(
    new LocalStrategy({ usernameField: 'email' }, (email, password, done) => {
      User.findOne().byEmailOrUsername(email).then(user => {
        if (!user) {
          return done(null, false, { message: 'Incorrect email or password' })
        }

        bcrypt.compare(password, user.password, (err, isMatch) => {
          if (err) {
            return done(err);
          } else if (isMatch) {
            return done(null, user);
          } else {
            return done(null, false, { message: 'Incorrect email or password' });
          }
        });
      })
    }));

  passport.serializeUser(function (user, done) {
    console.log('serialize');
    return done(null, user.id);
  });

  passport.deserializeUser(function (id, done) {
    console.log('deserialize');

    return User.findById(id, function (err, user) {
      return done(err, user);
    });
  });
}

Приносим извинения, если этот вопрос сформулирован слишком слабо, но я очень не уверен, что вызывает эту ошибку. Спасибо

Ответы [ 2 ]

0 голосов
/ 07 мая 2020

Исправлено

Раньше я перенаправлял HTTP-запросы на HTTPS-сервер, используя

app.use((req, res, next) => {
  if (req.protocol === 'http') {
    res.redirect(301, `https://${req.headers.host}${req.url}`);
  }
  next();
})

. Это заставляло любые HTTP-запросы обрабатывать дважды. Я испытывал это только при использовании вкладки инкогнито, потому что на обычной вкладке Chrome автоматически переключается на HTTPS перед отправкой запроса. Исправлено путем выполнения

app.use((req, res, next) => {
  if (req.protocol === 'http') {
    res.redirect(301, `https://${req.headers.host}${req.url}`);
  } else {
    next();
  }
})
0 голосов
/ 07 мая 2020
return User.findById(id, function (err, user) {
  return done(err, user);
});

});

Вы не можете использовать оператор возврата в операторе возврата, потому что есть только оператор возврата. !!!

...