diff --git a/examples/http_client.cc b/examples/http_client.cc index ba84373..c407757 100644 --- a/examples/http_client.cc +++ b/examples/http_client.cc @@ -19,10 +19,10 @@ void ExampleBasic() { auto r = session.Request(webcc::HttpRequestBuilder{} .Get() - .url("http://httpbin.org/get") - .parameter("key1", "value1") - .parameter("key2", "value2") - .header("Accept", "application/json")()); + .Url("http://httpbin.org/get") + .Parameter("key1", "value1") + .Parameter("key2", "value2") + .Header("Accept", "application/json")()); std::cout << r->content() << std::endl; } @@ -45,9 +45,9 @@ void ExampleHttps() { auto r = session.Request(webcc::HttpRequestBuilder{} .Get() - .url("https://httpbin.org/get") - .parameter("key1", "value1") - .header("Accept", "application/json")()); + .Url("https://httpbin.org/get") + .Parameter("key1", "value1") + .Header("Accept", "application/json")()); std::cout << r->content() << std::endl; } @@ -111,9 +111,9 @@ void ExamplePostFiles() { auto r = session.Request(HttpRequestBuilder{} .Post() - .url("http://httpbin.org/post") - .file_data("file1", "report.xls", "", "application/vnd.ms-excel") - .file_data("file2", "report.xml", "", "text/xml")()); + .Url("http://httpbin.org/post") + .FileData("file1", "report.xls", "", "application/vnd.ms-excel") + .FileData("file2", "report.xml", "", "text/xml")()); std::cout << r->content() << std::endl; } @@ -128,8 +128,8 @@ void ExamplePostFiles(const std::string& name, auto r = session.Request(HttpRequestBuilder{} .Post() - .url("http://httpbin.org/post") - .file(name, file_name, file_path, content_type)()); + .Url("http://httpbin.org/post") + .File(name, file_name, file_path, content_type)()); std::cout << r->content() << std::endl; } diff --git a/webcc/globals.h b/webcc/globals.h index 04b7b00..891ce58 100644 --- a/webcc/globals.h +++ b/webcc/globals.h @@ -80,6 +80,7 @@ namespace headers { const char* const kHost = "Host"; const char* const kDate = "Date"; +const char* const kAuthorization = "Authorization"; const char* const kContentType = "Content-Type"; const char* const kContentLength = "Content-Length"; const char* const kContentEncoding = "Content-Encoding"; diff --git a/webcc/http_client_session.cc b/webcc/http_client_session.cc index ce25f17..631b8a9 100644 --- a/webcc/http_client_session.cc +++ b/webcc/http_client_session.cc @@ -33,7 +33,7 @@ static void SetHeaders(const std::vector& headers, assert(headers.size() % 2 == 0); for (std::size_t i = 1; i < headers.size(); i += 2) { - builder->header(headers[i - 1], headers[i]); + builder->Header(headers[i - 1], headers[i]); } } @@ -41,11 +41,11 @@ HttpResponsePtr HttpClientSession::Get( const std::string& url, const std::vector& parameters, const std::vector& headers) { HttpRequestBuilder builder{http::methods::kGet}; - builder.url(url); + builder.Url(url); assert(parameters.size() % 2 == 0); for (std::size_t i = 1; i < parameters.size(); i += 2) { - builder.parameter(parameters[i - 1], parameters[i]); + builder.Parameter(parameters[i - 1], parameters[i]); } SetHeaders(headers, &builder); @@ -57,12 +57,12 @@ HttpResponsePtr HttpClientSession::Post( const std::string& url, std::string&& data, bool json, const std::vector& headers) { HttpRequestBuilder builder{http::methods::kPost}; - builder.url(url); + builder.Url(url); SetHeaders(headers, &builder); - builder.data(std::move(data)); - builder.json(json); + builder.Data(std::move(data)); + builder.Json(json); return Request(builder()); } @@ -71,12 +71,12 @@ HttpResponsePtr HttpClientSession::Put( const std::string& url, std::string&& data, bool json, const std::vector& headers) { HttpRequestBuilder builder{http::methods::kPut}; - builder.url(url); + builder.Url(url); SetHeaders(headers, &builder); - builder.data(std::move(data)); - builder.json(json); + builder.Data(std::move(data)); + builder.Json(json); return Request(builder()); } @@ -84,7 +84,7 @@ HttpResponsePtr HttpClientSession::Put( HttpResponsePtr HttpClientSession::Delete( const std::string& url, const std::vector& headers) { HttpRequestBuilder builder{http::methods::kDelete}; - builder.url(url); + builder.Url(url); SetHeaders(headers, &builder); @@ -95,12 +95,12 @@ HttpResponsePtr HttpClientSession::Patch( const std::string& url, std::string&& data, bool json, const std::vector& headers) { HttpRequestBuilder builder{http::methods::kPatch}; - builder.url(url); + builder.Url(url); SetHeaders(headers, &builder); - builder.data(std::move(data)); - builder.json(json); + builder.Data(std::move(data)); + builder.Json(json); return Request(builder()); } diff --git a/webcc/http_request_builder.cc b/webcc/http_request_builder.cc index cf0bd8f..af2f999 100644 --- a/webcc/http_request_builder.cc +++ b/webcc/http_request_builder.cc @@ -2,6 +2,7 @@ #include +#include "webcc/base64.h" #include "webcc/logger.h" #include "webcc/utility.h" #include "webcc/zlib_wrapper.h" @@ -27,7 +28,7 @@ static bool ReadFile(const std::string& path, std::string* output) { // ----------------------------------------------------------------------------- -HttpRequestPtr HttpRequestBuilder::operator()() { +HttpRequestPtr HttpRequestBuilder::Build() { assert(parameters_.size() % 2 == 0); assert(headers_.size() % 2 == 0); @@ -70,7 +71,7 @@ HttpRequestPtr HttpRequestBuilder::operator()() { return request; } -HttpRequestBuilder& HttpRequestBuilder::file(const std::string& name, +HttpRequestBuilder& HttpRequestBuilder::File(const std::string& name, const std::string& file_name, const std::string& file_path, const std::string& content_type) { @@ -84,6 +85,19 @@ HttpRequestBuilder& HttpRequestBuilder::file(const std::string& name, return *this; } +HttpRequestBuilder& HttpRequestBuilder::Auth(const std::string& type, + const std::string& credentials) { + headers_.push_back(http::headers::kAuthorization); + headers_.push_back(type + " " + credentials); + return *this; +} + +HttpRequestBuilder& HttpRequestBuilder::AuthBasic(const std::string& login, + const std::string& password) { + auto credentials = Base64Encode(login + ":" + password); + return Auth("Basic", credentials); +} + void HttpRequestBuilder::SetContent(HttpRequestPtr request, std::string&& data) { if (gzip_ && data.size() > kGzipThreshold) { @@ -102,7 +116,7 @@ void HttpRequestBuilder::SetContent(HttpRequestPtr request, void HttpRequestBuilder::CreateFormData(std::string* data, const std::string& boundary) { - for (File& file : files_) { + for (UploadFile& file : files_) { data->append("--" + boundary + kCRLF); // Content-Disposition header diff --git a/webcc/http_request_builder.h b/webcc/http_request_builder.h index 26e2f67..880344f 100644 --- a/webcc/http_request_builder.h +++ b/webcc/http_request_builder.h @@ -15,79 +15,94 @@ public: } // Build the request. - HttpRequestPtr operator()(); + HttpRequestPtr Build(); - HttpRequestBuilder& Get() { return method(http::methods::kGet); } - HttpRequestBuilder& Head() { return method(http::methods::kHead); } - HttpRequestBuilder& Post() { return method(http::methods::kPost); } - HttpRequestBuilder& Put() { return method(http::methods::kPut); } - HttpRequestBuilder& Delete() { return method(http::methods::kDelete); } - HttpRequestBuilder& Patch() { return method(http::methods::kPatch); } + HttpRequestPtr operator()() { + return Build(); + } + + HttpRequestBuilder& Get() { return Method(http::methods::kGet); } + HttpRequestBuilder& Head() { return Method(http::methods::kHead); } + HttpRequestBuilder& Post() { return Method(http::methods::kPost); } + HttpRequestBuilder& Put() { return Method(http::methods::kPut); } + HttpRequestBuilder& Delete() { return Method(http::methods::kDelete); } + HttpRequestBuilder& Patch() { return Method(http::methods::kPatch); } + + // NOTE: + // The naming convention doesn't follow Google C++ Style for + // consistency and simplicity. - HttpRequestBuilder& method(const std::string& method) { + HttpRequestBuilder& Method(const std::string& method) { method_ = method; return *this; } - HttpRequestBuilder& url(const std::string& url) { + HttpRequestBuilder& Url(const std::string& url) { url_ = url; return *this; } - HttpRequestBuilder& parameter(const std::string& key, + HttpRequestBuilder& Parameter(const std::string& key, const std::string& value) { parameters_.push_back(key); parameters_.push_back(value); return *this; } - HttpRequestBuilder& data(const std::string& data) { + HttpRequestBuilder& Data(const std::string& data) { data_ = data; return *this; } - HttpRequestBuilder& data(std::string&& data) { + HttpRequestBuilder& Data(std::string&& data) { data_ = std::move(data); return *this; } - HttpRequestBuilder& json(bool json = true) { + HttpRequestBuilder& Json(bool json = true) { json_ = json; return *this; } // Upload a file with its path. - HttpRequestBuilder& file(const std::string& name, + // TODO: UNICODE file path. + HttpRequestBuilder& File(const std::string& name, const std::string& file_name, - const std::string& file_path, // TODO: UNICODE + const std::string& file_path, const std::string& content_type = ""); // Upload a file with its data. - HttpRequestBuilder& file_data(const std::string& name, - const std::string& file_name, - std::string&& file_data, - const std::string& content_type = "") { + HttpRequestBuilder& FileData(const std::string& name, + const std::string& file_name, + std::string&& file_data, + const std::string& content_type = "") { files_.push_back({name, file_name, file_data, content_type}); return *this; } - HttpRequestBuilder& gzip(bool gzip = true) { + HttpRequestBuilder& Gzip(bool gzip = true) { gzip_ = gzip; return *this; } - HttpRequestBuilder& header(const std::string& key, + HttpRequestBuilder& Header(const std::string& key, const std::string& value) { headers_.push_back(key); headers_.push_back(value); return *this; } - HttpRequestBuilder& keep_alive(bool keep_alive) { + HttpRequestBuilder& KeepAlive(bool keep_alive) { keep_alive_ = keep_alive; return *this; } + HttpRequestBuilder& Auth(const std::string& type, + const std::string& credentials); + + HttpRequestBuilder& AuthBasic(const std::string& login, + const std::string& password); + private: void SetContent(HttpRequestPtr request, std::string&& data); @@ -107,10 +122,11 @@ private: // Is the data to send a JSON string? bool json_ = false; + // A file to upload. // Examples: // { "images", "example.jpg", "BinaryData", "image/jpeg" } // { "file", "report.csv", "BinaryData", "" } - struct File { + struct UploadFile { std::string name; std::string file_name; std::string file_data; // Binary file data @@ -118,7 +134,7 @@ private: }; // Files to upload for a POST (or PUT?) request. - std::vector files_; + std::vector files_; // Compress the request content. // NOTE: Most servers don't support compressed requests.