Запрос к сервису может не дойти до приложения, хотя пользователь видит обычную страницу ошибки. 404 говорит о выбранном ресурсе, 503 — о доступности обработчика, а ERR_TLS_CERT_ALTNAME_INVALID возникает ещё до HTTP. Цена смешения этих уровней — часы на исправление маршрута в коде, когда проблема находится в имени узла или на обратном прокси.
Разберём три наблюдаемых случая на одном маршруте: сначала получим ответ локального HTTP-сервера, затем отделим HTTP-статус от TLS-этапа и зафиксируем следующий запрос для проверки. Пример учебный: он не обращается к внешней сети и не выдаёт локальный результат за состояние чужой инфраструктуры.
Сначала фиксируем точку отказа
У любого запроса есть последовательность: разрешение имени, установка TCP-соединения, TLS-рукопожатие для https, отправка HTTP-запроса и чтение ответа. Важен первый наблюдаемый факт. Если клиент не смог проверить сертификат, у него нет HTTP-статуса. Если получен 404, TLS и HTTP-соединение уже состоялись, а искать нужно URI, метод или маршрутизацию.
| Наблюдение | Уровень | Первое действие | Чего не делать |
|---|---|---|---|
| Ошибка имени сертификата | TLS | сверить host и SAN | не менять HTTP-заголовки |
| 404 Not Found | HTTP-маршрут | проверить путь и метод | не увеличивать timeout |
| 503 Service Unavailable | обработчик или зависимость | прочитать заголовки и логи | не повторять POST вслепую |
| Нет ответа и timeout | сеть или сервер | разделить connect/read timeout | не считать это 500 |
Учебный HTTP-ответ на локальном сервере
Чтобы не спорить о сообщении браузера, поднимем два endpoint в одном Node-процессе. Вход — путь запроса. Ожидаемый результат — числовой статус и тело. Такой запуск показывает семантику HTTP-ответа, но не тестирует TLS: для TLS нужен отдельный сервер с сертификатом и проверкой имени.
import { createServer } from 'node:http';
const server = createServer((request, response) => {
if (request.url === '/health') {
response.writeHead(200, { 'content-type': 'text/plain' });
response.end('ok');
return;
}
response.writeHead(404, { 'content-type': 'text/plain' });
response.end('missing');
});
server.listen({ port: 0, host: '127.0.0.1' }, async () => {
const port = server.address().port;
const response = await fetch('http://127.0.0.1:' + port + '/missing');
console.log(response.status, await response.text());
server.close();
});Запустите файл командой node check-http.mjs. В консоли будет 404 missing. Входом является только локальный путь; ожидаемый результат проверяем двумя значениями. Если изменить путь на /health, получится 200 ok. Это полезнее, чем проверять только цвет страницы: статус и тело принадлежат разным частям HTTP-контракта.
Почему 503 нельзя лечить повтором по умолчанию
503 означает, что сервер временно не может обработать запрос. Заголовок Retry-After может дать клиенту ориентир, но он не делает повтор безопасным. Для GET повтор обычно не меняет ресурс, а для POST повтор способен создать вторую запись или списать деньги повторно. Перед автоматикой нужно знать семантику метода и наличие ключа идемпотентности.
В диагностической записи сохраняйте метод, путь без секретов, статус, важные заголовки, время ожидания и первый байт ответа. Не прикладывайте токен авторизации и полные cookie. Для 503 сначала проверяется зависимость, ограничение соединений или обслуживание сервера; затем выбирается контролируемый повтор с лимитом и задержкой.
Ошибка сертификата находится до HTTP
TLS 1.3 устанавливает защищённый канал и проверяет имя узла в сертификате. Имя берётся из URL и должно совпасть с одним из значений Subject Alternative Name. Если клиент подключается к IP вместо доменного имени, использует устаревший alias или получает сертификат другого виртуального хоста, HTTP-заголовок Host проблему не исправит: запрос ещё не отправлен.
Практическая граница видна в подробном выводе клиента: после строки об успешной проверке сертификата и до ответа 404 проблема уже относится к HTTP-маршруту. Если TLS завершается исключением, статус и тело приложения искать бессмысленно. Это простое разделение экономит одну итерацию проверки.
Проверка должна разделять имя, цепочку доверия и срок действия. В учебной диагностике достаточно зафиксировать hostname, адрес назначения и текст ошибки библиотеки. Флаг вроде --insecure может подтвердить, что сервер отвечает, но он отключает проверку и не является исправлением. После такого эксперимента соединение нужно закрыть и повторить проверку с обычной валидацией.
Порядок диагностики
- Записать URL, метод, момент запроса и безопасный идентификатор запроса; убрать Authorization, Cookie и персональные параметры.
- Проверить разрешение имени и адрес назначения отдельно от приложения.
- Для HTTPS проверить hostname, SAN, срок действия и цепочку сертификата обычным клиентом.
- Только после успешного TLS посмотреть HTTP-статус, заголовок Allow, Location, Retry-After и тело.
- Сопоставить метод и действие: повтор разрешать только для операции с понятной идемпотентностью.
- Зафиксировать один следующий тест и ожидаемый результат, например «/health возвращает 200, /missing — 404».
Ограничения и следующий шаг
Локальный сервер не показывает работу CDN, DNS-балансировщика, корпоративного proxy или реального центра сертификации. Статус 404 не доказывает, что маршрут одинаково настроен во всех регионах, а 503 не называет виновную зависимость. Для этого нужны согласованные логи и сетевые наблюдения с разрешённым доступом.
Следующим шагом соберите две безопасные записи: успешный запрос к health-endpoint и один ошибочный запрос с тем же hostname. Сравните этап, статус, заголовки и время. Если различие появляется до HTTP, оставайтесь на TLS или сети; если оба запроса дошли до сервера, переходите к маршруту и контракту приложения.
Проверяемые источники
- RFC 9110 — HTTP Semantics — IETF Standards Track, June 2022. Нужен для различения методов, статусов, заголовков, маршрутизации и ответа посредника. Граница применимости: Не объясняет конкретную конфигурацию прокси, DNS или причину ошибки в вашем сервисе.
- RFC 8446 — The Transport Layer Security (TLS) Protocol Version 1.3 — IETF Standards Track, August 2018. Нужен для разбора рукопожатия TLS 1.3, проверки имени узла и сообщения об ошибке сертификата. Граница применимости: Не подтверждает доверие к конкретному центру сертификации и не заменяет проверку ключевого материала.