Я пытаюсь написать свой собственный HTTP-сервер, используя библиотеку boost :: asio для учебных целей. Я могу запустить сервер и просто отправить запрос GET (строка 40 stdout: GET /index.html HTTP / 1.1), но когда я делаю запрос POST, я также хочу прочитать данные, но опять же, строка 40 печатает только : POST /index.html HTTP / 1.1 (данные не включены). Как я могу прочитать все, включая данные?
Сервис. cpp
#include "service.h"
Service::Service(std::shared_ptr<asio::ip::tcp::socket> sock) :
_sock(sock),
_request(4096),
_response_status_code(200),
_resource_size_bytes(0)
{
std::cout << "[Service Constructor] Created an instance of service constructor." << std::endl;
}
void Service::start_handling() {
std::cout << "[Service start_handling()] Triggered!" << std::endl;
// LOOK HERE :)
asio::async_read_until(*_sock.get(), _request, "\r\n\r\n",[this](const boost::system::error_code& ec, std::size_t bytes_transferred) {
on_request_line_received(ec, bytes_transferred);
});
}
void Service::on_request_line_received(const boost::system::error_code& ec, std::size_t bytes_transferred) {
if (ec != 0) {
std::cout << "Error. Code: " << ec.value() << " Message: " << ec.message() << std::endl;
if (ec == asio::error::not_found) {
_response_status_code = 413;
send_response();
return;
} else {
on_finish();
return;
}
}
std::string request_line;
std::istream request_stream(&_request);
std::getline(request_stream, request_line);
std::cout << "request_line: " << request_line << std::endl; // GET /index.html HTTP/1.1
request_stream.get(); // Remove '\n' from the buffer
// Parse requested line
std::string request_method;
std::istringstream request_line_stream(request_line);
request_line_stream >> request_method;
// We only support GET method
if (request_method.compare("GET") != 0) {
_response_status_code = 501;
send_response();
return;
}
request_line_stream >> _requested_resource;
std::string request_http_version;
request_line_stream >> request_http_version;
if (request_http_version.compare("HTTP/1.1") != 0) {
_response_status_code = 505;
send_response();
return;
}
asio::async_read_until(*_sock.get(), _request, "\r\n\r\n", [this](const boost::system::error_code& ec, std::size_t bytes_transferred) {
on_headers_received(ec, bytes_transferred);
});
return;
}
void Service::on_headers_received(const boost::system::error_code& ec, std::size_t bytes_transferred) {
if (ec != 0) {
std::cout << "Error. Code: " << ec.value() << " Message: " << ec.message();
if (ec == asio::error::not_found) {
_response_status_code = 413;
send_response();
return;
} else {
on_finish();
return;
}
}
std::istream request_stream(&_request);
std::string header_name, header_value;
while (!request_stream.eof()) {
std::getline(request_stream, header_name, ':');
if (!request_stream.eof()) {
std::getline(request_stream, header_value, '\r');
request_stream.get();
_request_headers[header_name] = header_value;
}
}
// Now we need to process the request
process_request();
send_response();
return;
}
void Service::process_request() {
std::string resource_file_path = std::string("/home/robin/Programming/Boost_Asio_Tutorials/HTTPServer/html_files" + _requested_resource);
if (!boost::filesystem::exists(resource_file_path)) {
_response_status_code = 404;
return;
}
std::ifstream resource_fstream(resource_file_path, std::ifstream::binary);
if (!resource_fstream.is_open()) {
_response_status_code = 500;
return;
}
resource_fstream.seekg(0, std::ifstream::end);
_resource_size_bytes = static_cast<std::size_t>(resource_fstream.tellg());
_resource_buffer.reset(new char[_resource_size_bytes]);
resource_fstream.seekg(std::ifstream::beg);
resource_fstream.read(_resource_buffer.get(), _resource_size_bytes);
_response_headers += std::string("content-length") + ": " + std::to_string(_resource_size_bytes) + "\r\n";
}
void Service::send_response() {
_sock->shutdown(asio::ip::tcp::socket::shutdown_receive);
auto status_line = http_status_table.at(_response_status_code);
_response_status_line = std::string("HTTP/1.1 ") + status_line + "\r\n";
_response_headers += "\r\n";
std::vector<asio::const_buffer> response_buffers;
response_buffers.push_back(asio::buffer(_response_status_line));
if (_response_headers.length() > 0) {
response_buffers.push_back(asio::buffer(_response_headers));
}
if (_resource_size_bytes > 0) {
response_buffers.push_back(asio::buffer(_resource_buffer.get(), _resource_size_bytes));
}
asio::async_write(*_sock.get(), response_buffers, [this](const boost::system::error_code& ec, std::size_t bytes_transferred) {
on_response_sent(ec, bytes_transferred);
});
}
void Service::on_response_sent(const boost::system::error_code& ec, std::size_t bytes_transferred) {
if (ec != 0) {
std::cout << "Error. Code: " << ec.value() << " Message: " << ec.message();
}
_sock->shutdown(asio::ip::tcp::socket::shutdown_both);
on_finish();
}
void Service::on_finish() {
delete this;
}
Уведомление asio::async_read_until(*_sock.get(), _request, "\r\n\r\n"...
. Вот полный код: https://wandbox.org/permlink/Xvoo5Zm1Y2LZag3S
Читайте, пока "\ r \ n \ r \ n" не будет правильным, верно? Я также захватил пакет, используя wireshark, чтобы убедиться: