Вопрос или проблема
Я немного изменил файл шаблона, с помощью которого генерируются конфигурации nginx, результат следующий:
# from nginxproxy/nginx-proxy
# uknp.dock/
upstream uknp.dock {
# Container: WSDD-Web-Server-PHP8.3
# networks:
# wsdd-network (reachable)
# IP address: 172.18.0.2
# exposed ports (first ten): 10000/tcp 80/tcp
# default port: 80
# using port: 80
server 172.18.0.2:80;
}
server {
server_name uknp.dock;
access_log /var/log/nginx/access.log vhost;
http2 on;
listen 80 ;
location /.well-known/acme-challenge/ {
proxy_intercept_errors off;
fastcgi_intercept_errors off;
auth_basic off;
allow all;
root /usr/share/nginx/html;
try_files $uri =404;
break;
}
listen 443 ssl ;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_certificate /etc/nginx/certs/uknp.dock.crt;
ssl_certificate_key /etc/nginx/certs/uknp.dock.key;
location / {
proxy_intercept_errors off;
fastcgi_intercept_errors off;
proxy_pass http://uknp.dock;
set $upstream_keepalive false;
# Add these headers to keep the original status codes
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
# Ensure that HTTP status codes are not modified
proxy_ignore_headers Set-Cookie;
proxy_pass_request_headers on;
}
# custom 419 error
error_page 419 = /custom_419.html;
location = /custom_419.html {
internal;
add_header Content-Type text/html;
return 419 "Session expired or CSRF token invalid.";
}
}
Это, предположительно, моя конфигурация обратного прокси, указывающая на контейнер Apache (который работал нормально, пока мне не пришлось реализовать статус код 419 для CSRF).
Независимо от моей конфигурации Nginx, он продолжает преобразовывать/перезаписывать ошибку 419 в 500…
<?php
// Set headers to avoid caching
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');
// Set custom header for CSRF
header('X-CSRF-TOKEN: expired_token_12345');
// Set status code 419 (CSRF Token Expired)
http_response_code(419);
// Response content in JSON format
header('Content-Type: application/json');
echo json_encode([
'error' => true,
'message' => 'CSRF token has expired',
'code' => 419,
'status' => 'CSRF_TOKEN_EXPIRED'
]);
Примечание: я уже перезапустил сервисы/контейнеры.
Ответ или решение
В приведенной вами конфигурации nginx выступает в роли обратного прокси, который необходим для маршрутизации запросов к Apache-серверу, находящемуся в контейнере. Основная проблема, с которой вы столкнулись, заключается в том, что при попытке вернуть статус код 419 для обработки ошибок CSRF, nginx почему-то заменяет этот статус код на 500. Давайте рассмотрим возможные причины и решения этой проблемы.
Теория
В мире веб-разработки статус код HTTP 419 не является официальным стандартом в спецификации HTTP. Однако он часто используется в приложениях для обозначения ошибок, связанных с истечением срока действия сессии или неправильно установленным CSRF-токеном. Обычно разработчики используют этот статус код для улучшения взаимодействия с пользователем.
При этом форматирование и обработка нестандартных кодов ошибок может вызывать проблемы в некоторых серверах и конфигурациях. Так как статус код 500 указывает на внутреннюю ошибку сервера, это может означать, что nginx просто не знает, как обрабатывать нестандартный статус код 419 и потому заменяет его на 500.
Пример
Давайте разберем вашу конфигурацию nginx:
server {
...
location / {
proxy_intercept_errors off;
fastcgi_intercept_errors off;
proxy_pass http://uknp.dock;
...
}
error_page 419 = /custom_419.html;
location = /custom_419.html {
internal;
add_header Content-Type text/html;
return 419 "Session expired or CSRF token invalid.";
}
}
Из этой конфигурации видно, что вы пытаетесь создать пользовательскую страницу ошибки для кода 419. Однако, несмотря на это, nginx, вероятно, интерпретирует ваш кастомный код 419 как ошибку и заменяет его на 500.
Применение
-
Измените конфигурацию nginx:
Убедитесь, что в вашем конфигурационном файле для nginx директивыproxy_intercept_errors
иfastcgi_intercept_errors
отключены. Это должно препятствовать nginx перехватывать и изменять статус код, который возвращает ваш бэкэнд сервер.proxy_intercept_errors off; fastcgi_intercept_errors off;
-
Настройте Apache для обработки нестандартных кодов:
Убедитесь, что ваш Apache-сервер также правильно настроен для обработки и возврата нестандартных кодов ошибок, таких как 419. Возможно, вам необходимо использовать модуль mod_proxy со специальной конфигурацией, если Apache проходит запросы через другой прокси. -
Изучите использование других стандартных кодов:
Рассмотрите возможность использования стандартного HTTP кода, который наиболее близко совпадает с функциональностью 419. Например, для пользователя это может быть 403 (Forbidden) с соответствующим объяснением в теле ответа, а для серверного логирования и интерпретации можно дополнительно использовать специальные заголовки. -
Логирование и диагностика:
Добавьте дополнительное логирование в nginx и Apache, чтобы точно понять, на каком этапе происходит замена статус кода. Это может быть достигнуто путем добавления строк в журналы доступа и ошибок. -
Исключения на стороне клиента:
Проверьте, как ваш фронтенд обрабатывает такие ошибки. Важно убедиться, что фронтенд правильно интерпретирует ответ сервера и отображает понятное сообщение пользователю.
Если после этих изменений ситуация остается прежней, стоит рассмотреть обновление версии nginx или использование других инструментов для маршрутизации и обработки нестандартных кодов ошибок. Регулярно проверяйте официальные источники и документы, чтобы оставаться в курсе изменений в поведении и возможностях веб-серверов.
Возможность использовать нестандартные коды ошибок, такие как 419, является удобной для специфических приложений, но всегда необходимо учитывать ограничения и особенности инфраструктуры, чтобы обеспечить стабильную работу всей системы.