Handle both HTTP & HTTPS in HttpClientSession; remove macro WEBCC_ENABLE_SSL.

master
Chunting Gu 6 years ago
parent 9b8304f06c
commit ffa0794926

@ -10,7 +10,6 @@ project(webcc)
option(WEBCC_ENABLE_REST "Enable REST support?" ON)
option(WEBCC_ENABLE_SOAP "Enable SOAP support (need pugixml)?" ON)
option(WEBCC_ENABLE_SSL "Enable SSL/HTTPS support (need OpenSSL)?" OFF)
option(WEBCC_ENABLE_UNITTEST "Build unit test?" ON)
option(WEBCC_ENABLE_EXAMPLES "Build examples?" ON)
@ -85,14 +84,12 @@ if(Boost_FOUND)
message(STATUS ${Boost_LIBRARIES})
endif()
if(WEBCC_ENABLE_SSL)
set(OPENSSL_USE_STATIC_LIBS ON)
set(OPENSSL_MSVC_STATIC_RT ON)
find_package(OpenSSL)
if(OPENSSL_FOUND)
include_directories(${OPENSSL_INCLUDE_DIR})
message(STATUS "OpenSSL libs: " ${OPENSSL_LIBRARIES})
endif()
set(OPENSSL_USE_STATIC_LIBS ON)
set(OPENSSL_MSVC_STATIC_RT ON)
find_package(OpenSSL)
if(OPENSSL_FOUND)
include_directories(${OPENSSL_INCLUDE_DIR})
message(STATUS "OpenSSL libs: " ${OPENSSL_LIBRARIES})
endif()
include_directories(
@ -121,6 +118,17 @@ endif()
add_subdirectory(webcc)
if(WEBCC_ENABLE_EXAMPLES)
# Common libraries to link for examples.
set(EXAMPLE_COMMON_LIBS webcc ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES}
"${CMAKE_THREAD_LIBS_INIT}")
if(WIN32)
set(EXAMPLE_COMMON_LIBS ${EXAMPLE_COMMON_LIBS} crypt32)
endif()
if(UNIX)
# Add `-ldl` for Linux to avoid "undefined reference to `dlopen'".
set(EXAMPLE_COMMON_LIBS ${EXAMPLE_COMMON_LIBS} ${CMAKE_DL_LIBS})
endif()
add_subdirectory(example/http_client)
# add_subdirectory(example/http_async_client)
@ -143,13 +151,11 @@ if(WEBCC_ENABLE_EXAMPLES)
add_subdirectory(example/soap_book_client)
endif()
if(WEBCC_ENABLE_SSL)
add_subdirectory(example/http_ssl_client)
# add_subdirectory(example/http_ssl_async_client)
add_subdirectory(example/http_ssl_client)
# add_subdirectory(example/http_ssl_async_client)
if(WEBCC_ENABLE_REST)
# add_subdirectory(example/github_rest_client)
endif()
if(WEBCC_ENABLE_REST)
# add_subdirectory(example/github_rest_client)
endif()
endif()

@ -1,15 +1,2 @@
set(LIBS webcc jsoncpp ${Boost_LIBRARIES} "${CMAKE_THREAD_LIBS_INIT}")
set(LIBS ${LIBS} ${OPENSSL_LIBRARIES})
if(WIN32)
set(LIBS ${LIBS} crypt32)
endif()
if(UNIX)
# Add `-ldl` for Linux to avoid "undefined reference to `dlopen'".
set(LIBS ${LIBS} ${CMAKE_DL_LIBS})
endif()
add_executable(github_rest_client main.cc)
target_link_libraries(github_rest_client ${LIBS})
target_link_libraries(github_rest_client ${EXAMPLE_COMMON_LIBS} jsoncpp)

@ -1,4 +1,2 @@
add_executable(http_client main.cc)
target_link_libraries(http_client webcc ${Boost_LIBRARIES})
target_link_libraries(http_client "${CMAKE_THREAD_LIBS_INIT}")
target_link_libraries(http_client ${EXAMPLE_COMMON_LIBS})

