Как программно составить список обслуживаемых хостов?
Как я узнал из англоязычного Stack Overflow, валидация HTTP-заголовка HOST с помощью регулярных выражений, учитывающая все возможные сценарии, может привести к довольно сложному регулярному выражению. Однако достаточно проверить, входит ли значение полученного HTTP-заголовка HOST в список поддерживаемых (тем более, что валидация с помощью регулярного выражения всё равно не избавляет от необходимости этой проверки в целях безопасности). Чтобы реализовать эти проверки, необходимо знать всё возможные варианты валидного заголовка HOST для своего случая.
Изложу всё, что я уже собрал по данной теме.
Режим локальной разработки
В режиме локальной разработке обычно используется localhost. Вроде как, им не обязательно должен быть IP-адрес 127.0.0.1, но при каких условиях localhost будет ссылаться на другие IP-адреса - мне неизвестно.
Таким образом, при обслуживании IP-адреса 127.0.0.1 и порта 80 (по умолчанию для HTTP), валидными будут следующие заголовки HOST:
127.0.0.1localhost127.0.0.1:80localhost:80
При этом, перед сравнением присланного заголовка с одним из валидным из списка нужно будет:
- Добавить порт по умолчанию, если таковой не указан.
- Убрать нули в начале номера порта, если таковые имеются (например: 0080 -> 80).
Таким образом, список обслуживаемых хостов сокращается до:
127.0.0.1:80localhost:80
Для HTTPS, соответственно, порт по умолчанию будет 443.
Если же порт будет не умолчанию - то после двоеточия будет номер этого порта.
Режим продакшена
Полагаю, с режиме продакшена localhost-а не будет, а вместо 127.0.0.1 будет тот IP-адрес, который выдал провайдер VPS.
- Если на этот IP-адрес зарегистрировано доменное имя, то в список нужно будет добавить валидный вариант с этим доменным именем (например,
example.com:80). - С портами всё остаётся так же.
Поддержка поддоменов
Полагаю, список поддерживаемых поддоменов должен быть конечным. Если часть поддомена является параметризованной (например локаль, как ru в ru.stackoverflow.com), то все возможные значения должны быть заранее известны. Тогда, для example.com с двумя поддоменами и IP-адрсом 000.0.0.0 получаем такой список:
- 000.0.0.0:80
- example.com:80
- ru.000.0.0.0:80
- en.000.0.0.0:80
- ru.example.com:80
- en.example.com:80
Напоследок
Полагаю, алгоритм будет одинаковым для всех языков программирования, поддерживающих серверное программирования, поэтому я прошу Вас лишь заполнить пробелы в изложенных выше знаниях. Прошу Вас также не рекомендовать никаких готовых решений, так как в данном вопросе речь идёт о именно о самостоятельной реализации механизма валидации HTTP-заголовка HOST.
Ответы (1 шт):
Поддерживаемые хосты действительно следует прописывать вручную, однако это не подразумевает составления списка с перебором всех возможных вариантов. К этой задаче следует подходить с другой стороны - с разбора хоста. Хост предствляет собой запись вида
<ipv4|ipv6|domain>:<opt_port>
При этом доменное имя не может пересекаться с адресом ipv6, так как в нем не разрешается :, и не может пересекаться с адресом ipv4, так как домен верхнего уровня не может состоять только из чисел. т.е. вариантов вида ru.000.0.0.0:80 быть не может. А если используется адрес ipv6 и указывается порт, то адрес должен быть в квадратных скобках. Эти ограничения позволяют однозначно разобрать хост на компоненты за один проход не прибегая ни к каким регулярным выражениям. Причем разбор имеет смысл производить с конца, сразу определив опциональный порт, а затем перейдя к разбору адреса или домена. Получая адрес проверить его валидность тривиально по плоскому перечню разрешенных адресов. Доменное имя как раз тоже важно разбирать с конца, так как там находятся домены более высокого уровня, и получая домен
его валидность тоже несложно проверить по иерархическому перечню разрешенных доменов, начиная навигацию с домена верхнего уровня, например подобного:
{
"com":
{
"option1":...
, "subdomains":
{
"example":
{
"option1":...
, "subdomain":
{
"ru":
{
"option1":...
}
, "en":
{
"option1":...
}
}
}
}
}
}
По сути это карта сайта по иерархии доменов. И в ней же можно сразу прописывать обработчики и какие-то нужные настройки для поддерживаемых доменов.