Как программно составить список обслуживаемых хостов?

Как я узнал из англоязычного 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.1
  • localhost
  • 127.0.0.1:80
  • localhost:80

При этом, перед сравнением присланного заголовка с одним из валидным из списка нужно будет:

  1. Добавить порт по умолчанию, если таковой не указан.
  2. Убрать нули в начале номера порта, если таковые имеются (например: 0080 -> 80).

Таким образом, список обслуживаемых хостов сокращается до:

  • 127.0.0.1:80
  • localhost: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 шт):

Автор решения: user7860670

Поддерживаемые хосты действительно следует прописывать вручную, однако это не подразумевает составления списка с перебором всех возможных вариантов. К этой задаче следует подходить с другой стороны - с разбора хоста. Хост предствляет собой запись вида

<ipv4|ipv6|domain>:<opt_port>

При этом доменное имя не может пересекаться с адресом ipv6, так как в нем не разрешается :, и не может пересекаться с адресом ipv4, так как домен верхнего уровня не может состоять только из чисел. т.е. вариантов вида ru.000.0.0.0:80 быть не может. А если используется адрес ipv6 и указывается порт, то адрес должен быть в квадратных скобках. Эти ограничения позволяют однозначно разобрать хост на компоненты за один проход не прибегая ни к каким регулярным выражениям. Причем разбор имеет смысл производить с конца, сразу определив опциональный порт, а затем перейдя к разбору адреса или домена. Получая адрес проверить его валидность тривиально по плоскому перечню разрешенных адресов. Доменное имя как раз тоже важно разбирать с конца, так как там находятся домены более высокого уровня, и получая домен его валидность тоже несложно проверить по иерархическому перечню разрешенных доменов, начиная навигацию с домена верхнего уровня, например подобного:

{
   "com":
   {
       "option1":...
   ,   "subdomains":
       {
           "example":
           {
               "option1":...
           ,   "subdomain":
               {
                   "ru":
                   {
                       "option1":...
                   }
               ,   "en":
                   {
                       "option1":...
                   }
               }
           }
       }
   }
}

По сути это карта сайта по иерархии доменов. И в ней же можно сразу прописывать обработчики и какие-то нужные настройки для поддерживаемых доменов.

→ Ссылка