@ -1,6 +1,6 @@
#include <iostream>
#include "webcc/http_client_session.h" // TEST
#include "webcc/http_client_session.h"
#include "webcc/logger.h"
int main() {
@ -12,38 +12,49 @@ int main() {
HttpClientSession session;
#if 0
r = session.Request(HttpRequestArgs("GET")
.url("http://httpbin.org/get") // Moved
.parameters({ "key1", "value1", "key2", "value2" }) // Moved
.headers({ "Accept", "application/json" }) // Moved
.buffer_size(1000));
// ---------------------------------------------------------------------------
r = session.Request(HttpRequestArgs{ "GET" }.
url("http://httpbin.org/get"). // moved
parameters({ "key1", "value1", "key2", "value2" }). // moved
headers({ "Accept", "application/json" }). // moved
buffer_size(1000));
std::cout << r->content() << std::endl;
// ---------------------------------------------------------------------------
// If you want to create the args object firstly, there'll be an extra call
// to its move constructor.
// - constructor: HttpRequestArgs("GET")
// - constructor: HttpRequestArgs{ "GET" }
// - move constructor: auto args = ...
auto args = HttpRequestArgs("GET")
.url("http://httpbin.org/get")
.parameters({ "key1", "value1", "key2", "value2" })
.headers({ "Accept", "application/json" })
.buffer_size(1000);
auto args = HttpRequestArgs{"GET"}.
url("http://httpbin.org/get").
parameters({ "key1", "value1", "key2", "value2" }).
headers({ "Accept", "application/json" }).
buffer_size(1000);
r = session.Request(std::move(args));
// ---------------------------------------------------------------------------
// Use pre-defined wrappers.
r = session.Get("http://httpbin.org/get",
{ "key1", "value1", "key2", "value2" },
{ "Accept", "application/json" },
HttpRequestArgs().buffer_size(1000));
#endif
HttpRequestArgs{}.buffer_size(1000));
// ---------------------------------------------------------------------------
// HTTPS is auto-detected from the URL schema.
r = session.Post("http://httpbin.org/post", "{ 'key': 'value' }", true,
r = session.Post("https://httpbin.org/post", "{ 'key': 'value' }", true,
{ "Accept", "application/json" },
HttpRequestArgs().buffer_size(1000));
HttpRequestArgs{}.ssl_verify(false).buffer_size(1000));
std::cout << r->content() << std::endl;
if (r) {
std::cout << r->content() << std::endl;
}
return 0;
}

@ -1,10 +1,2 @@
add_executable(http_ssl_client main.cc)
set(SSL_LIBS ${OPENSSL_LIBRARIES})
if(WIN32)
set(SSL_LIBS ${SSL_LIBS} crypt32)
endif()
target_link_libraries(http_ssl_client webcc ${Boost_LIBRARIES})
target_link_libraries(http_ssl_client "${CMAKE_THREAD_LIBS_INIT}")
target_link_libraries(http_ssl_client ${SSL_LIBS})
target_link_libraries(http_ssl_client ${EXAMPLE_COMMON_LIBS})

@ -0,0 +1,83 @@
#include "gtest/gtest.h"
#include "webcc/url.h"
TEST(Url, Basic) {
webcc::Url url("http://example.com/path", false);
EXPECT_EQ("http", url.scheme());
EXPECT_EQ("example.com", url.host());
EXPECT_EQ("", url.port());
EXPECT_EQ("path", url.path());
EXPECT_EQ("", url.query());
}
TEST(Url, NoPath) {
webcc::Url url("http://example.com", false);
EXPECT_EQ("http", url.scheme());
EXPECT_EQ("example.com", url.host());
EXPECT_EQ("", url.port());
EXPECT_EQ("", url.path());
EXPECT_EQ("", url.query());
}
TEST(Url, NoPath2) {
webcc::Url url("http://example.com/", false);
EXPECT_EQ("http", url.scheme());
EXPECT_EQ("example.com", url.host());
EXPECT_EQ("", url.port());
EXPECT_EQ("", url.path());
EXPECT_EQ("", url.query());
}
TEST(Url, NoPath3) {
webcc::Url url("http://example.com?key=value", false);
EXPECT_EQ("http", url.scheme());
EXPECT_EQ("example.com", url.host());
EXPECT_EQ("", url.port());
EXPECT_EQ("", url.path());
EXPECT_EQ("key=value", url.query());
}
TEST(Url, NoPath4) {
webcc::Url url("http://example.com/?key=value", false);
EXPECT_EQ("http", url.scheme());
EXPECT_EQ("example.com", url.host());
EXPECT_EQ("", url.port());
EXPECT_EQ("", url.path());
EXPECT_EQ("key=value", url.query());
}
TEST(Url, NoScheme) {
webcc::Url url("/path/to", false);
EXPECT_EQ("", url.scheme());
EXPECT_EQ("", url.host());
EXPECT_EQ("", url.port());
EXPECT_EQ("path/to", url.path());
EXPECT_EQ("", url.query());
}
TEST(Url, NoScheme2) {
webcc::Url url("/path/to?key=value", false);
EXPECT_EQ("", url.scheme());
EXPECT_EQ("", url.host());
EXPECT_EQ("", url.port());
EXPECT_EQ("path/to", url.path());
EXPECT_EQ("key=value", url.query());
}
TEST(Url, Full) {
webcc::Url url("https://localhost:3000/path/to?key=value", false);
EXPECT_EQ("https", url.scheme());
EXPECT_EQ("localhost", url.host());
EXPECT_EQ("3000", url.port());
EXPECT_EQ("path/to", url.path());
EXPECT_EQ("key=value", url.query());
}

