Деякі збої WordPress голосні: білі екрани, фатальні помилки, ті, які помічаєш перш ніж охолоне кава. Збої REST API тихіші й дратують більше. Ваш редактор не зберігає, безголовий фронтенд стає пустим, WooCommerce іноді оформляє замовлення «інколи», і єдина підказка — зарозуміле повідомлення на кшталт «The REST API encountered an error».
Практична реальність така: REST API — це не одна функція. Це ланцюг — перезаписи, маршрутизація, автентифікація, cookies/nonce, шари кешування, проміжні захисні механізми та хостинг — і кожен з них може ламатися окремо. Ми виявимо, яке посилання зламалося, з командами, які ви можете виконати, виводами, які зможете інтерпретувати, і рішеннями, які можна прийняти без гадань.
Як WordPress REST фактично працює (і де він ламається)
Коли хтось каже «WordPress REST API зламався», зазвичай мають на увазі одне з наступного:
- Маршрут недоступний (перезаписи, постійні посилання, конфігурація сервера, зворотний проксі, CDN або WAF заважають).
- Маршрут доступний, але заблоковано (проблеми авторизації, nonce/cookie, перевірки прав, плагіни безпеки або правила WAF).
- Маршрут виконується та аварійно завершується (фатальна помилка PHP, таймаути БД, ліміти пам’яті, код плагіна, помилки серіалізації).
- Маршрут виконується, але відповідь спотворюється (кешування, компресія, зміна content-type, несподівані редиректи, змішаний контент, CORS).
На здоровому сайті канонічна базова кінцева точка:
/wp-json/(JSON-індекс неймспейсів і маршрутів)- Приклад маршруту:
/wp-json/wp/v2/posts
Під капотом WordPress використовує правила перезапису, щоб направляти /wp-json/... до index.php, де REST-сервер делегує обробку зареєстрованим маршрутам. Це означає, що навіть «API»-збої часто починаються як нудні помилки перезапису.
Також: REST-запити — це просто HTTP-запити. Це сила й слабкість. Кожний проміжний елемент, що «допомагав» вебсайту (кеш, CDN, фаєрвол, блокувальник ботів, фільтр gzip, мінімізатор, «зміцнювач безпеки»), може «допомогти» вашому REST API потрапити в могилу.
Одна операційна цитата, щоб не обманювати себе:
«Сподівання — не стратегія.» — ген. Гордон Р. Салліван
Де збігаються відмови
У продакшені проблеми REST API концентруються навколо п’яти шарів:
- DNS/TLS/edge: сертифікати, невідповідність SNI, редиректи HTTP→HTTPS, кешування CDN, блокування WAF.
- Зворотний проксі / вебсервер: перезаписи Nginx/Apache, нормалізація шляхів, обрізання заголовків, обмеження тіла запиту.
- Шар додатка WordPress: налаштування постійних посилань, реєстрація маршрутів, конфлікти плагінів, логіка автентифікації і nonce.
- Стан і зберігання: блокування/таймаути БД, дивна поведінка object cache, права на файлову систему.
- Поведінка клієнта: JS-фронтенд, редактор Gutenberg, CORS, змішані cookies, застарілі nonce.
Не починайте діагностику з інтерфейсу адміністратора WordPress. Це як діагностувати мережевий збій, дивлячись на шпалери робочого столу. Почніть із запиту з-поза браузера з відомими вхідними даними та очікуваними виходами.
Швидка інструкція діагностики
Коли REST «впав», вам потрібна відповідь за кілька хвилин: це edge/proxy, додаток чи бекенд? Використовуйте цю інструкцію послідовно. Не пропускайте кроки, бо ви «вже знаєте». Саме так інциденти перетворюються на спогади.
По-перше: підтвердіть кінцеву точку та HTTP-правду
- Запитайте
/wp-json/через curl і зафіксуйте: код статусу, content-type і будь-які редиректи. - Порівняйте з двох точок: з вашого ноутбука і з сервера (або з машини в тій же мережі, що й WordPress).
- Перевірте HTML замість JSON. HTML часто означає, що ви отримуєте сторінку входу, блок-сторінку WAF або кешований шаблон помилки.
По-друге: ізолюйте edge/безпеку від WordPress
- Обійдіть CDN, якщо можливо (прямий origin-хост, VIP внутрішнього балансувальника навантаження або запис у hosts файл у контрольованому середовищі).
- Перегляньте логи WAF/плагінів безпеки на предмет блокувань
/wp-jsonі типових сигнатур (помилкові спрацьовування SQLi/XSS). - Підтвердіть відсутність зациклених редиректів (HTTP→HTTPS→HTTP, www→non-www, правила trailing slash).
По-третє: підтвердіть маршрутизацію WordPress і перезаписи
- Переконайтеся, що постійні посилання не встановлені в «Plain». REST може працювати в plain-режимі, але перезаписи часто стають непослідовними, коли люди перемикають налаштування без очищення правил.
- Підтвердіть, що правила перезапису існують у конфігурації сервера (правила location Nginx) або в
.htaccess(Apache). - Перевірте, чи працює
index.php?rest_route=/. Якщо так — перезаписи зламані; якщо ні — проблема в додатку або блокуванні.
По-четверте: автентифікація лише після того, як шлях працює
- Спочатку перевіряйте публічні кінцеві точки (список записів), потім приватні (користувачі, налаштування).
- Якщо потрібна автентифікація, тестуйте з Application Passwords або Basic Auth (у безпечному середовищі), щоб прибрати складність nonce/cookie.
- Потім перевіряйте cookie+nonce-потоки для проблем з редактором.
По-п’яте: якщо все повільно або 500-ить, розглядайте як насичення бекенду
- Корелюйте з насиченням PHP-FPM, повільними запитами до БД і логами помилок.
- Візьміть вибірку невдалих запитів і простежте: лог доступу вебсервера → лог помилок PHP → WP debug лог → логи БД.
- Прийміть рішення: відкат плагіну/теми, масштабування або тимчасове пом’якшення через виключення кешування.
Правило прийняття рішення: Якщо /wp-json/ не повертає стабільний 200 з JSON з двох точок, не витрачайте час на налагодження функцій WordPress. Виправте маршрутизацію/edge перш за все.
Карта симптомів: розшифровка помилок за поведінкою HTTP
Помилки REST часто з’являються як загальне повідомлення в адмінці WordPress. Ігноруйте повідомлення і дивіться HTTP.
Коди статусу і що вони зазвичай означають
- 200, але неправильний content-type (HTML): ви потрапили на сторінку входу, блок-сторінку WAF, кешований шаблон помилки або ціль редиректу.
- 301/302 зациклення: канонізаційні правила конфліктують (HTTP/HTTPS, www/non-www, trailing slash), або заголовки проксі неправильно встановлені.
- 401 Unauthorized: відсутні/некоректні облікові дані, помилка nonce, Application Passwords вимкнені, плагін безпеки перехоплює.
- 403 Forbidden: правило WAF/CDN, mod_security, обмеження IP, «блокувати JSON-запити», або перевірка прав, що провалюється.
- 404 Not Found: перезаписи не працюють, невідповідність location Nginx, баги мультисайту або маршрути не зареєстровані.
- 405 Method Not Allowed: проксі/сервер забороняє POST/PUT, або шар кешування дозволяє тільки GET.
- 413 Payload Too Large: обмеження розміру тіла проксі; завантаження через REST і медіа-ендпоінти падають.
- 429 Too Many Requests: ліміт запитів, WAF, захист від ботів або агресивне обмеження плагіну.
- 500/502/503: фатальна помилка PHP, аварія апстріму, вичерпано php-fpm, таймаут БД, origin недоступний або таймаут шлюзу.
Жарт #1: REST API «станний» — це мило, ніби називати малюка «тихий» за п’ять хвилин до того, як цукор подіє.
Практичні завдання (команди, виводи, рішення)
Це не «поради». Це повторювані завдання. Кожне містить команду, що означає вивід і яке рішення приймати далі.
Завдання 1: Перевірте індекс REST з вашої робочої станції
cr0x@server:~$ curl -sS -D- -o /tmp/rest.json https://example.com/wp-json/ | head -n 20
HTTP/2 200
content-type: application/json; charset=UTF-8
x-robots-tag: noindex
x-content-type-options: nosniff
Що означає вивід: Отримано 200 і content-type JSON. Добре: маршрутизація і базовий шлях відповіді працюють зовні.
Рішення: Перейдіть до перевірок, пов’язаних з автентифікацією та плагінами. Якщо бачите 301/302 — слідуйте за редиректами (-L) і проаналізуйте канонізацію. Якщо content-type — text/html, ви не отримуєте REST API.
Завдання 2: Перевірте, чи отримуєте HTML замість JSON
cr0x@server:~$ curl -sS -D- https://example.com/wp-json/ | sed -n '1,25p'
HTTP/2 403
content-type: text/html; charset=UTF-8
server: cloudflare
<!doctype html>
<html>
<head><title>Access denied</title></head>
Що означає вивід: 403 з HTML-блок-сторінкою і хедером CDN/server. Це не WordPress. Це проблема на edge.
Рішення: Припиніть чіпати WordPress. Розслідуйте правила WAF/CDN/фаєрволу і обійдіть edge, щоб підтвердити здоров’я origin.
Завдання 3: Протестуйте з origin-хоста, щоб обійти CDN/WAF (де можливо)
cr0x@server:~$ curl -sS -D- -H 'Host: example.com' http://127.0.0.1/wp-json/ | head -n 15
HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
X-Powered-By: PHP/8.2.12
Що означає вивід: Origin повертає JSON нормально. Edge — проблема.
Рішення: Виправте політику edge: дозвольте /wp-json/*, дозвольте потрібні методи, відрегулюйте правила ботів або додайте виключення WAF для REST-ендпоінтів (строго обмежене).
Завдання 4: Визначте, чи зламані перезаписи, використовуючи rest_route
cr0x@server:~$ curl -sS -D- "https://example.com/index.php?rest_route=/" | head -n 15
HTTP/2 200
content-type: application/json; charset=UTF-8
Що означає вивід: REST API працює, коли ви обходите перезаписи. Отже, шар перезаписів зламаний.
Рішення: Виправте конфігурацію серверних перезаписів або скиньте пермалінки. Не витрачайте час на налагодження плагінів, поки /wp-json/ не працюватиме як index.php?rest_route=/.
Завдання 5: Перевірте модулі перезапису Apache та стан .htaccess
cr0x@server:~$ sudo apachectl -M | egrep 'rewrite|headers'
rewrite_module (shared)
headers_module (shared)
Що означає вивід: Потрібні модулі існують. Якщо rewrite відсутній, пермалінки і REST-маршрути часто не працюють.
Рішення: Якщо rewrite_module відсутній — увімкніть його і перезавантажте Apache. Якщо присутній — перевірте vhost і правила .htaccess далі.
Завдання 6: Перевірте маршрутизацію Nginx для wp-json (поширена проблема)
cr0x@server:~$ sudo nginx -T 2>/dev/null | sed -n '/server_name example.com/,/}/p' | egrep -n 'location|try_files|rewrite'
12: location / {
13: try_files $uri $uri/ /index.php?$args;
14: }
28: location ~ \.php$ {
29: include snippets/fastcgi-php.conf;
30: fastcgi_pass unix:/run/php/php8.2-fpm.sock;
31: }
Що означає вивід: Нормальний fallback try_files перенаправляє невідомі шляхи (включно з /wp-json/) до index.php.
Рішення: Якщо бачите try_files $uri =404; без fallback на index, виправте його або REST буде повертати 404. Після змін перезавантажте Nginx і повторіть тест.
Завдання 7: Переконайтеся, що WordPress вважає site URL реальним
cr0x@server:~$ wp option get siteurl --path=/var/www/html
https://example.com
cr0x@server:~$ wp option get home --path=/var/www/html
https://example.com
Що означає вивід: Ці URL керують канонічними редиректами і cookies. Невідповідність (http проти https, www проти non-www) ламає nonce/cookie-автентифікацію і створює циклі редиректів.
Рішення: Якщо вони неправильні — виправте обережно, після чого перевірте редиректи і REST-запити.
Завдання 8: Перегляньте правила перезаписів WordPress і безпечно скиньте їх
cr0x@server:~$ wp rewrite list --path=/var/www/html | head -n 12
^wp-json/?$ index.php?rest_route=/ last
^wp-json/(.+)?$ index.php?rest_route=/$matches[1] last
^wp-sitemap\.xml$ index.php?sitemap=index last
Що означає вивід: Правила перезаписів REST існують на рівні WordPress.
Рішення: Якщо вони відсутні — скиньте правила:
cr0x@server:~$ wp rewrite flush --hard --path=/var/www/html
Success: Rewrite rules flushed.
Рішення: Якщо WordPress має правила, але HTTP все одно 404 — ваш вебсервер їх ігнорує (конфігурація Nginx, Apache AllowOverride тощо).
Завдання 9: Перевірте, чи Apache дозволяє переоприділення через .htaccess
cr0x@server:~$ sudo apachectl -S 2>/dev/null | sed -n '1,80p'
VirtualHost configuration:
*:80 example.com (/etc/apache2/sites-enabled/example.conf:1)
cr0x@server:~$ sudo sed -n '1,120p' /etc/apache2/sites-enabled/example.conf | egrep -n 'DocumentRoot|Directory|AllowOverride'
2: DocumentRoot /var/www/html
5: <Directory /var/www/html>
6: AllowOverride None
7: </Directory>
Що означає вивід: AllowOverride None означає, що ваш .htaccess ігнорується. Пермалінки і перезаписи REST не працюватимуть, якщо vhost не має еквівалентних правил перезапису.
Рішення: Встановіть AllowOverride All (або явно додайте правила перезапису у vhost), перезавантажте Apache і повторіть тест /wp-json/.
Завдання 10: Ідентифікуйте, чи плагін перехоплює REST-запити
cr0x@server:~$ wp plugin list --status=active --path=/var/www/html
+-------------------------+--------+-----------+---------+
| name | status | update | version |
+-------------------------+--------+-----------+---------+
| wordfence | active | none | 7.11.6 |
| w3-total-cache | active | available | 2.7.5 |
| classic-editor | active | none | 1.6.7 |
+-------------------------+--------+-----------+---------+
Що означає вивід: Плагіни безпеки і кешування — часті винуватці проблем REST. Це не звинувачення; це ймовірність.
Рішення: Тимчасово відключіть підозрілі плагіни (у контрольований час) і повторіть тест. Почніть з плагінів WAF/безпеки та агресивних кеш-плагінів.
Завдання 11: Тимчасово відключіть плагіни, не руйнуючи продакшен сліпо
cr0x@server:~$ wp plugin deactivate wordfence w3-total-cache --path=/var/www/html
Plugin 'wordfence' deactivated.
Plugin 'w3-total-cache' deactivated.
Що означає вивід: Ви перевіряєте, чи відновиться REST після видалення перехоплення.
Рішення: Якщо REST відновлюється — вмикайте по одному плагіну, щоб ізолювати проблему. Потім налаштуйте: дозволити /wp-json/, вимкнути блокування REST, виключити кешування для REST-ендпоінтів.
Завдання 12: Перевірте помилки, пов’язані з REST, у логах PHP
cr0x@server:~$ sudo tail -n 40 /var/log/php8.2-fpm.log
[27-Dec-2025 10:12:41] WARNING: [pool www] child 1842 said into stderr: "PHP Warning: Cannot modify header information - headers already sent in /var/www/html/wp-content/plugins/some-plugin/plugin.php on line 88"
[27-Dec-2025 10:12:41] WARNING: [pool www] child 1842 said into stderr: "PHP Fatal error: Uncaught TypeError: json_encode(): Argument #2 ($flags) must be of type int, string given in /var/www/html/wp-content/plugins/some-plugin/api.php:55"
Що означає вивід: Така фатальна помилка може перетворити API-запит у 500, і WordPress повідомить «REST API encountered an error».
Рішення: Відкотіть плагін/тему до раніше працюючої версії, виправте код або зафіксуйте версію PHP, якщо виникла несумісність. Виправлення фатальної помилки — обов’язкове.
Завдання 13: Перевірте журнали доступу Nginx/Apache щодо статусів і таймінгу апстріму
cr0x@server:~$ sudo tail -n 20 /var/log/nginx/access.log | egrep 'wp-json|rest_route' | tail -n 5
203.0.113.10 - - [27/Dec/2025:10:13:02 +0000] "GET /wp-json/ HTTP/2.0" 200 2534 "-" "curl/8.5.0"
203.0.113.10 - - [27/Dec/2025:10:13:05 +0000] "POST /wp-json/wp/v2/posts HTTP/2.0" 401 214 "-" "Mozilla/5.0"
203.0.113.10 - - [27/Dec/2025:10:13:08 +0000] "GET /index.php?rest_route=/wp/v2/users/me HTTP/2.0" 200 612 "-" "Mozilla/5.0"
Що означає вивід: Публічний GET працює, автентифікований POST повертає 401, але автентифікований запит через rest_route працює (можливо з cookies). Це вказує на відмінності в потоках автентифікації, обрізані заголовки або проблеми з nonce.
Рішення: Зосередьтеся на автентифікації: cookies, nonce, Application Passwords, заголовки зворотного проксі або плагіни безпеки, що по-різному обробляють POST до /wp-json.
Завдання 14: Підтвердіть, що проксі не обрізає заголовки відповіді
cr0x@server:~$ curl -sS -D- -o /dev/null https://example.com/wp-json/ | egrep -i 'content-type|cache-control|vary|www-authenticate|set-cookie'
content-type: application/json; charset=UTF-8
cache-control: no-cache, must-revalidate, max-age=0
vary: Accept-Encoding
Що означає вивід: Для багатьох REST-ендпоінтів правильна поведінка cache-control важлива. Відсутність Set-Cookie при потоках входу або відсутність WWW-Authenticate при 401 також можуть сигналізувати про обрізання заголовків.
Рішення: Якщо заголовки відрізняються між origin і edge — виправте конфіг проксі (передачу заголовків) або поведінку CDN. REST і «розумне» кешування за замовчуванням не друзі.
Завдання 15: Перевірте, чи працює базова автентифікація REST з Application Password
cr0x@server:~$ curl -sS -u "apiuser:abcd efgh ijkl mnop" https://example.com/wp-json/wp/v2/users/me | head
{"id":2,"name":"API User","url":"","description":"","link":"https:\/\/example.com\/author\/apiuser\/"}
Що означає вивід: Автентифікація працює і WordPress може обслуговувати автентифіковані REST-запити.
Рішення: Якщо редактор все ще падає, але це працює — ймовірно проблема в cookie+nonce або CORS, а не «REST не працює».
Завдання 16: Виявлення циклів редиректів і конфліктів канонізації
cr0x@server:~$ curl -sS -I -L -o /dev/null -w '%{url_effective} %{http_code}\n' http://example.com/wp-json/
https://www.example.com/wp-json/ 200
Що означає вивід: HTTP був перенаправлений на HTTPS і www, потім успішно відповів.
Рішення: Якщо бачите повторювані редиректи або він завершується на не-JSON локації — виправте siteurl/home, заголовки проксі (X-Forwarded-Proto) і правила канонізації на edge і у WordPress.
Завдання 17: Перевірте заголовки CORS для headless фронтендів
cr0x@server:~$ curl -sS -D- -o /dev/null -X OPTIONS \
-H 'Origin: https://app.example.net' \
-H 'Access-Control-Request-Method: POST' \
https://example.com/wp-json/wp/v2/posts | egrep -i 'http/|access-control'
HTTP/2 403
Що означає вивід: OPTIONS preflight блокується. Багато WAF-ів вважають OPTIONS підозрілим. Браузери відмовляться від фактичного запиту, якщо preflight не проходить.
Рішення: Дозвольте OPTIONS до /wp-json/* на edge і налаштуйте WordPress/CORS-плагін ретельно. Також переконайтеся, що ви випадково не вимагаєте автентифікацію для preflight.
Завдання 18: Перевірте насичення PHP-FPM (REST «працює», поки не перестане)
cr0x@server:~$ sudo ss -s | sed -n '1,20p'
Total: 693
TCP: 41 (estab 18, closed 12, orphaned 0, synrecv 0, timewait 12/0), ports 0
Transport Total IP IPv6
RAW 0 0 0
UDP 9 7 2
TCP 29 18 11
INET 38 25 13
FRAG 0 0 0
cr0x@server:~$ sudo systemctl status php8.2-fpm --no-pager | sed -n '1,20p'
● php8.2-fpm.service - The PHP 8.2 FastCGI Process Manager
Loaded: loaded (/lib/systemd/system/php8.2-fpm.service; enabled)
Active: active (running) since Sat 2025-12-27 09:40:12 UTC; 32min ago
Main PID: 1021 (php-fpm8.2)
Status: "Processes active: 28, idle: 0, Requests: 1827, slow: 12"
Що означає вивід: Нуль простих воркерів і зростання повільних запитів означає, що REST API може падати під навантаженням з 502/504, особливо для автентифікованих кінцевих точок.
Рішення: Збільшіть потужність FPM (в межах доступної ОЗП), зменшіть витратні плагіни, додайте кешування для публічних кінцевих точок і припиніть дозволяти ботам бити по /wp-json.
Що зазвичай ламає REST (реальні режими відмов)
1) Перезаписи та пермалінки: нудна основа
Якщо /wp-json/ повертає 404, але index.php?rest_route=/ працює, ваші перезаписи зламані. Зазвичай це одне з:
- відключений Apache
mod_rewrite. AllowOverride Noneблокує.htaccess.- відсутній fallback
try_files ... /index.phpв Nginx. - правила мультисайту не відповідають фактичній структурі директорій.
- пермалінки перемикали, але правила не скинуто.
Порада: якщо ви на Nginx і розраховуєте на «автоматичні» перезаписи WordPress — ви вже торгуєте з фізикою. Покладіть правильні правила Nginx у систему контролю версій і перестаньте вважати, що адмінка керує вашим вебсервером.
2) Зворотні проксі та «допоміжні» редиректи
REST чутливий до схеми/хоста, бо автентифікація використовує cookies і nonce, прив’язані до origin. Якщо проксі завершує TLS, але WordPress думає, що працює на HTTP, ви побачите:
- цикли редиректів
- cookies встановлені для невірного домену
- провали валідації nonce (часто показуються як 401)
Виправлення зазвичай включають налаштування правильних пересланих заголовків і переконання, що WordPress їх поважає (або коректне встановлення home/siteurl плюс конфіг, що враховує проксі).
3) WAF і захист від ботів, що блокують /wp-json
Шари безпеки люблять блокувати JSON-API, бо атакувальники теж їх люблять. На жаль, і ваш редактор їх теж любить.
Типові тригери WAF:
- POST-тіла, що виглядають як HTML або містять
<script>у легітимному контенті. - Повторювані запити від залогінених користувачів (Gutenberg дуже балакучий).
- OPTIONS preflight для CORS.
- Лімітування, що не відрізняє бота від редактора.
Виправляйте звужуючи винятки: дозволяйте конкретні методи та шляхи, логгайте агресивно та тримайте радіус ураження малим. «Вимкнути WAF» — не виправлення; це лист відмови.
4) Шари кешування, що трактують REST як статичний контент
Публічні ендпоінти можна кешувати обережно. Автентифіковані ендпоінти зазвичай не повинні кешуватися на edge. Коли кеши помиляються, ви бачите:
- користувачі бачать дані інших (рідко, але катастрофічно)
- застарілі nonce і випадкові 401
- випадкові HTML-відповіді, бо кеш зберіг блок-сторінку
Практичне правило: ніколи не кешуйте запити з cookie на edge, якщо ви не знаєте точно, що робите і не можете довести ізоляцію ключів кешу.
5) Конфлікти плагінів: реєстрація маршрутів і фільтрація запитів
Плагіни можуть ламати REST шляхом:
- некоректної реєстрації маршрутів (конфлікти неймспейсів, невірні permission callbacks)
- фільтрації
rest_authentication_errorsта безумовного повернення помилок - виведення пробілів/повідомлень, які псують JSON
- зміни content-type або буферизації виводу
Якщо відключення одного плагіна вирішує проблему — у вас є винуватець. Якщо відключення всіх плагінів вирішує — це плагін, але не сказано який. Ізолюйте систематично.
6) Автентифікація: cookies, nonce і безліч шляхів їх псування
Gutenberg і адмін-екрани часто використовують cookie-автентифікацію з nonce. Це означає, що браузер повинен:
- надсилати правильні cookies для правильного домену/шляху
- надсилати дійсний nonce у заголовку (
X-WP-Nonce) - не блокуватися політиками SameSite або через невідповідність доменів
Коли це не працює, сам REST API може бути у порядку, але редактор кричатиме. Виправляють це вирівнюючи домени, схеми та поведінку cookie — не «переінсталюючи WordPress».
7) Надійність бекенду: фатали PHP, таймаути БД, проблеми зі зберіганням
REST-запити виконують шляхи коду WordPress. Вони звертаються до бази. Вони читають/пишуть опції. Вони можуть генерувати мініатюри. Вони можуть звертатися до зовнішніх API. Якщо ваше сховище повільне або БД нещасна, REST-ендпоінти впадуть першими, бо їх постійно викликають сучасні функції WordPress.
Як порада інженера зі зберігання: «випадкові» відмови REST під навантаженням часто корелюють зі сплесками затримки введення/виведення, особливо на шаред-хостингу або недомірних мережевих дисках. Перевірте I/O wait і здоров’я БД, перш ніж звинувачувати REST у «схильності до збоїв».
Жарт #2: Якщо ваш REST API ламається тільки по понеділках, він не одержимий — це ваш графік деплоїв у масці.
Три корпоративні міні-історії з практики
Міні-історія 1: Інцидент через неправильне припущення
Середня компанія запустила WordPress за зворотним проксі і CDN. Вони розгорнули нову headless-лендінг-сторінку, яка забирала записи через REST. У staging все працювало. У production редактор перестав публікувати, а headless-сторінка інколи повертала 401. Усі звинувачували «WordPress, яким він є».
Неправильне припущення було просте: «Якщо сайт завантажується, API має бути в порядку». Головна сторінка була закешована на CDN. REST-запити не були — хоча інколи вони кешувались, бо CDN мав загальне правило кешувати «всі GET-запити». Публічні REST GET кешувалися. Автентифіковані GET теж кешувалися, бо ключ кешу ігнорував cookies заради продуктивності.
Наслідком була періодична плутанина: відповідь одного редактора могла бути віддана іншому (іноді блокувалася перевірками прав, іноді ні). Команда не помітила витоку даних, але помітила зламані сесії і помилки nonce, бо кешовані відповіді не відповідали очікуванням браузера.
Виправлення не було героїчним. Вони змінили політику CDN: обходити кеш для будь-якого запиту з Cookie і для будь-якого шляху під /wp-json/, якщо явно не дозволено. Потім вони дозволили у whitelist лише кілька публічних кінцевих точок з безпечним ключем кешу і коротким TTL. REST стабілізувався миттєво.
Висновок: ніколи не припускайте, що «веб працює» означає «API працює», особливо коли задіяне кешування. Ваша головна сторінка — брехун; curl — чесний.
Міні-історія 2: Оптимізація, що відбилася назад
Корпоративна маркетинг-команда захотіла швидший TTFB. Інженер увімкнув агресивну оптимізацію HTML і компресію відповідей на зворотному проксі. Він також увімкнув набір правил «зміцнення безпеки», щоб блокувати «підозрілі рядки запиту».
Продуктивність публічного сайту покращилася. Потім Gutenberg почав падати при завантаженні зображень і оновленнях постів. Панель Site Health повідомляла про помилки REST API. Розробники почали ганяти фейкові конфлікти плагінів.
Справжня проблема: правило оптимізації проксі буферизувало і переписувало відповіді та встановило маленький client_max_body_size. Завантаження медіа через REST супроводжувались 413. Одночасно правило «підозрілий рядок запиту» відмічало шаблони rest_route= і блокувало fallback-запити, які використовували деякі клієнти й плагіни.
Виправлення було банально простим: підняти ліміти розміру тіла в релевантних location-блоках, вимкнути переписування для JSON-відповідей і відрегулювати правила WAF для відомих REST-маршрутів. Також вони додали моніторинг конкретно для статус-кодів /wp-json/, щоб ловити регресії раніше, ніж помітила маркетинг-команда.
Висновок: оптимізації дозволені. Але вони потребують allowlist-ментальності для API. Якщо ваш проксі модифікує payload, ви виконуєте роботу додатка без тестів додатка.
Міні-історія 3: Нудна, але правильна практика, що врятувала ситуацію
Глобальна організація керувала кількома інстансами WordPress з ідентичною інфраструктурою-as-code для Nginx і PHP-FPM. Їхня SRE-команда запровадила одну нудну політику: кожна конфігураційна зміна мала канарку, і кожна канарка мала синтетичну перевірку, яка запитувала /wp-json/, публічний ендпоінт і автентифікований ендпоінт.
Одного тижня незначна зміна Nginx, спрямована на посилення безпеки, випадково видалила fallback try_files і перетворила невідомі шляхи на 404. Публічний сайт все ще працював, бо більшість сторінок кешувалися і загальні маршрути існували. Але REST-запити почали падати миттєво на канарці.
Синтетичні перевірки спіймали це за кілька хвилин. Вони відкотили зміни до повного розгортання. Жодних звернень клієнтів. Жодних панічних розкопок в Slack. Лише чистий відкат і невеликий постмортем.
Висновок: «нудні» практики — канарки, синтетичні перевірки і конфіг у версійному контролі — рятують вас від хитрощів. REST — ідеальна ціль для канарки, бо швидко проходить маршрутизацію, PHP і логіку додатка.
Типові помилки: симптом → корінна причина → виправлення
Цей розділ призначений для використання під тиском. Знайдіть ваш симптом і зробіть виправлення. Не дискутуйте філософію під час простою.
1) WordPress каже «REST API encountered an error», і /wp-json повертає HTML
- Симптом:
content-type: text/html, можливо сторінка входу або сторінка блокування. - Корінна причина: WAF/CDN блок, редирект на вхід або кешований шаблон помилки.
- Виправлення: Обійдіть edge до origin і порівняйте. Вимкніть кешування для
/wp-json. Додайте правила дозволу WAF для REST-шляхів/методів. Підтвердіть, що для API маршрутів не застосовується редирект на вхід.
2) /wp-json працює, але автентифіковані ендпоінти повертають 401 в редакторі
- Симптом: Публічні ендпоінти OK; дії в редакторі падають; випадкові «nonce invalid».
- Корінна причина: Невідповідність домену/схеми cookie, проблеми SameSite cookie, проксі не надсилає правильний
X-Forwarded-Protoабо кешування nonce. - Виправлення: Вирівняйте
homeіsiteurl. Виправте заголовки проксі і канонічні редиректи. Переконайтеся, що автентифіковані REST-запити ніде не кешуються.
3) /wp-json повертає 404, але index.php?rest_route працює
- Симптом: Шлях перезапису не працює, прямий запит працює.
- Корінна причина: Неправильна конфігурація перезапису Nginx/Apache, .htaccess ігнорується або відсутній try_files fallback.
- Виправлення: Виправте конфігурацію сервера. Скиньте перезаписи. Повторно тестуйте обидві кінцеві точки до ідентичної поведінки.
4) REST-запити повертають 403 тільки для POST/PUT/DELETE
- Симптом: GET працює; записування блокується.
- Корінна причина: Правило WAF блокує методи, false positive мод_security CRS або обмеження методів на проксі.
- Виправлення: Перегляньте логи WAF за ID правила і налаштуйте винятки вузько для
/wp-json. Переконайтеся, що проксі дозволяє ці методи до origin.
5) REST повертає 500 періодично, у логах видно фатали PHP
- Симптом: 500/502 з трасуванням у логах PHP.
- Корінна причина: Баг плагіна/теми або несумісність версії PHP.
- Виправлення: Відкотіть зміну, що внесла фатали. Запатчіть плагін. Додайте автоматизовані тести або хоча б синтетичні REST-перевірки в pipeline деплою.
6) REST повільний; іноді 504 Gateway Timeout
- Симптом: Довгі відповіді, потім таймаути під навантаженням.
- Корінна причина: Вичерпання воркерів PHP-FPM, контенція БД, повільне сховище, зовнішні API у шляху запиту.
- Виправлення: Профілюйте повільні запити; обережно збільшіть потужність FPM; оптимізуйте БД і object cache; додайте таймаути/схему переключення для зовнішніх викликів; блокуй аб’юз клієнтів.
7) Помилки CORS у консолі браузера, curl працює
- Симптом: Браузер блокує запити; curl успішний.
- Корінна причина: Відсутні/заблоковані заголовки CORS, OPTIONS блокується, невірні заголовки Origin.
- Виправлення: Дозвольте OPTIONS через WAF/проксі і налаштуйте коректні
Access-Control-Allow-Originта пов’язані заголовки, бажано з allowlist-ом.
Контрольні списки / покроковий план
Контрольний список A: У вас зараз помилка REST
- Запустіть curl до
/wp-json/і зафіксуйте статус, заголовки та тип тіла відповіді (JSON vs HTML). - Запустіть curl до
/index.php?rest_route=/і порівняйте. - Протестуйте з origin-хоста з заголовком
Host:, щоб обійти edge. - Якщо причетний edge: перевірте логи WAF/CDN на блокування, ліміти та обмеження методів.
- Якщо причетні перезаписи: перевірте
try_filesNginx або AllowOverride/mod_rewrite Apache. - Якщо причина в автентифікації: протестуйте Application Password; потім cookie+nonce-потоки редактора.
- Якщо 500/таймаут: перевірте логи PHP, насичення FPM, стан БД і останні деплои/зміни плагінів.
Контрольний список B: Запобігти наступному інциденту (операційна гігієна)
- Додайте синтетичні перевірки для
/wp-json/, публічного ендпоінту і автентифікованого ендпоінту. - Інструментуйте статус-коди для
/wp-jsonв логах доступу і ставте алерти на сплески 4xx/5xx. - Покладіть конфіги Nginx/Apache в контроль версій; пропускайте зміни через канарки.
- Ясно визначте політику кешування: які REST-ендпоінти кешуються і як будуються ключі кешу.
- Створіть процес винятків WAF: allowlist шляхів/методів, відстеження ID правил і огляди термінів дії.
- Тримайте оновлення плагінів у стадіях; моніторте синтетичні REST-перевірки після деплою.
Контрольний список C: Коли підозрюєте конфлікт плагіна
- Зробіть знімок списку активних плагінів.
- Вимикайте по одному ризикованому плагіну (безпека/кешування).
- Повторно тестуйте
/wp-json/і той маршрут, що падає. - Коли працює — вмикайте інших по черзі, щоб ізолювати.
- Застосуйте конфігураційне виправлення або замініть плагін, якщо він не може співіснувати з вашими вимогами.
Цікаві факти та історія (коротко, корисний контекст)
- Факт 1: WordPress REST API починався як feature-плагін перед злиттям у ядро, тому старі статті досі згадують «REST API plugin».
- Факт 2: Базова кінцева точка
/wp-json/— це індексний документ — API «змістова частина», тому зламаний індекс часто означає проблему маршрутизації або блокування, а не «відсутні записи». - Факт 3: Gutenberg (блоковий редактор) сильно залежить від REST. Якщо REST нестабільний, редактор зазвичай перший починає скаржитися.
- Факт 4: WordPress може обслуговувати REST через параметр запиту (
rest_route), що робить його відмінним інструментом для розрізнення проблем перезаписів від проблем додатка. - Факт 5: Багато продуктів безпеки історично трактували JSON-ендпоінти як «поверхню API» і за замовчуванням включали жорсткішу інспекцію, через що false positive часто зосереджуються навколо
/wp-json. - Факт 6: REST-маршрути реєструються кодом під час виконання. Якщо плагін не завантажився (фатальна помилка), цілі неймспейси маршрутів можуть зникнути, перетворивши очікувані 200 на 404.
- Факт 7: Автентифікація WordPress для браузерних REST-викликів часто використовує nonce замість Basic Auth; nonce чутливі до часу і легко ламаються кешуванням або зсувом часу.
- Факт 8: Історично деякі хости і плагіни блокували шляхи
/wp-json/wp/v2/usersдля зменшення ризику перелічення користувачів, інколи блокуючи занадто широко і ламаючи легітимні дії адміністратора. - Факт 9: Політики кешування CDN, що ігнорують cookies, можуть спричинити витік API-відповідей між сесіями — рідко, але траплялося достатньо, щоб досвідчені SRE нервувалися щодо цього.
Питання й відповіді
1) Як зрозуміти, чи WordPress REST впав чи лише редактор?
Запустіть curl -D- https://example.com/wp-json/. Якщо це 200 з JSON — REST працює. Якщо редактор не працює, зосередьтеся на автентифікації/nonce/cookies і кешуванні.
2) Чому /wp-json працює, але /wp-json/wp/v2/posts падає?
Індекс може завантажитись, тоді як конкретні маршрути падають через код плагіна/теми, permission callbacks або проблеми реєстрації маршруту. Перевірте логи PHP і відключайте плагіни для ізоляції.
3) Який найшвидший тест перезаписів?
Порівняйте /wp-json/ з /index.php?rest_route=/. Якщо працює лише другий — проблема в перезаписах вебсервера.
4) Чому я отримую 401 Unauthorized хоча в адмінці я залогінений?
Зазвичай це невідповідність cookie/nonce через домен або схему (www vs non-www, http vs https), політику SameSite cookie або проксі, що неправильно повідомляє HTTPS.
5) Як зрозуміти, чи WAF блокує REST?
Шукайте 403 з HTML-блок-сторінками, заголовки CDN/WAF або блокування лише для POST/OPTIONS. Обійдіть edge до origin; якщо origin працює — це WAF/CDN.
6) Чи можу я кешувати відповіді REST API?
Так, вибірково. Кешуйте лише справді публічні, неперсоналізовані ендпоінти. Ніколи не кешуйте запити з cookie на edge, якщо не можете довести безпеку ключів кешу і ізоляцію.
7) Чому я бачу помилки CORS, але curl працює?
Браузери застосовують CORS і часто виконують preflight OPTIONS. Якщо OPTIONS блокується або CORS-заголовки неправильні, браузер відмовляє. Curl на це не зважає.
8) Чи завжди вимкнення плагінів доводить, що проблема в плагіні?
Вимкнення доводить взаємодію, але не винуватість. Плагін може лише спровокувати правило проксі/WAF або виявити приховану проблему конфігурації. Використовуйте це, щоб звузити сферу, а потім знайдіть справжню корінну причину.
9) Який найбезпечніший метод автентифікації для сервер‑до‑сервер REST‑викликів?
Application Passwords зазвичай найменш болісні в ядрі WordPress. Використовуйте HTTPS, обмежуйте права, ротуйте облікові дані і моніторте на зловживання.
10) Чому REST падає тільки під навантаженням?
Тому що під навантаженням ви досягаєте лімітів: воркери PHP-FPM, з’єднання БД, затримки I/O або лімітування. REST-ендпоінти балакучі і швидко підсилюють вузькі місця.
Висновок: наступні кроки, що дійсно зменшують рецидиви
Якщо зробите лише кілька дій з цього списку, зробіть ці:
- Зробіть
/wp-json/спостережуваним. Додайте синтетичні перевірки та алерти на статус-коди і затримки. REST — це канарка для сучасного WordPress. - Розділіть маршрутизацію, автентифікацію та здоров’я бекенду. Використовуйте тест
rest_route, щоб довести перезаписи; потім тестуйте публічні ендпоінти, потім автентифіковані. - Припиніть дозволяти проміжним елементам імпровізувати. Явно визначайте кешування і WAF‑поведінку для
/wp-json. Default‑deny — ок; default‑surprise — ні. - Версифікуйте конфігурацію вашого вебсерверу. Якщо доступність REST залежить від одноразового фрагмента Nginx, вставленого три роки тому — у вас не конфіг, а фольклор.
Тепер зробіть негламурну річ: виконайте перші три завдання, запишіть спостережувану поведінку і слідуйте шару, куди вказує реальність. Збої WordPress REST рідко містять таємницю. Вони просто розподілені по стількох компонентах, що люди плутають «складно» з «незрозуміло».