From ef7f4692a49e826cf88a426a4fda9dca1752930d Mon Sep 17 00:00:00 2001 From: eidheim Date: Wed, 6 Jan 2016 12:45:21 +0100 Subject: [PATCH] Fixes #33 --- client_http.hpp | 144 ++++++++++++++++++++++++++++----------------- http_examples.cpp | 8 +-- https_examples.cpp | 8 +-- 3 files changed, 97 insertions(+), 63 deletions(-) diff --git a/client_http.hpp b/client_http.hpp index 32c5d14..929a6a6 100644 --- a/client_http.hpp +++ b/client_http.hpp @@ -2,6 +2,7 @@ #define CLIENT_HTTP_HPP #include +#include #include #include @@ -26,11 +27,38 @@ namespace SimpleWeb { Response(): content(&content_buffer) {}; }; - - std::shared_ptr request(const std::string& request_type, const std::string& path="/", + + std::shared_ptr request(const std::string& request_type, const std::string& path="/", boost::string_ref content="", const std::map& header=std::map()) { - 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 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(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 request_read() { + std::shared_ptr 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 diff --git a/http_examples.cpp b/http_examples.cpp index 55bb541..b8faae9 100644 --- a/http_examples.cpp +++ b/http_examples.cpp @@ -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(); diff --git a/https_examples.cpp b/https_examples.cpp index 9059a70..9ed5f81 100644 --- a/https_examples.cpp +++ b/https_examples.cpp @@ -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();