Блок задач

4. Один класс

Темы
Сложность 4

Задача «Адреса веб-сайта»

Требуется реализовать класс для распознавания адресов страниц на веб-сайте.

Входные данные

Два текстовых файла: с набором правил распознавания и с набором запросов. Если файл с набором запросов не указан, то запросы считываются из стандартного входа (std::сin).

Файл правил

Адрес страницы состоит из фрагментов, разделённых символом /. Правило распознавания имеет такую же структуру, как и адрес, и описывает, какие фрагменты адреса должны принимать фиксированное значение, а какие — могут принимать произвольное. Фрагментам с произвольным содержимым присваивается имя. В записи правила такой фрагмент начинается с символа :, после которого идёт имя.

Формат файла правил:

/<фикс_фрагмент>
/:<имя_фрагмента>
/<фикс_фрагмент>/:<имя_фрагмента>
/:<имя_фрагмента>/<фикс_фрагмент>
/<фикс_фрагмент>/:<имя_фрагмента>/<фикс_фрагмент>
...

Пример набора правил для сайта с блогами:

/posts/new
/posts/:id
/posts/:id/delete
/blogs/:name/posts/:id

Здесь id и name — имена фрагментов с произвольным содержимым.

Файл запросов состоит из строк с адресами страниц.

Например:

/posts/1
/posts/new
/posts/2
/posts/super-mega-long-title
/blogs/petya/posts/999-abc

Задача

Разработать класс Router, который позволяет сопоставить адреса страниц тому или иному правилу из заранее заданного набора.

Класс Router может быть полезен при обработке сервером входящих HTTP-запросов, когда ответное действие сервера должно соответствовать запрашиваемому адресу.

Интерфейс класса должен содержать методы:

  1. Добавление правила. Метод должен принимать в качестве аргумента строку с правилом и возвращать уникальный целочисленный идентификатор, соответствующий правилу.
  2. Поиск адреса. Метод принимает в качестве аргумента строку с адресом и пытается найти правило, которому она соответствует, возвращая номер подходящего правила. Если ничего не найдено, должно возвращаться выделенное значение (например, –1). В случае многозначности (адрес подходит под несколько правил), должно сработать правило, которое было добавлено раньше прочих. Дополнительно должна формироваться и возвращаться структура данных, содержащая в себе значения именованных фрагментов (можно использовать std::map<string, string>).

Тестирование

Необходимо реализовать набор тестов, проверяющих работу класса Router.

Выходные данные

Текстовый файл со списком найденных правил и значениями именованных фрагментов (если они есть в правиле). Если выходной файл не указан, то результаты пишутся в стандартный поток вывода (std::сout).

Например, для приведённых выше правил и запросов, результат будет выглядеть следующим образом:

2 id='1'
1
2 id='2'
2 id='super-mega-long-title'
4 name='petya' id='999-abc'

Возможное усложнение

Протокол HTTP поддерживает различные методы доступа к страницам. В процессе запроса передаётся не только адрес, но и метод: GET, POST, DELETE, PUT, PATCH.

Добавить в класс Router поддержку HTTP-методов. Каждое правило должно соответствовать одному или нескольким HTTP-методам (подумайте, как их задавать и хранить!). У метода поиска по правилам добавляется ещё один аргумент: HTTP-метод запроса. Теперь он должен искать первое правило, которое будет соответствовать HTTP-методу запроса и адресу.