Правильное использование res.locals / app.locals в Node.js / Express.js приложениях

Всем привет!

Из-за однопоточности Node.js нужно очень внимательно следить за специфичной для пользователей информацией и не хранить её в замыканиях, куда другое соединение может получить доступ (информация из статьи Eric Elliott (раздел “Memory Management”)).

Вариант решения - использовать отдельный middleware и объект res.locals, который хранит локальные для ответа ( res ) переменные, ограниченные областью видимости запроса ( req )

app.use((req, res, next) => {
  res.locals.user = req.user;
  res.locals.authenticated = !req.user.anonymous;
  next();
});

Вопрос №1: неужели нужно создавать для каждого запроса к API такой middleware?
Вопрос №2: как быть, если у меня не просто 2-3 поля в req, которые я хочу записать в res.locals (см. пример выше), а большая форма на десятки полей, количество которых, к тому же, может динамически меняться?

Спасибо.

Первое. Чувак в статье рассказывает решение проблемы, не уточняя в чем проблема. Он предполагает что ты захочешь написать код вида

var userData
app.get(('/', res) => {
	userData = req.user
});

app.get('/kkk', (req, res) => {
        // do something with userData
});

При такой конструкции когда будет сыпаться куча запросов, может произойти ситуация когда:

  • user1 зашел на /, в userData записалось, допустим, user1
  • user2 зашел на /, в userData записалось user2
  • user1 зашел на /kkk страницу, а в переменной уже user2 (так как переменная в замыкании в котором объявлены функции обработчики ответов).

Второе. res.locals нужен для двух случаев:

  • когда ты хочешь в каком-то middleware собрать значения, и сделать их доступными в рамках сессии запроса-ответа (т.е. для другого middleware и обработчика, который формирует конечный ответ).
  • когда ты хочешь собрать данные, которые будут использоваться для рендера темплейтов. Некоторые движки темплейтов делают res.local доступными в темплейтах.

Третье. Можно сохранять и мутировать значения в рамках сессии. В этом случае тебе нужно подключить session middleware, и мутировать значения в req.session - вот пример счетчика заходов на страницу в рамках сессии GitHub - expressjs/session: Simple session middleware for Express.

Думаю нет. Нужен конкретный пример чтобы было понятно что ты имеешь в виду.

Использовать Object.assign в комбинации с Underscore.js. Например в req.params у тебя могут быть поля userName, address, email, phone комбинациях (например phone может быть не указан).

Object.assign(res.locals, _.pick(req.params, ['userName', 'address', 'email', 'phone']))
1 лайк

Да, действительно “чувак” не описал в чём конкретно проблема. Но я не уверен, что под проблемой “однопоточности” Node.js он имел в виду описанный тобой пример с замыканиями т.к. это в принципе особенность JS и ясное дело, что так делать не стоит.

Я думал, прочитав статью, что в res.locals нужно хранить данные, которые могут прийти в req.body, например.

А так спасибо, стало понятнее.