Власні сторінки помилок
OxPHP віддає фірмові HTML-сторінки помилок для відповідей 4xx і 5xx. Кожна сторінка зчитується з диска один раз під час запуску й віддається з памʼяті, тож під час обробки запиту жодних дискових операцій введення-виведення не відбувається.
Як це працює
- Завантаження під час запуску. Під час запуску OxPHP зчитує каталог, указаний у
ERROR_PAGES_DIR, і завантажує в памʼять кожен коректний файл{status}.html. - Правила іменування. Імʼя файлу має бути числовим кодом стану HTTP з діапазону 400–599 (наприклад,
404.html,503.html). Файли з нечисловими іменами, кодами стану поза цим діапазоном (зокрема200.html) або з розширенням, відмінним від.html, мовчки ігноруються. - Заміна тіла. Коли OxPHP формує відповідь 4xx або 5xx, він перевіряє, чи є відповідна попередньо завантажена сторінка помилки. Якщо вона є, OxPHP замінює лише тіло та заголовки, що його описують:
Content-Typeнабуває значенняtext/html; charset=utf-8,Content-Length— розміру сторінки, а заголовки, привʼязані до початкового тіла (Content-Encoding,ETag,Last-Modified), відкидаються, щоб вони не могли хибно позначити замінене тіло чи спричинити його повторну перевірку (наприклад, тіло помилки PHP, стисненеob_gzhandler, не залишить HTML-сторінку з позначкоюContent-Encoding: gzip). Заголовки, які описують семантику відповіді, а не її тіло, зберігаються у власній сторінці:Content-Rangeдля416 Range Not Satisfiable,Retry-Afterдля529 Site is overloadedіAllowдля405 Method Not Allowed. - Резервний варіант. Якщо каталогу не існує або його не вдається прочитати під час запуску, OxPHP записує попередження в журнал і працює далі без власних сторінок помилок. Відповіді з помилками повертаються до тіл у вигляді звичайного тексту, доки каталог не буде виправлено, а сервер — перезапущено.
Налаштування
| Змінна | Типове значення | Опис |
|---|---|---|
ERROR_PAGES_DIR |
(не задано) | Каталог з HTML-файлами власних сторінок помилок. Файли мають називатися {status}.html для кодів стану 400–599. Якщо змінну не задано, відповіді з помилками використовують тіла у вигляді звичайного тексту |
Приклади сторінок
Кожна сторінка помилки — це самодостатній HTML-файл з іменем {status}.html. Тримайте стилі вбудованими, без зовнішніх ресурсів: інакше невдалий додатковий запит зламає саму сторінку помилки.
Шаблон для повторного використання
Скопіюйте його в кожен {status}.html і змініть <title>, <h1> та <p>:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>500 — Internal Server Error</title>
<style>
body { font-family: system-ui, sans-serif; text-align: center; padding: 4rem 1rem; color: #333; }
h1 { font-size: 2rem; margin-bottom: 0.5rem; }
p { color: #666; }
</style>
</head>
<body>
<h1>Something went wrong</h1>
<p>Please try again in a moment.</p>
</body>
</html>Коди стану, для яких варто мати сторінки
OxPHP замінює тіло кожної відповіді 4xx або 5xx, що доходить до конвеєра відповідей. Ось коди, які він повертає самостійно, тож підготуйте файл для кожного з них:
| Файл | Стан | Коли OxPHP його повертає |
|---|---|---|
400.html |
Bad Request | Запит QUERY (RFC 10008), надісланий без заголовка Content-Type |
404.html |
Not Found | Немає відповідного файлу чи маршруту; заблокований dotfile (.env, .git/); прямий запит до .php у режимі Framework; типовий резервний варіант PHP_DENY_PATHS |
413.html |
Payload Too Large | Тіло запиту перевищує максимальний розмір |
416.html |
Range Not Satisfiable | Нездійсненний заголовок Range для статичного файлу (Content-Range зберігається) |
500.html |
Internal Server Error | Неперехоплена або фатальна помилка PHP |
503.html |
Service Unavailable | Плавне завершення обробки запитів під час зупинки сервера |
504.html |
Gateway Timeout | Вичерпано max_execution_time PHP (або ліміт set_time_limit()). Див. Тайм-аути |
529.html |
Site is overloaded | Запит вичерпав свій бюджет очікування (щонайбільше QUEUE_WAIT_TIMEOUT_MS, менше там, де сервер його скоротив), так і не потрапивши до воркера (очікуючи на місце в черзі або в самій черзі), або вже очікували QUEUE_MAX_WAITING запитів, або їхні тіла вже заповнили QUEUE_MAX_WAITING_BYTES (Retry-After зберігається) |
Будь-який інший код 4xx чи 5xx працює так само — додайте 403.html, 451.html тощо для кодів, які повертає ваш PHP-застосунок, або для власного стану PHP_DENY_FALLBACK. Єдиний виняток — 429 від обмежувача частоти запитів: він формується ще до запуску цього обробника й завжди використовує типове тіло (див. примітку нижче).
Готові приклади
Мінімальна сторінка 404:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>404 - Page Not Found</title>
<style>
body { font-family: system-ui, sans-serif; text-align: center; padding: 4rem 1rem; color: #333; }
h1 { font-size: 2rem; margin-bottom: 0.5rem; }
p { color: #666; }
</style>
</head>
<body>
<h1>Page Not Found</h1>
<p>The page you requested does not exist.</p>
</body>
</html>Сторінка технічного обслуговування 503 з автоматичним оновленням:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="refresh" content="30">
<title>503 - Service Unavailable</title>
<style>
body { font-family: system-ui, sans-serif; text-align: center; padding: 4rem 1rem; color: #333; }
h1 { font-size: 2rem; margin-bottom: 0.5rem; }
p { color: #666; }
</style>
</head>
<body>
<h1>Service Unavailable</h1>
<p>We are performing maintenance. This page will refresh automatically.</p>
</body>
</html>Усунення несправностей
Власні сторінки помилок не зʼявляються
Переконайтеся, що ERROR_PAGES_DIR задано, а файли названо правильно.
Перевірка: переконайтеся в правильності шляху до каталогу й у тому, що під час запуску OxPHP записав у журнал рядки «Loaded custom error page»:
docker logs my-app 2>&1 | grep "error page"Виправлення: переконайтеся, що шлях до каталогу правильний, файли мають імена {status}.html, а контейнер має доступ на читання до каталогу.
Попередження під час запуску про відсутній каталог сторінок помилок
Якщо каталогу ERROR_PAGES_DIR не існує або його не вдається прочитати, OxPHP записує попередження в журнал і працює далі без власних сторінок помилок. Тоді відповіді з помилками використовують тіла у вигляді звичайного тексту. Перевірте, чи правильно змонтовано том у Docker:
docker run --rm -v ./errors:/var/www/errors:ro \
-e ERROR_PAGES_DIR=/var/www/errors \
ghcr.io/oxphp/oxphp:0.13.0Відповідь 429 усе одно показує типове тіло
Деякі відповіді, що формуються до запуску конвеєра відповідей, — наприклад, відмови через обмеження частоти запитів — не обробляються обробником сторінок помилок. Відповідь 429 Too Many Requests від обмежувача частоти запитів використовує типове тіло незалежно від того, чи є файл 429.html.
Приклад для Docker
services:
app:
image: ghcr.io/oxphp/oxphp:0.13.0
ports:
- "8080:80"
volumes:
- ./src:/var/www/html:ro
- ./errors:/var/www/errors:ro
environment:
ERROR_PAGES_DIR: "/var/www/errors"
ENTRY_FILE: "index.php"Структура каталогів:
project/
src/
public/
index.php
errors/
400.html
403.html
404.html
500.html
503.html
504.html
529.htmlРекомендації
- Робіть сторінки помилок самодостатніми, із вбудованим CSS. Не посилайтеся на зовнішні таблиці стилів чи скрипти — ці додаткові запити самі можуть завершитися помилкою.
- Додайте до
503.htmlтег<meta http-equiv="refresh" content="30">, щоб браузери користувачів автоматично повторили спробу після завершення технічного обслуговування. - Робіть сторінки помилок невеликими. Кожна завантажена сторінка зберігається в памʼяті протягом усього життя процесу сервера.
Власні сторінки помилок застосовуються до відповідей, що проходять звичайним конвеєром обробки запитів. Відповідь 429 Too Many Requests від обмежувача частоти запитів формується до запуску обробника сторінок помилок і використовує типове тіло у вигляді звичайного тексту.
Промпти для вашого агента
Ці промпти розраховані на агента, до якого підключено MCP-сервер документації OxPHP, — потрібні сторінки він прочитає сам.
Зроби для мого розгортання фірмові сторінки помилок OxPHP. Прочитай сторінку `features/error-pages` через MCP-сервер документації OxPHP.
Візьми шрифти й кольори з власного макета цього репозиторію, напиши самодостатній файл для кожного стану, який OxPHP формує сам, і підключи каталог до мого контейнера.Див. також
- Маршрутизація — як формуються відповіді 404 для шляхів без відповідного маршруту
- Обмеження частоти запитів — поведінка обмеження частоти та відповіді 429
- Довідник з налаштувань — повний довідник змінних середовища