Ось готовий урок, створений за твоїм майстер-промптом.
🎓 CS50-Style Lesson: Middleware (Прошарок)
Привіт, друзі! Мене звати [Твоє Ім'я], і це... ні, не Гарвард, але ми тут, щоб розібратися з однією з найважливіших концепцій у веб-розробці.
Сьогодні ми говоримо про Middleware.
Звучить як щось складне й абстрактне, правда? Але я обіцяю: до кінця цього уроку ви не просто зрозумієте, що це таке, а й будете дивуватися, як ви взагалі писали код без нього.
1. 🔥 Вступ: Проблема та мотивація
Уявіть, що ви власник елітного нічного клубу. У вас є бармен, ді-джей і VIP-зона.
Тепер уявіть ситуацію: до бармена підходить людина і просить коктейль. Бармен, замість того щоб просто налити напій, мусить спочатку запитати: "А тобі є 18 років?", перевірити паспорт, потім перевірити, чи є людина в списку гостей, і тільки потім налити.
Потім ця ж людина йде до VIP-зони. Охоронець VIP-зони знову перевіряє паспорт, знову шукає в списку...
Питання до вас: Чи ефективно це? Чи повинен бармен займатися перевіркою паспортів?
Звісно, ні! Бармен має наливати, ді-джей — грати музику.
У програмуванні те саме. Уявіть, що у вас є 50 маршрутів (сторінок) на сайті. * Ви хочете, щоб доступ до них мали лише зареєстровані користувачі. * Ви хочете записувати в лог кожен запит, щоб знати, хто прийшов.
Невже ви будете копіювати код перевірки користувача (if user.is_logged_in) у кожну з цих 50 функцій?
Проблема: Дублювання коду, хаос, і якщо логіка зміниться — доведеться правити в 50 місцях. Рішення: Поставити на вході "фейс-контроль". Оце і є Middleware.
2. 🧠 Теоретична база (Як це працює "під капотом")
Давайте розберемо це поняття без зайвих академізмів.
Middleware (мідлвар, проміжне ПЗ) — це функція (або шматок коду), яка виконується між отриманням запиту від клієнта (Request) і відправкою фінальної відповіді (Response).
Уявіть собі конвеєр на заводі. 1. Сировина (Запит) заїжджає на стрічку. 2. Middleware 1: Миє сировину. 3. Middleware 2: Фарбує сировину. 4. Middleware 3: Перевіряє якість. 5. Фінальний обробник: Пакує і віддає клієнту.
Як це виглядає в коді (логіка):
Кожна функція Middleware має доступ до трьох речей: 1. 📦 Request (req) — що нам прислали. 2. 📝 Response (res) — що ми віддамо. 3. ➡️ Next — чарівна кнопка "передати далі".
❗️ Що треба запам’ятати залізно: Middleware має лише два шляхи: 1. Або передати естафету далі, викликавши
next(). 2. Або перервати ланцюжок і віддати відповідь одразу (наприклад, "Помилка: Доступ заборонено").Якщо Middleware не зробить ні того, ні іншого — ваш сайт "зависне", клієнт буде вічно чекати відповіді.
3. 🧪 Приклади (Step-by-Step)
Для прикладів використаємо синтаксис JavaScript (Node.js/Express), бо він тут найчитабельніший, але логіка ідентична в Python (Django/FastAPI), Go чи PHP.
Приклад 1: "Балакучий спостерігач" (Logging)
Найпростіший приклад. Ми хочемо просто знати, що хтось зайшов на сайт.
// Це наш Middleware
function logger(req, res, next) {
console.log("Хтось постукав у двері!");
next(); // 👈 Ключовий момент! Передаємо управління далі.
}
// Використовуємо його
app.use(logger);
// Наш головний маршрут
app.get('/', (req, res) => {
res.send("Привіт, це головна сторінка!");
});
Питання до студента: Що буде, якщо я видалю рядок next() у функції logger, а потім спробую зайти на сайт?
(Подумай секунду...)
Відповідь: Браузер буде крутити значок завантаження вічно. Сервер прийняв запит, вивів повідомлення в консоль, але не знає, що робити далі. Ланцюжок розірвано.
Приклад 2: "Суворий охоронець" (Authentication)
Тепер реальний кейс. Захищаємо секретну сторінку.
function checkPassword(req, res, next) {
// Уявимо, що пароль передали в запиті
if (req.query.password === "secret123") {
next(); // Пароль вірний? Проходь!
} else {
res.send("🛑 Стояти! Пароль невірний."); // Перериваємо ланцюжок!
}
}
// Застосовуємо ТІЛЬКИ до секретної сторінки
app.get('/secret', checkPassword, (req, res) => {
res.send("💰 Ось наші скарби!");
});
Чому це круто? Функція app.get (наш фінальний обробник) навіть не знає про існування паролів. Вона просто віддає скарби. Вона впевнена: якщо управління дійшло до неї, значить, охоронець уже все перевірив. Це називається Clean Code.
Приклад 3: "Дбайливий асистент" (Data Processing)
Middleware може не тільки пропускати або забороняти, а й щось додавати до запиту.
function addTimestamp(req, res, next) {
// Додаємо нову властивість до об'єкта запиту
req.requestTime = new Date().toString();
next();
}
app.use(addTimestamp);
app.get('/', (req, res) => {
// Тепер ми можемо використовувати req.requestTime!
res.send("Ви зайшли о: " + req.requestTime);
});
Тут Middleware діє як асистент, який підготував документи для шефа (додав час), щоб шефу (контролеру) не треба було дивитися на годинник.
4. 🛠 Практична частина
Час забруднити руки кодом (або псевдокодом).
Завдання 1. Повторення
Напиши middleware, який просто виводить у консоль метод запиту (GET, POST) і URL.
(Підказка: в req зазвичай є поля req.method та req.url).
Завдання 2. Режим "Технічні роботи"
Уяви, що сайт зламався. Напиши middleware, який стоїть найпершим і на будь-який запит відповідає: "Вибачте, ми зачинені на ремонт".
(Важливо: чи потрібен тут next()?)
Завдання 3. Виправляємо помилку новачка Студент написав код:
function myMiddleware(req, res, next) {
if (req.url === '/admin') {
res.send("Тут тільки для адмінів");
}
next();
}
Питання: Що станеться, якщо юзер зайде на /admin?
(Підказка: помилка "Headers already sent" або креш сервера. Чому ми викликаємо next() після відправки відповіді?)
Завдання 4. Кейс "Фейс-контроль 18+"
Напиши middleware, який перевіряє вік користувача (умовно req.age).
* Якщо < 18 — відправ помилку "Тобі сюди не можна".
* Якщо >= 18 — пропусти далі.
Завдання 5. Міні-кейс (на подумати) Тобі треба зробити так, щоб користувач не міг надсилати більше 5 запитів за хвилину (захист від спаму). Опиши словесно логіку такого middleware. Де б ти зберігав лічильник запитів?
5. 💡 Мислення як у розробника
Як відрізнити новачка від профі в темі Middleware?
1. Порядок має значення!
Новачки часто плутають порядок підключення.
* Якщо ви поставите middleware ErrorHandler (обробка помилок) на самому початку — він нічого не зловить.
* Якщо ви поставите перевірку пароля після того, як віддали дані — це дірка в безпеці.
Порада: Уявляйте код як фізичний тунель. Хто стоїть першим біля входу?
2. "Товсті" контролери — це погано. Якщо ви бачите у своїй фінальній функції (контролері) 50 рядків коду, де ви перевіряєте валідацію пошти, права доступу, форматуєте дату... ЗУПИНІТЬСЯ. Винесіть це в middleware. Контролер має бути "тупим": взяв підготовлені дані -> віддав відповідь.
3. Не забувайте про return
Коли ви робите res.send("Error"), код не зупиняється автоматично! Функція продовжує виконуватися далі.
* Bad: if (error) res.send("Error"); next(); (Буде баг!)
* Good: if (error) return res.send("Error");
6. 🧩 Підсумок
Отже, що ми сьогодні розібрали?
- Middleware — це посередник. Він стоїть між клієнтом і сервером.
- Він може: виконати код, змінити запит/відповідь, завершити запит або викликати наступного.
- Без нього ваш код перетвориться на спагеті з однакових перевірок.
Що ти тепер вмієш? Ти можеш "перехоплювати" запити. Ти розумієш, як працюють плагіни авторизації, логування та обробки помилок у будь-якому сучасному фреймворку.
🔮 Тизер наступного уроку: Ми навчилися перевіряти, хто прийшов. Але як сервер запам'ятовує користувача між запитами, щоб не питати пароль щоразу? На наступному уроці розберемо Sessions, Cookies та JWT. Готуйтеся, будемо печиво їсти (або ні).
А тепер — йдіть і напишіть свій перший "фейс-контроль"! 🚀