You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
📖 Подробное описание того, что должен делать сервер
🧠 Что это означает на практике
✅ Итог
Нужно реализовать асинхронный HTTP-сервер на порту 8080.
Сервер должен: - отвечать на GET и HEAD; - на GET /{target} возвращать: - статус 200 OK - Content-Type: text/html - тело Hello, {target_without_leading_slash} - на HEAD возвращать тот же ответ, но без тела; - на остальные методы возвращать: - 405 Method Not Allowed - Content-Type: text/html - Allow: GET, HEAD - тело Invalid method. Также сервер должен: - корректно обрабатывать SIGINT и SIGTERM; - печатать Server has started... перед запуском RunWorkers(...).
Это значит, что сервер должен быть одновременно HTTP-корректным, асинхронным и корректно завершаемым по сигналам
Реализуется полноценный async HTTP server под требования задания
Почему это решение соответствует заданию
GET
🧪 Проверка GET-запроса и соответствие условию
📖 Полное объяснение того, какой ответ формирует сервер
⚙️ Как это делается в коде
✅ Итог
На запрос GET /Ivan
сервер вернёт: статус 200 OK, Content-Type: text/html, тело: Hello, Ivan
Из target удаляется ведущий /: if (!target.empty() && target.front() == '/') { target.erase(target.begin()); } потом строится: std::string body = "Hello, "s + target;
GET соответствует условию
HEAD
🧪 Проверка HEAD-запроса и соответствие условию
📖 Полное объяснение того, как сервер формирует ответ на HEAD
⚙️ Как это сделано в коде
✅ Итог
На HEAD /Ivan возвращается тот же ответ, что и для GET, но: тело пустое; Content-Length остаётся равным длине тела соответствующего GET-ответа
Это сделано здесь: if (req.method() == http::verb::head) { response.body().clear(); response.content_length(body.size()); } То есть: фактическое тело очищается; но длина выставляется по исходной строке Hello, Ivan.
Это ровно соответствует HTTP-смыслу HEAD
HEAD соответствует условию
Другие методы
🧪 Проверка POST, PUT, DELETE и других неподдерживаемых методов
📖 Полное описание ожидаемого ответа
⚙️ Как это сделано в коде
✅ Итог
Например POST, PUT, DELETE
Сервер возвращает: статус 405 Method Not Allowed, Content-Type: text/html, Allow: GET, HEAD, тело: Invalid method.
Это сделано в: const auto make_invalid_method_response = [&req]() { auto response = MakeStringResponse(http::status::method_not_allowed, "Invalid method."sv, req.version(), req.keep_alive(), ContentType::TEXT_HTML); response.set(http::field::allow, "GET, HEAD"); return response; };
Неподдерживаемые методы обрабатываются правильно
Сигналы
🧪 Корректное завершение по сигналам
📖 Полное описание поведения
⚙️ Как это сделано в коде
✅ Итог
Сервер обрабатывает: SIGINT, SIGTERM
Завершение идёт корректно, а не грубо
через: net::signal_set signals(ioc, SIGINT, SIGTERM); и корректно завершает работу через: ioc.stop();
Graceful shutdown реализован
Фраза для тестов
🧪 Требование автотестов на стартовую фразу
📖 Полное описание
⚙️ Как это выполнено
✅ Итог
Перед RunWorkers(...) выводится: Server has started...
Это прямо требуется условием
Выполнено через: std::cout << "Server has started..."sv << std::endl;
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 11
Hello, Ivan
HEAD /Ivan
curl -I http://127.0.0.1:8080/Ivan
Ожидаемо:
200 OK
Content-Type: text/html
Content-Length: 11
тела нет
GET /
curl -i http://127.0.0.1:8080/
Ожидаемо:
Hello,
Потому что target после удаления / становится пустым.
POST /Ivan
curl -i -X POST http://127.0.0.1:8080/Ivan
Ожидаемо:
HTTP/1.1 405 Method Not Allowed
Content-Type: text/html
Allow: GET, HEAD
Content-Length: 14
Invalid method.
Важное замечание про \n и curl
⚠️ Что нужно обязательно указать
📖 Полное объяснение без потери содержания
🧠 Как правильно поступать
✅ Итог
👉 то есть без \n
Не нужно добавлять \n в серверный ответ только ради красивого вида в терминале, если это ломает ожидаемую длину тела или меняет сам ответ
Вариант 3 (хитрый): не менять сервер, а сделать в curl: curl -i http://127.0.0.1:8080/Ivan && echo или: curl http://127.0.0.1:8080/Ivan; echo 👉 это добавит перенос строки снаружи, не ломая сервер
Красивый вывод делается на стороне curl, а не сервера
Что важно по архитектуре
🏗 Элемент архитектуры
📖 Полное описание без потери содержания
🧠 Почему это важно
✅ Итог
Listener
Асинхронно принимает новые соединения через async_accept.
Это даёт неблокирующий accept-loop
Сервер принимает клиентов асинхронно
SessionBase
Хранит: beast::tcp_stream, beast::flat_buffer, текущий HTTP-запрос. И реализует общий цикл: Run → Read → OnRead → HandleRequest → Write → OnWrite → Read.
Это общая база для HTTP-сессии
Повторяющаяся логика вынесена в одно место
Session<RequestHandler>
Хранит request_handler_ и вызывает его в HandleRequest.
Делает обработчик запроса настраиваемым
Гибкая архитектура
ServeHttp(...)
Запускает сервер, скрывая сложность Listener и Session.
200 OK, Content-Type: text/html, Content-Length: 11, тело Hello, Ivan
GET работает
HEAD
curl -I http://127.0.0.1:8080/Ivan
200 OK, Content-Type: text/html, Content-Length: 11, без тела
HEAD работает
Invalid method
curl -i -X POST http://127.0.0.1:8080/Ivan
405 Method Not Allowed, Allow: GET, HEAD, тело Invalid method.
Ошибка метода работает
Корректное завершение
🧩 Graceful shutdown
📖 Полное описание без потери содержания
🧠 Что происходит
✅ Итог
Сервер подписывается на: SIGINT, SIGTERM
При получении сигнала вызывается ioc.stop(), после чего сервер корректно завершает цикл обработки событий
Это даёт серверу завершиться управляемо, а не грубо
Shutdown реализован правильно
Итог
🏁 Финальный вывод по solution
📖 Полное описание без потери содержания
🧠 Что это означает
✅ Итог
Реализован асинхронный HTTP-сервер на Boost.Asio + Boost.Beast, соответствующий требованиям задания.
Он правильно отвечает на GET и HEAD, корректно обрабатывает неподдерживаемые методы, стартует с требуемой фразой, умеет завершаться по сигналам и построен на архитектуре Listener / SessionBase / Session<RequestHandler> / ServeHttp(...)
Это полноценное решение под условие задачи, а не просто минимальный код “чтобы ответить на curl”