33 #ifndef _IDENTT_HTTP_CLIENTBASE_HPP_ 34 #define _IDENTT_HTTP_CLIENTBASE_HPP_ 43 template <
class socket_type>
47 using RespPtr = std::shared_ptr<Response>;
50 const std::string& request_type,
51 const std::string& path=
"/",
52 const std::map<std::string,
53 std::string>& header=std::map<std::string, std::string>())
55 std::stringstream empty_ss;
56 return request(request_type, path, empty_ss, header);
59 RespPtr request(
const std::string& request_type,
const std::string& path, std::ostream& content,
60 const std::map<std::string, std::string>& header=std::map<std::string, std::string>())
62 std::string corrected_path=path;
63 if(corrected_path==
"") corrected_path=
"/";
65 content.seekp(0, std::ios::end);
66 size_t content_length=content.tellp();
67 content.seekp(0, std::ios::beg);
69 boost::asio::streambuf write_buffer;
70 std::ostream write_stream(&write_buffer);
71 write_stream << request_type <<
" " << corrected_path <<
" HTTP/1.1\r\n";
72 write_stream <<
"Host: " << host <<
"\r\n";
73 for(
auto& h: header) {
74 write_stream << h.first <<
": " << h.second <<
"\r\n";
77 write_stream <<
"Content-Length: " << std::to_string(content_length) <<
"\r\n";
78 write_stream <<
"\r\n";
80 write_stream << content.rdbuf();
86 boost::asio::write(*socket, write_buffer);
87 size_t bytes_transferred = boost::asio::read_until(*socket, response->content_buffer,
"\r\n\r\n");
88 size_t num_additional_bytes=response->content_buffer.size()-bytes_transferred;
89 parse_response_header(response, response->content);
91 if(response->header.count(
"Content-Length")>0) {
92 boost::asio::read(*socket, response->content_buffer,
93 boost::asio::transfer_exactly(stoull(response->header[
"Content-Length"])-num_additional_bytes));
94 }
else if(response->header.count(
"Transfer-Encoding")>0 && response->header[
"Transfer-Encoding"]==
"chunked") {
95 boost::asio::streambuf streambuf;
96 std::ostream content(&streambuf);
101 size_t bytes_transferred = boost::asio::read_until(*socket, response->content_buffer,
"\r\n");
103 getline(response->content, line);
104 bytes_transferred-=line.size()+1;
106 length=stoull(line, 0, 16);
108 size_t num_additional_bytes=response->content_buffer.size()-bytes_transferred;
110 if((2+length)>num_additional_bytes) {
111 boost::asio::read(*socket, response->content_buffer,
112 boost::asio::transfer_exactly(2+length-num_additional_bytes));
115 buffer.resize(length);
116 response->content.read(&buffer[0], length);
117 content.write(&buffer[0], length);
120 response->content.get();
121 response->content.get();
124 std::ostream response_content_output_stream(&response->content_buffer);
125 response_content_output_stream << content.rdbuf();
127 }
catch(
const std::exception& e) {
129 throw std::invalid_argument(e.what());
136 boost::asio::io_service asio_io_service;
137 boost::asio::ip::tcp::endpoint asio_endpoint;
138 boost::asio::ip::tcp::resolver asio_resolver;
140 std::shared_ptr<socket_type> socket;
146 ClientBase(
const std::string& host_port,
unsigned short default_port) :
147 asio_resolver(asio_io_service), socket_error(
false)
149 size_t host_end=host_port.find(
':');
150 if(host_end==std::string::npos) {
154 host=host_port.substr(0, host_end);
155 port=(
unsigned short)stoul(host_port.substr(host_end+1));
158 asio_endpoint=boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port);
161 virtual void connect()=0;
163 void parse_response_header(RespPtr response, std::istream& stream)
const 166 getline(stream, line);
167 size_t version_end=line.find(
' ');
168 if(version_end!=std::string::npos) {
169 response->http_version=line.substr(5, version_end-5);
170 response->status_code=line.substr(version_end+1, line.size()-version_end-2);
172 getline(stream, line);
173 size_t param_end=line.find(
':');
174 while(param_end!=std::string::npos) {
175 size_t value_start=param_end+1;
176 if(line[value_start]==
' ')
179 response->header[line.substr(0, param_end)]=line.substr(value_start, line.size()-value_start-1);
181 getline(stream, line);
182 param_end=line.find(
':');
Definition: ClientResponse.hpp:45
Definition: CryptoBase.hpp:49
Definition: HttpClientBase.hpp:44