@ -30,6 +30,7 @@ set(HEADERS
http_response.h
http_response_parser.h
http_server.h
http_ssl_client.h
# http_ssl_async_client.h
queue.h
url.h
@ -53,6 +54,7 @@ set(SOURCES
http_response.cc
http_response_parser.cc
http_server.cc
http_ssl_client.cc
# http_ssl_async_client.cc
logger.cc
url.cc
@ -61,7 +63,7 @@ set(SOURCES
if(WEBCC_ENABLE_REST)
set(REST_HEADERS
# rest_async_client.h
# rest_async_client.h
# rest_client.h
rest_request_handler.h
rest_server.h
@ -80,11 +82,6 @@ if(WEBCC_ENABLE_REST)
set(SOURCES ${SOURCES} ${REST_SOURCES})
endif()
if(WEBCC_ENABLE_SSL)
set(HEADERS ${HEADERS} http_ssl_client.h)
set(SOURCES ${SOURCES} http_ssl_client.cc)
endif()
if(WEBCC_ENABLE_SOAP)
set(SOAP_HEADERS
# soap_async_client.h

@ -1,7 +1,7 @@
#include "webcc/http_client_session.h"
#include "webcc/http_client.h"
#include "webcc/http_request.h"
#include "webcc/http_ssl_client.h"
#include "webcc/url.h"
namespace webcc {
@ -14,7 +14,7 @@ HttpResponsePtr HttpClientSession::Request(HttpRequestArgs&& args) {
assert(args.parameters_.size() % 2 == 0);
assert(args.headers_.size() % 2 == 0);
HttpRequest request(args.method_, args.url_, args.parameters_);
HttpRequest request{ args.method_, args.url_, args.parameters_ };
if (!args.data_.empty()) {
request.SetContent(std::move(args.data_), true);
@ -39,12 +39,26 @@ HttpResponsePtr HttpClientSession::Request(HttpRequestArgs&& args) {
request.Prepare();
HttpClient client;
if (!client.Request(request, args.buffer_size_)) {
// TODO:
std::shared_ptr<HttpClientBase> impl;
if (request.url().scheme() == "http") {
impl.reset(new HttpClient);
} else if (request.url().scheme() == "https") {
impl.reset(new HttpSslClient{args.ssl_verify_});
} else {
return HttpResponsePtr{};
}
return client.response();
if (impl) {
if (!impl->Request(request, args.buffer_size_)) {
return HttpResponsePtr{};
}
return impl->response();
}
return HttpResponsePtr{};
}
HttpResponsePtr HttpClientSession::Get(const std::string& url,

@ -17,7 +17,7 @@ class HttpClientSession;
class HttpRequestArgs {
public:
explicit HttpRequestArgs(const std::string& method = "")
: method_(method), json_(false), buffer_size_(0) {
: method_(method), json_(false), ssl_verify_(true), buffer_size_(0) {
LOG_VERB("HttpRequestArgs()");
}
@ -38,6 +38,7 @@ public:
data_(std::move(rhs.data_)),
json_(rhs.json_),
headers_(std::move(rhs.headers_)),
ssl_verify_(rhs.ssl_verify_),
buffer_size_(rhs.buffer_size_) {
LOG_VERB("HttpRequestArgs(&&)");
}
@ -50,6 +51,7 @@ public:
data_ = std::move(rhs.data_);
json_ = rhs.json_;
headers_ = std::move(rhs.headers_);
ssl_verify_ = rhs.ssl_verify_;
buffer_size_ = buffer_size_;
}
LOG_VERB("HttpRequestArgs& operator=(&&)");
@ -108,6 +110,11 @@ public:
return std::move(*this);
}
HttpRequestArgs&& ssl_verify(bool ssl_verify = true) {
ssl_verify_ = ssl_verify;
return std::move(*this);
}
HttpRequestArgs&& buffer_size(std::size_t buffer_size) {
buffer_size_ = buffer_size;
return std::move(*this);
@ -130,6 +137,10 @@ private:
std::vector<std::string> headers_;
// Verify the certificate of the peer (remote server) or not.
// HTTPS only.
bool ssl_verify_;
// Size of the buffer to read response.
// Leave it to 0 for using default value.
std::size_t buffer_size_;

Loading…
Cancel
Save