From d42556ce5a42d88a36bbb57883ed059c346e55ee Mon Sep 17 00:00:00 2001 From: Chunting Gu Date: Mon, 25 Feb 2019 10:31:28 +0800 Subject: [PATCH] Forbit to create http async clients on stack since they are derived from std::shared_from_this. --- example/github_rest_client/main.cc | 9 ++++----- example/http_async_client/main.cc | 8 +++----- example/http_client/main.cc | 4 ++-- example/http_ssl_async_client/main.cc | 6 ++---- webcc/http_async_client.h | 20 +++++++++++++----- webcc/http_request.cc | 10 ++++----- webcc/http_request.h | 10 ++++----- webcc/http_ssl_async_client.h | 29 ++++++++++++++++++--------- webcc/rest_async_client.cc | 4 +--- webcc/soap_async_client.cc | 4 +--- 10 files changed, 58 insertions(+), 46 deletions(-) diff --git a/example/github_rest_client/main.cc b/example/github_rest_client/main.cc index 2920e6f..3a20d56 100644 --- a/example/github_rest_client/main.cc +++ b/example/github_rest_client/main.cc @@ -2,22 +2,21 @@ #include "json/json.h" -#include "webcc/rest_ssl_client.h" #include "webcc/logger.h" +#include "webcc/rest_ssl_client.h" const bool kSslVerify = false; #define PRINT_CONTENT 0 - static Json::Value StringToJson(const std::string& str) { Json::Value json; Json::CharReaderBuilder builder; std::stringstream stream(str); - std::string errs; - if (!Json::parseFromStream(builder, stream, &json, &errs)) { - std::cerr << errs << std::endl; + std::string errors; + if (!Json::parseFromStream(builder, stream, &json, &errors)) { + std::cerr << errors << std::endl; } return json; diff --git a/example/http_async_client/main.cc b/example/http_async_client/main.cc index d8995f8..f2555f0 100644 --- a/example/http_async_client/main.cc +++ b/example/http_async_client/main.cc @@ -9,12 +9,10 @@ // Only HttpBin.org has this issue. static void Test(boost::asio::io_context& io_context) { - auto request = webcc::HttpRequest::Make(webcc::kHttpGet, "/get", - "httpbin.org"); + auto request = webcc::HttpRequest::New(webcc::kHttpGet, "/get", + "httpbin.org"); - webcc::HttpAsyncClientPtr client{ - new webcc::HttpAsyncClient(io_context) - }; + auto client = webcc::HttpAsyncClient::New(io_context); client->SetTimeout(3); diff --git a/example/http_client/main.cc b/example/http_client/main.cc index 55de951..8144650 100644 --- a/example/http_client/main.cc +++ b/example/http_client/main.cc @@ -14,8 +14,8 @@ static void PrintError(const webcc::HttpClient& client) { int main() { WEBCC_LOG_INIT("", webcc::LOG_CONSOLE); - auto request = webcc::HttpRequest::Make(webcc::kHttpGet, "/get", - "httpbin.org"); + auto request = webcc::HttpRequest::New(webcc::kHttpGet, "/get", + "httpbin.org"); webcc::HttpClient client; diff --git a/example/http_ssl_async_client/main.cc b/example/http_ssl_async_client/main.cc index 70daa16..55b8d6c 100644 --- a/example/http_ssl_async_client/main.cc +++ b/example/http_ssl_async_client/main.cc @@ -26,15 +26,13 @@ int main(int argc, char* argv[]) { boost::asio::io_context io_context; // Leave port to default value. - auto request = webcc::HttpRequest::Make(webcc::kHttpGet, url, host); + auto request = webcc::HttpRequest::New(webcc::kHttpGet, url, host); // Verify the certificate of the peer or not. // See HttpSslClient::Request() for more details. bool ssl_verify = false; - webcc::HttpSslAsyncClientPtr client{ - new webcc::HttpSslAsyncClient{ io_context, 2000, ssl_verify } - }; + auto client = webcc::HttpSslAsyncClient::New(io_context, 2000, ssl_verify); // Response callback. auto callback = [](webcc::HttpResponsePtr response, webcc::Error error, diff --git a/webcc/http_async_client.h b/webcc/http_async_client.h index d30dbbc..b927e3c 100644 --- a/webcc/http_async_client.h +++ b/webcc/http_async_client.h @@ -5,15 +5,27 @@ namespace webcc { +class HttpAsyncClient; +typedef std::shared_ptr HttpAsyncClientPtr; + // HTTP asynchronous client. class HttpAsyncClient : public HttpAsyncClientBase { public: - explicit HttpAsyncClient(boost::asio::io_context& io_context, - std::size_t buffer_size = 0); - ~HttpAsyncClient() = default; + // Forbid to create HttpAsyncClient in stack since it's derived from + // std::shared_from_this. + static HttpAsyncClientPtr New(boost::asio::io_context& io_context, + std::size_t buffer_size = 0) { + return HttpAsyncClientPtr{ + new HttpAsyncClient(io_context, buffer_size) + }; + } + private: + explicit HttpAsyncClient(boost::asio::io_context& io_context, + std::size_t buffer_size = 0); + void Resolve() final { DoResolve(kHttpPort); } @@ -34,8 +46,6 @@ class HttpAsyncClient : public HttpAsyncClientBase { tcp::socket socket_; }; -typedef std::shared_ptr HttpAsyncClientPtr; - } // namespace webcc #endif // WEBCC_HTTP_ASYNC_CLIENT_H_ diff --git a/webcc/http_request.cc b/webcc/http_request.cc index 09fff75..396f97c 100644 --- a/webcc/http_request.cc +++ b/webcc/http_request.cc @@ -33,11 +33,11 @@ void HttpRequest::Prepare() { } // static -HttpRequestPtr HttpRequest::Make(const std::string& method, - const std::string& url, - const std::string& host, - const std::string& port, - bool prepare) { +HttpRequestPtr HttpRequest::New(const std::string& method, + const std::string& url, + const std::string& host, + const std::string& port, + bool prepare) { HttpRequestPtr request{ new HttpRequest{ method, url, host, port } }; diff --git a/webcc/http_request.h b/webcc/http_request.h index b3d52fe..e29f115 100644 --- a/webcc/http_request.h +++ b/webcc/http_request.h @@ -43,11 +43,11 @@ class HttpRequest : public HttpMessage { // Compose start line, set Host header, etc. void Prepare() override; - static HttpRequestPtr Make(const std::string& method, - const std::string& url, - const std::string& host, - const std::string& port = "", - bool prepare = true); + static HttpRequestPtr New(const std::string& method, + const std::string& url, + const std::string& host, + const std::string& port = "", + bool prepare = true); private: friend class HttpRequestParser; diff --git a/webcc/http_ssl_async_client.h b/webcc/http_ssl_async_client.h index c35c9c7..1ded014 100644 --- a/webcc/http_ssl_async_client.h +++ b/webcc/http_ssl_async_client.h @@ -7,24 +7,37 @@ namespace webcc { +class HttpSslAsyncClient; +typedef std::shared_ptr HttpSslAsyncClientPtr; + // HTTP SSL (a.k.a., HTTPS) asynchronous client. class HttpSslAsyncClient : public HttpAsyncClientBase { public: - // SSL verification (|ssl_verify|) needs CA certificates to be found - // in the default verify paths of OpenSSL. On Windows, it means you need to - // set environment variable SSL_CERT_FILE properly. - explicit HttpSslAsyncClient(boost::asio::io_context& io_context, - std::size_t buffer_size = 0, - bool ssl_verify = true); - ~HttpSslAsyncClient() = default; + // Forbid to create HttpSslAsyncClient in stack since it's derived from + // std::shared_from_this. + static HttpSslAsyncClientPtr New(boost::asio::io_context& io_context, + std::size_t buffer_size = 0, + bool ssl_verify = true) { + return HttpSslAsyncClientPtr{ + new HttpSslAsyncClient(io_context, buffer_size, ssl_verify) + }; + } + // See https://stackoverflow.com/q/657155/6825348 std::shared_ptr shared_from_this() { return shared_from_base(); } private: + // SSL verification (|ssl_verify|) needs CA certificates to be found + // in the default verify paths of OpenSSL. On Windows, it means you need to + // set environment variable SSL_CERT_FILE properly. + explicit HttpSslAsyncClient(boost::asio::io_context& io_context, + std::size_t buffer_size = 0, + bool ssl_verify = true); + void Resolve() final; // Override to do handshake after connected. @@ -51,8 +64,6 @@ class HttpSslAsyncClient : public HttpAsyncClientBase { bool ssl_verify_; }; -typedef std::shared_ptr HttpSslAsyncClientPtr; - } // namespace webcc #endif // WEBCC_HTTP_SSL_ASYNC_CLIENT_H_ diff --git a/webcc/rest_async_client.cc b/webcc/rest_async_client.cc index 0c99d6f..302e78e 100644 --- a/webcc/rest_async_client.cc +++ b/webcc/rest_async_client.cc @@ -26,9 +26,7 @@ void RestAsyncClient::Request(const std::string& method, http_request->Prepare(); - HttpAsyncClientPtr http_async_client{ - new HttpAsyncClient(io_context_, buffer_size_) - }; + auto http_async_client = HttpAsyncClient::New(io_context_, buffer_size_); if (timeout_seconds_ > 0) { http_async_client->SetTimeout(timeout_seconds_); diff --git a/webcc/soap_async_client.cc b/webcc/soap_async_client.cc index 34b87e4..331ba72 100644 --- a/webcc/soap_async_client.cc +++ b/webcc/soap_async_client.cc @@ -65,9 +65,7 @@ void SoapAsyncClient::Request(const std::string& operation, http_request->SetHeader(kSoapAction, operation); http_request->Prepare(); - HttpAsyncClientPtr http_async_client{ - new HttpAsyncClient(io_context_, buffer_size_) - }; + auto http_async_client = HttpAsyncClient::New(io_context_, buffer_size_); if (timeout_seconds_ > 0) { http_async_client->SetTimeout(timeout_seconds_);