Каким образом можно обработать ошибку, возникающую в middleware, внутри контроллера?

У меня есть маршрут /authorize, поддерживающий методы POST и GET, и я использую middleware для проверки авторизации пользователей. Когда пользователь не авторизован, я вызываю ошибку через цепочку: <code class="javascript">next({ status: 401, message: "Unauthorized" });</code> и обрабатываю эту ошибку с помощью другого middleware: <pre><code class="javascript">app.use((err, res, req, next) =&gt; {
   if (err.status === 401) 
      return res.json({});
   }
   next();
});</code></pre> 

У этого маршрута также есть контроллер. Проблема заключается в том, что мне нужно обрабатывать ошибки авторизации именно в контроллерах маршрута /authorize, чтобы, в случае его неавторизации, перенаправить пользователя на страницу авторизации с передачей определенного параметра. 

Использовать описанный выше middleware для обработки ошибок не подходит, так как мне нужно перекидывать пользователя на другую страницу только в контексте этого определенного маршрута, а не во всех. Как мне решить эту задачу? Если необходимо, я могу продемонстрировать на примере кода то, что я планирую сделать. 

Например, маршрут /authorize поддерживает методы GET и POST, где GET используется для отображения окна подтверждения передачи данных, а POST для подтверждения этих данных. При переходе пользователя на /authorize мне нужно проверить, авторизован он или нет. Если нет, пользователя следует перенаправить на форму авторизации /login с параметром <code>?redirect=https://my.site/authorize</code>, чтобы после успешной авторизации его вернули на эту страницу.
  • 31 марта 2025 г. 8:45
Ответы на вопрос 1
Чтобы обрабатывать ошибки авторизации непосредственно в контроллере, вам нужно сделать следующее:

1. **Проверять авторизацию в middleware** и, если пользователь не авторизован, возвращать соответствующее состояние, например, код статуса 401, учитывая контекст маршрута.

2. **Обрабатывать это состояние в контроллере** и, в случае необходимости, перенаправлять пользователя на страницу авторизации с нужным параметром.

Вместо передачи ошибки через `next`, вы можете изменять поведение вашего middleware и использовать `req` объект для установки атрибута, определяющего авторизацию. Затем в контроллере вы сможете проверить этот атрибут и выполнить необходимое действие.

Вот как это можно сделать на практике:

### Middleware для авторизации

```javascript
function authMiddleware(req, res, next) {
    // Логика проверки авторизации
    const isAuthenticated = false; // пример: проверить авторизацию пользователя

    if (!isAuthenticated) {
        // Вместо next({ status: 401, message: "Unauthorized" }); 
        // Устанавливаем атрибуты в req, чтобы использовать их в контроллере.
        req.isAuthenticated = false; 
        return next(); // Переходим к следующему middleware или контроллеру
    }

    req.isAuthenticated = true; 
    next();
}
```

### Контроллер для маршрута /authorize

```javascript
app.get('/authorize', authMiddleware, (req, res) => {
    if (!req.isAuthenticated) {
        // Если пользователь не авторизован, перенаправляем его на страницу авторизации
        return res.redirect(`/login?redirect=${encodeURIComponent(req.originalUrl)}`);
    }

    // Логика для отображения окна подтверждения передачи данных
    res.json({ message: 'Authorized, showing confirmation window.' });
});
```

### Контроллер для маршрута POST

```javascript
app.post('/authorize', authMiddleware, (req, res) => {
    if (!req.isAuthenticated) {
        return res.redirect(`/login?redirect=${encodeURIComponent(req.originalUrl)}`);
    }

    // Логика обработки подтверждения данных
    res.json({ message: 'Data confirmed successfully.' });
});
```

### Дополнительные улучшения

- Вы можете обработать другие статусы ошибок аналогичным образом, создавая отдельные условия в контроллерах.
- Если ваши middleware и контроллеры становятся слишком громоздкими, рассмотрите возможность вынести более общую логику в отдельные функции для повышения читаемости.
- Использование `req.isAuthenticated` позволяет избежать ненужных редиректов и сообщений об ошибках, если это не нужно для вашей бизнес-логики.

Используя этот подход, вы сможете обрабатывать авторизацию и перенаправления в контроллере маршрута `/authorize`, сохраняя общие проверочные функции в middleware.
Похожие вопросы