Add automation test for http client based on httpbin.org
This commit is contained in:
@@ -21,7 +21,7 @@ bool kSslVerify = true;
|
|||||||
const std::string kUrlRoot = "https://api.github.com";
|
const std::string kUrlRoot = "https://api.github.com";
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// JSON helper functions (based on cppjson).
|
// JSON helper functions (based on jsoncpp).
|
||||||
|
|
||||||
// Parse a string to JSON object.
|
// Parse a string to JSON object.
|
||||||
Json::Value StringToJson(const std::string& str) {
|
Json::Value StringToJson(const std::string& str) {
|
||||||
|
|||||||
@@ -25,34 +25,6 @@ void ExampleBasic() {
|
|||||||
std::cout << r->content() << std::endl;
|
std::cout << r->content() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use predefined shortcuts.
|
|
||||||
void ExampleShortcut() {
|
|
||||||
webcc::HttpClientSession session;
|
|
||||||
|
|
||||||
auto r = session.Get("http://httpbin.org/get",
|
|
||||||
{"key1", "value1", "key2", "value2"},
|
|
||||||
{"Accept", "application/json"});
|
|
||||||
|
|
||||||
std::cout << r->content() << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if WEBCC_ENABLE_SSL
|
|
||||||
|
|
||||||
// HTTPS is auto-detected from the URL scheme.
|
|
||||||
void ExampleHttps() {
|
|
||||||
webcc::HttpClientSession session;
|
|
||||||
session.set_ssl_verify(kSslVerify);
|
|
||||||
|
|
||||||
auto r = session.Request(webcc::HttpRequestBuilder{}.Get().
|
|
||||||
Url("https://httpbin.org/get").
|
|
||||||
Query("key1", "value1").
|
|
||||||
Header("Accept", "application/json")());
|
|
||||||
|
|
||||||
std::cout << r->content() << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // WEBCC_ENABLE_SSL
|
|
||||||
|
|
||||||
// Example for testing Keep-Alive connection.
|
// Example for testing Keep-Alive connection.
|
||||||
//
|
//
|
||||||
// Boost.org doesn't support persistent connection so always includes
|
// Boost.org doesn't support persistent connection so always includes
|
||||||
@@ -79,33 +51,6 @@ void ExampleKeepAlive(const std::string& url) {
|
|||||||
session.Get(url);
|
session.Get(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExampleCompression() {
|
|
||||||
webcc::HttpClientSession session;
|
|
||||||
|
|
||||||
auto r = session.Get("http://httpbin.org/gzip");
|
|
||||||
|
|
||||||
std::cout << r->content() << std::endl;
|
|
||||||
|
|
||||||
r = session.Get("http://httpbin.org/deflate");
|
|
||||||
|
|
||||||
std::cout << r->content() << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get an image from HttpBin.org and save to the given file path.
|
|
||||||
// E.g., ExampleImage("E:\\example.jpg")
|
|
||||||
void ExampleImage(const std::string& path) {
|
|
||||||
webcc::HttpClientSession session;
|
|
||||||
|
|
||||||
auto r = session.Get("http://httpbin.org/image/jpeg");
|
|
||||||
|
|
||||||
// Or
|
|
||||||
// auto r = session.Get("http://httpbin.org/image", {},
|
|
||||||
// {"Accept", "image/jpeg"});
|
|
||||||
|
|
||||||
std::ofstream ofs(path, std::ios::binary);
|
|
||||||
ofs << r->content();
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
WEBCC_LOG_INIT("", webcc::LOG_CONSOLE);
|
WEBCC_LOG_INIT("", webcc::LOG_CONSOLE);
|
||||||
|
|
||||||
|
|||||||
+12
-6
@@ -1,19 +1,25 @@
|
|||||||
# Tests
|
# Tests
|
||||||
|
|
||||||
# Common libraries to link.
|
# Common libraries to link.
|
||||||
set(TEST_COMMON_LIBS webcc ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES}
|
set(TEST_LIBS webcc ${Boost_LIBRARIES} "${CMAKE_THREAD_LIBS_INIT}")
|
||||||
"${CMAKE_THREAD_LIBS_INIT}")
|
|
||||||
|
if(WEBCC_ENABLE_SSL)
|
||||||
|
set(TEST_LIBS ${TEST_LIBS} ${OPENSSL_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(TEST_COMMON_LIBS ${TEST_COMMON_LIBS} zlibstatic crypt32)
|
set(TEST_LIBS ${TEST_LIBS} zlibstatic crypt32)
|
||||||
else()
|
else()
|
||||||
set(TEST_COMMON_LIBS ${TEST_COMMON_LIBS} ${ZLIB_LIBRARIES})
|
set(TEST_LIBS ${TEST_LIBS} ${ZLIB_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
# Add `-ldl` for Linux to avoid "undefined reference to `dlopen'".
|
# Add `-ldl` for Linux to avoid "undefined reference to `dlopen'".
|
||||||
set(TEST_COMMON_LIBS ${TEST_COMMON_LIBS} ${CMAKE_DL_LIBS})
|
set(TEST_LIBS ${TEST_LIBS} ${CMAKE_DL_LIBS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_executable(test_logger test_logger.cc)
|
add_executable(test_logger test_logger.cc)
|
||||||
target_link_libraries(test_logger ${TEST_COMMON_LIBS})
|
target_link_libraries(test_logger ${TEST_LIBS})
|
||||||
|
|
||||||
|
add_executable(test_http_client test_http_client.cc)
|
||||||
|
target_link_libraries(test_http_client gtest jsoncpp ${TEST_LIBS})
|
||||||
|
|||||||
@@ -0,0 +1,230 @@
|
|||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
#include "boost/algorithm/string.hpp"
|
||||||
|
#include "json/json.h"
|
||||||
|
|
||||||
|
#include "webcc/http_client_session.h"
|
||||||
|
#include "webcc/logger.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if (defined(WIN32) || defined(_WIN64))
|
||||||
|
// You need to set environment variable SSL_CERT_FILE properly to enable
|
||||||
|
// SSL verification.
|
||||||
|
bool kSslVerify = false;
|
||||||
|
#else
|
||||||
|
bool kSslVerify = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// JSON helper functions (based on jsoncpp).
|
||||||
|
|
||||||
|
// Parse a string to JSON object.
|
||||||
|
Json::Value StringToJson(const std::string& str) {
|
||||||
|
Json::Value json;
|
||||||
|
|
||||||
|
Json::CharReaderBuilder builder;
|
||||||
|
std::stringstream stream(str);
|
||||||
|
std::string errors;
|
||||||
|
if (!Json::parseFromStream(builder, stream, &json, &errors)) {
|
||||||
|
std::cerr << errors << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
|
||||||
|
static void AssertGet(webcc::HttpResponsePtr r) {
|
||||||
|
Json::Value json = StringToJson(r->content());
|
||||||
|
|
||||||
|
Json::Value args = json["args"];
|
||||||
|
|
||||||
|
EXPECT_EQ(2, args.size());
|
||||||
|
EXPECT_EQ("value1", args["key1"].asString());
|
||||||
|
EXPECT_EQ("value2", args["key2"].asString());
|
||||||
|
|
||||||
|
Json::Value headers = json["headers"];
|
||||||
|
|
||||||
|
EXPECT_EQ("application/json", headers["Accept"].asString());
|
||||||
|
EXPECT_EQ("gzip, deflate", headers["Accept-Encoding"].asString());
|
||||||
|
EXPECT_EQ("httpbin.org", headers["Host"].asString());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TestHttpClient, Get_RequestFunc) {
|
||||||
|
webcc::HttpClientSession session;
|
||||||
|
|
||||||
|
try {
|
||||||
|
auto r = session.Request(webcc::HttpRequestBuilder{}.Get().
|
||||||
|
Url("http://httpbin.org/get").
|
||||||
|
Query("key1", "value1").
|
||||||
|
Query("key2", "value2").
|
||||||
|
Header("Accept", "application/json")
|
||||||
|
());
|
||||||
|
|
||||||
|
AssertGet(r);
|
||||||
|
|
||||||
|
} catch (const webcc::Exception& e) {
|
||||||
|
std::cerr << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TestHttpClient, Get_Shortcut) {
|
||||||
|
webcc::HttpClientSession session;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Use predefined shortcuts.
|
||||||
|
|
||||||
|
auto r = session.Get("http://httpbin.org/get",
|
||||||
|
{ "key1", "value1", "key2", "value2" },
|
||||||
|
{ "Accept", "application/json" });
|
||||||
|
|
||||||
|
AssertGet(r);
|
||||||
|
|
||||||
|
} catch (const webcc::Exception& e) {
|
||||||
|
std::cerr << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if WEBCC_ENABLE_SSL
|
||||||
|
TEST(TestHttpClient, Get_SSL) {
|
||||||
|
webcc::HttpClientSession session;
|
||||||
|
|
||||||
|
session.set_ssl_verify(kSslVerify);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// HTTPS is auto-detected from the URL scheme.
|
||||||
|
|
||||||
|
auto r = session.Request(webcc::HttpRequestBuilder{}.Get().
|
||||||
|
Url("https://httpbin.org/get").
|
||||||
|
Query("key1", "value1").
|
||||||
|
Query("key2", "value2").
|
||||||
|
Header("Accept", "application/json")
|
||||||
|
());
|
||||||
|
|
||||||
|
AssertGet(r);
|
||||||
|
|
||||||
|
} catch (const webcc::Exception& e) {
|
||||||
|
std::cerr << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // WEBCC_ENABLE_SSL
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Test Gzip compressed response.
|
||||||
|
TEST(TestHttpClient, Compression_Gzip) {
|
||||||
|
webcc::HttpClientSession session;
|
||||||
|
|
||||||
|
try {
|
||||||
|
auto r = session.Get("http://httpbin.org/gzip");
|
||||||
|
|
||||||
|
Json::Value json = StringToJson(r->content());
|
||||||
|
|
||||||
|
EXPECT_EQ(true, json["gzipped"].asBool());
|
||||||
|
|
||||||
|
} catch (const webcc::Exception& e) {
|
||||||
|
std::cerr << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test Deflate compressed response.
|
||||||
|
TEST(TestHttpClient, Compression_Deflate) {
|
||||||
|
webcc::HttpClientSession session;
|
||||||
|
|
||||||
|
try {
|
||||||
|
auto r = session.Get("http://httpbin.org/deflate");
|
||||||
|
|
||||||
|
std::cout << r->content() << std::endl;
|
||||||
|
|
||||||
|
Json::Value json = StringToJson(r->content());
|
||||||
|
|
||||||
|
EXPECT_EQ(true, json["deflated"].asBool());
|
||||||
|
|
||||||
|
} catch (const webcc::Exception& e) {
|
||||||
|
std::cerr << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Test persistent connections.
|
||||||
|
TEST(TestHttpClient, KeepAlive) {
|
||||||
|
webcc::HttpClientSession session;
|
||||||
|
|
||||||
|
std::string url = "http://httpbin.org/get";
|
||||||
|
try {
|
||||||
|
|
||||||
|
// Keep-Alive by default.
|
||||||
|
auto r = session.Get(url);
|
||||||
|
|
||||||
|
using boost::iequals;
|
||||||
|
|
||||||
|
EXPECT_TRUE(iequals(r->GetHeader("Connection"), "Keep-alive"));
|
||||||
|
|
||||||
|
// Close by setting Connection header.
|
||||||
|
r = session.Get(url, {}, { "Connection", "Close" });
|
||||||
|
|
||||||
|
EXPECT_TRUE(iequals(r->GetHeader("Connection"), "Close"));
|
||||||
|
|
||||||
|
// Close by using request builder.
|
||||||
|
r = session.Request(webcc::HttpRequestBuilder{}.Get().
|
||||||
|
KeepAlive(false)
|
||||||
|
());
|
||||||
|
|
||||||
|
EXPECT_TRUE(iequals(r->GetHeader("Connection"), "Close"));
|
||||||
|
|
||||||
|
// Keep-Alive explicitly by using request builder.
|
||||||
|
r = session.Request(webcc::HttpRequestBuilder{}.Get().
|
||||||
|
KeepAlive(true)
|
||||||
|
());
|
||||||
|
|
||||||
|
EXPECT_TRUE(iequals(r->GetHeader("Connection"), "Keep-alive"));
|
||||||
|
|
||||||
|
} catch (const webcc::Exception& e) {
|
||||||
|
std::cerr << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Get a JPEG image.
|
||||||
|
TEST(TestHttpClient, GetImageJpeg) {
|
||||||
|
webcc::HttpClientSession session;
|
||||||
|
|
||||||
|
std::string url = "http://httpbin.org/get";
|
||||||
|
try {
|
||||||
|
|
||||||
|
auto r = session.Get("http://httpbin.org/image/jpeg");
|
||||||
|
|
||||||
|
// Or
|
||||||
|
// auto r = session.Get("http://httpbin.org/image", {},
|
||||||
|
// {"Accept", "image/jpeg"});
|
||||||
|
|
||||||
|
//std::ofstream ofs(path, std::ios::binary);
|
||||||
|
//ofs << r->content();
|
||||||
|
|
||||||
|
// TODO: Verify the response is a valid JPEG image.
|
||||||
|
|
||||||
|
} catch (const webcc::Exception& e) {
|
||||||
|
std::cerr << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// TODO: Post requests
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
// Set webcc::LOG_CONSOLE to enable logging.
|
||||||
|
WEBCC_LOG_INIT("", 0);
|
||||||
|
|
||||||
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
|
return RUN_ALL_TESTS();
|
||||||
|
}
|
||||||
@@ -85,37 +85,4 @@ void HttpRequestBuilder::SetContent(HttpRequestPtr request,
|
|||||||
request->SetContent(std::move(data), true);
|
request->SetContent(std::move(data), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void HttpRequestBuilder::CreateFormData(std::string* data,
|
|
||||||
// const std::string& boundary) {
|
|
||||||
// for (auto& pair : files_) {
|
|
||||||
// data->append("--" + boundary + kCRLF);
|
|
||||||
//
|
|
||||||
// // Content-Disposition header
|
|
||||||
// data->append("Content-Disposition: form-data");
|
|
||||||
// if (!pair.first.empty()) {
|
|
||||||
// data->append("; name=\"" + pair.first + "\"");
|
|
||||||
// }
|
|
||||||
// if (!pair.second.file_name().empty()) {
|
|
||||||
// data->append("; filename=\"" + pair.second.file_name() + "\"");
|
|
||||||
// }
|
|
||||||
// data->append(kCRLF);
|
|
||||||
//
|
|
||||||
// // Content-Type header
|
|
||||||
// if (!pair.second.mime_type().empty()) {
|
|
||||||
// data->append("Content-Type: " + pair.second.mime_type());
|
|
||||||
// data->append(kCRLF);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// data->append(kCRLF);
|
|
||||||
//
|
|
||||||
// // Payload
|
|
||||||
// data->append(pair.second.data());
|
|
||||||
//
|
|
||||||
// data->append(kCRLF);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// data->append("--" + boundary + "--");
|
|
||||||
// data->append(kCRLF);
|
|
||||||
//}
|
|
||||||
|
|
||||||
} // namespace webcc
|
} // namespace webcc
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpRequestBuilder& KeepAlive(bool keep_alive) {
|
HttpRequestBuilder& KeepAlive(bool keep_alive = true) {
|
||||||
keep_alive_ = keep_alive;
|
keep_alive_ = keep_alive;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -107,8 +107,6 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void SetContent(HttpRequestPtr request, std::string&& data);
|
void SetContent(HttpRequestPtr request, std::string&& data);
|
||||||
|
|
||||||
//void CreateFormData(std::string* data, const std::string& boundary);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string method_;
|
std::string method_;
|
||||||
|
|||||||
Reference in New Issue
Block a user