Fixes #33
This commit is contained in:
parent
99204ec73d
commit
ef7f4692a4
3 changed files with 97 additions and 63 deletions
144
client_http.hpp
144
client_http.hpp
|
|
@ -2,6 +2,7 @@
|
|||
#define CLIENT_HTTP_HPP
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
|
|
@ -26,11 +27,38 @@ namespace SimpleWeb {
|
|||
|
||||
Response(): content(&content_buffer) {};
|
||||
};
|
||||
|
||||
std::shared_ptr<Response> request(const std::string& request_type, const std::string& path="/",
|
||||
|
||||
std::shared_ptr<Response> request(const std::string& request_type, const std::string& path="/", boost::string_ref content="",
|
||||
const std::map<std::string, std::string>& header=std::map<std::string, std::string>()) {
|
||||
std::stringstream empty_ss;
|
||||
return request(request_type, path, empty_ss, header);
|
||||
std::string corrected_path=path;
|
||||
if(corrected_path=="")
|
||||
corrected_path="/";
|
||||
|
||||
boost::asio::streambuf write_buffer;
|
||||
std::ostream write_stream(&write_buffer);
|
||||
write_stream << request_type << " " << corrected_path << " HTTP/1.1\r\n";
|
||||
write_stream << "Host: " << host << "\r\n";
|
||||
for(auto& h: header) {
|
||||
write_stream << h.first << ": " << h.second << "\r\n";
|
||||
}
|
||||
if(content.size()>0)
|
||||
write_stream << "Content-Length: " << content.size() << "\r\n";
|
||||
write_stream << "\r\n";
|
||||
|
||||
try {
|
||||
connect();
|
||||
|
||||
boost::asio::write(*socket, write_buffer);
|
||||
if(content.size()>0)
|
||||
boost::asio::write(*socket, boost::asio::buffer(content.data(), content.size()));
|
||||
|
||||
}
|
||||
catch(const std::exception& e) {
|
||||
socket_error=true;
|
||||
throw std::invalid_argument(e.what());
|
||||
}
|
||||
|
||||
return request_read();
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> request(const std::string& request_type, const std::string& path, std::iostream& content,
|
||||
|
|
@ -51,68 +79,22 @@ namespace SimpleWeb {
|
|||
write_stream << h.first << ": " << h.second << "\r\n";
|
||||
}
|
||||
if(content_length>0)
|
||||
write_stream << "Content-Length: " << std::to_string(content_length) << "\r\n";
|
||||
write_stream << "Content-Length: " << content_length << "\r\n";
|
||||
write_stream << "\r\n";
|
||||
if(content_length>0)
|
||||
write_stream << content.rdbuf();
|
||||
|
||||
std::shared_ptr<Response> response(new Response());
|
||||
|
||||
try {
|
||||
connect();
|
||||
|
||||
|
||||
boost::asio::write(*socket, write_buffer);
|
||||
|
||||
size_t bytes_transferred = boost::asio::read_until(*socket, response->content_buffer, "\r\n\r\n");
|
||||
|
||||
size_t num_additional_bytes=response->content_buffer.size()-bytes_transferred;
|
||||
|
||||
parse_response_header(response, response->content);
|
||||
|
||||
if(response->header.count("Content-Length")>0) {
|
||||
boost::asio::read(*socket, response->content_buffer,
|
||||
boost::asio::transfer_exactly(stoull(response->header["Content-Length"])-num_additional_bytes));
|
||||
}
|
||||
else if(response->header.count("Transfer-Encoding")>0 && response->header["Transfer-Encoding"]=="chunked") {
|
||||
boost::asio::streambuf streambuf;
|
||||
std::ostream content(&streambuf);
|
||||
|
||||
size_t length;
|
||||
std::string buffer;
|
||||
do {
|
||||
size_t bytes_transferred = boost::asio::read_until(*socket, response->content_buffer, "\r\n");
|
||||
std::string line;
|
||||
getline(response->content, line);
|
||||
bytes_transferred-=line.size()+1;
|
||||
line.pop_back();
|
||||
length=stoull(line, 0, 16);
|
||||
|
||||
size_t num_additional_bytes=response->content_buffer.size()-bytes_transferred;
|
||||
|
||||
if((2+length)>num_additional_bytes) {
|
||||
boost::asio::read(*socket, response->content_buffer,
|
||||
boost::asio::transfer_exactly(2+length-num_additional_bytes));
|
||||
}
|
||||
|
||||
buffer.resize(length);
|
||||
response->content.read(&buffer[0], length);
|
||||
content.write(&buffer[0], length);
|
||||
|
||||
//Remove "\r\n"
|
||||
response->content.get();
|
||||
response->content.get();
|
||||
} while(length>0);
|
||||
|
||||
std::ostream response_content_output_stream(&response->content_buffer);
|
||||
response_content_output_stream << content.rdbuf();
|
||||
}
|
||||
}
|
||||
catch(const std::exception& e) {
|
||||
socket_error=true;
|
||||
throw std::invalid_argument(e.what());
|
||||
}
|
||||
|
||||
return response;
|
||||
return request_read();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -168,6 +150,62 @@ namespace SimpleWeb {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Response> request_read() {
|
||||
std::shared_ptr<Response> response(new Response());
|
||||
|
||||
try {
|
||||
size_t bytes_transferred = boost::asio::read_until(*socket, response->content_buffer, "\r\n\r\n");
|
||||
|
||||
size_t num_additional_bytes=response->content_buffer.size()-bytes_transferred;
|
||||
|
||||
parse_response_header(response, response->content);
|
||||
|
||||
if(response->header.count("Content-Length")>0) {
|
||||
boost::asio::read(*socket, response->content_buffer,
|
||||
boost::asio::transfer_exactly(stoull(response->header["Content-Length"])-num_additional_bytes));
|
||||
}
|
||||
else if(response->header.count("Transfer-Encoding")>0 && response->header["Transfer-Encoding"]=="chunked") {
|
||||
boost::asio::streambuf streambuf;
|
||||
std::ostream content(&streambuf);
|
||||
|
||||
size_t length;
|
||||
std::string buffer;
|
||||
do {
|
||||
size_t bytes_transferred = boost::asio::read_until(*socket, response->content_buffer, "\r\n");
|
||||
std::string line;
|
||||
getline(response->content, line);
|
||||
bytes_transferred-=line.size()+1;
|
||||
line.pop_back();
|
||||
length=stoull(line, 0, 16);
|
||||
|
||||
size_t num_additional_bytes=response->content_buffer.size()-bytes_transferred;
|
||||
|
||||
if((2+length)>num_additional_bytes) {
|
||||
boost::asio::read(*socket, response->content_buffer,
|
||||
boost::asio::transfer_exactly(2+length-num_additional_bytes));
|
||||
}
|
||||
|
||||
buffer.resize(length);
|
||||
response->content.read(&buffer[0], length);
|
||||
content.write(&buffer[0], length);
|
||||
|
||||
//Remove "\r\n"
|
||||
response->content.get();
|
||||
response->content.get();
|
||||
} while(length>0);
|
||||
|
||||
std::ostream response_content_output_stream(&response->content_buffer);
|
||||
response_content_output_stream << content.rdbuf();
|
||||
}
|
||||
}
|
||||
catch(const std::exception& e) {
|
||||
socket_error=true;
|
||||
throw std::invalid_argument(e.what());
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
};
|
||||
|
||||
template<class socket_type>
|
||||
|
|
|
|||
|
|
@ -145,13 +145,11 @@ int main() {
|
|||
auto r1=client.request("GET", "/match/123");
|
||||
cout << r1->content.rdbuf() << endl;
|
||||
|
||||
string json="{\"firstName\": \"John\",\"lastName\": \"Smith\",\"age\": 25}";
|
||||
stringstream ss(json);
|
||||
auto r2=client.request("POST", "/string", ss);
|
||||
string json_string="{\"firstName\": \"John\",\"lastName\": \"Smith\",\"age\": 25}";
|
||||
auto r2=client.request("POST", "/string", json_string);
|
||||
cout << r2->content.rdbuf() << endl;
|
||||
|
||||
ss.str(json);
|
||||
auto r3=client.request("POST", "/json", ss);
|
||||
auto r3=client.request("POST", "/json", json_string);
|
||||
cout << r3->content.rdbuf() << endl;
|
||||
|
||||
server_thread.join();
|
||||
|
|
|
|||
|
|
@ -146,13 +146,11 @@ int main() {
|
|||
auto r1=client.request("GET", "/match/123");
|
||||
cout << r1->content.rdbuf() << endl;
|
||||
|
||||
string json="{\"firstName\": \"John\",\"lastName\": \"Smith\",\"age\": 25}";
|
||||
stringstream ss(json);
|
||||
auto r2=client.request("POST", "/string", ss);
|
||||
string json_string="{\"firstName\": \"John\",\"lastName\": \"Smith\",\"age\": 25}";
|
||||
auto r2=client.request("POST", "/string", json_string);
|
||||
cout << r2->content.rdbuf() << endl;
|
||||
|
||||
ss.str(json);
|
||||
auto r3=client.request("POST", "/json", ss);
|
||||
auto r3=client.request("POST", "/json", json_string);
|
||||
cout << r3->content.rdbuf() << endl;
|
||||
|
||||
server_thread.join();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue