From 6c760ee348dfa61560660c214799b793ce17513b Mon Sep 17 00:00:00 2001 From: Mattes D Date: Mon, 22 Aug 2016 19:49:33 +0200 Subject: UrlClient: Basic HTTP implementation. --- tests/HTTP/CMakeLists.txt | 26 ++++++- tests/HTTP/UrlClientTest.cpp | 162 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 185 insertions(+), 3 deletions(-) create mode 100644 tests/HTTP/UrlClientTest.cpp (limited to 'tests/HTTP') diff --git a/tests/HTTP/CMakeLists.txt b/tests/HTTP/CMakeLists.txt index ed5c9daaf..1e2eb356a 100644 --- a/tests/HTTP/CMakeLists.txt +++ b/tests/HTTP/CMakeLists.txt @@ -11,6 +11,8 @@ set (HTTP_SRCS ${CMAKE_SOURCE_DIR}/src/HTTP/HTTPMessage.cpp ${CMAKE_SOURCE_DIR}/src/HTTP/HTTPMessageParser.cpp ${CMAKE_SOURCE_DIR}/src/HTTP/TransferEncodingParser.cpp + ${CMAKE_SOURCE_DIR}/src/HTTP/UrlClient.cpp + ${CMAKE_SOURCE_DIR}/src/HTTP/UrlParser.cpp ${CMAKE_SOURCE_DIR}/src/StringUtils.cpp ) @@ -19,13 +21,20 @@ set (HTTP_HDRS ${CMAKE_SOURCE_DIR}/src/HTTP/HTTPMessage.h ${CMAKE_SOURCE_DIR}/src/HTTP/HTTPMessageParser.h ${CMAKE_SOURCE_DIR}/src/HTTP/TransferEncodingParser.h + ${CMAKE_SOURCE_DIR}/src/HTTP/UrlClient.h + ${CMAKE_SOURCE_DIR}/src/HTTP/UrlParser.h ${CMAKE_SOURCE_DIR}/src/StringUtils.h ) +set (SHARED_SRCS + ${CMAKE_SOURCE_DIR}/src/OSSupport/Event.cpp +) + add_library(HTTP ${HTTP_SRCS} ${HTTP_HDRS} ) +target_link_libraries(HTTP Network OSSupport) if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") add_flags_cxx("-Wno-error=conversion -Wno-error=old-style-cast") @@ -35,11 +44,21 @@ endif() -# Define individual tests: +# Define individual test executables: # HTTPMessageParser_file: Feed file contents into a cHTTPResponseParser and print the callbacks as they're called: add_executable(HTTPMessageParser_file-exe HTTPMessageParser_file.cpp) -target_link_libraries(HTTPMessageParser_file-exe HTTP) +target_link_libraries(HTTPMessageParser_file-exe HTTP Network OSSupport) + +# UrlClientTest: Tests the UrlClient class by requesting a few things off the internet: +add_executable(UrlClientTest-exe UrlClientTest.cpp) +target_link_libraries(UrlClientTest-exe HTTP) + + + + + +# Define individual tests: # Test parsing the response file in 2-byte chunks (should go from response line parsing through headers parsing to body parsing, each within a different step): add_test(NAME HTTPMessageParser_file-test1-2 COMMAND HTTPMessageParser_file-exe ${CMAKE_CURRENT_SOURCE_DIR}/HTTPResponse1.data 2) @@ -63,7 +82,8 @@ add_test(NAME HTTPMessageParser_file-test4-512 COMMAND HTTPMessageParser_file-ex # Put all the tests into a solution folder (MSVC): set_target_properties( HTTPMessageParser_file-exe - PROPERTIES FOLDER Tests + UrlClientTest-exe + PROPERTIES FOLDER Tests/HTTP ) set_target_properties( HTTP diff --git a/tests/HTTP/UrlClientTest.cpp b/tests/HTTP/UrlClientTest.cpp new file mode 100644 index 000000000..5f70855fb --- /dev/null +++ b/tests/HTTP/UrlClientTest.cpp @@ -0,0 +1,162 @@ + +#include "Globals.h" +#include "HTTP/UrlClient.h" +#include "OSSupport/NetworkSingleton.h" + + + + + +class cCallbacks: + public cUrlClient::cCallbacks +{ +public: + cCallbacks(cEvent & a_Event): + m_Event(a_Event) + { + } + + virtual void OnConnected(cTCPLink & a_Link) override + { + LOG("Link connected to %s:%u", a_Link.GetRemoteIP().c_str(), a_Link.GetRemotePort()); + } + + virtual bool OnCertificateReceived() override + { + LOG("Server certificate received"); + return true; + } + + virtual void OnRequestSent() override + { + LOG("Request has been sent"); + } + + virtual void OnHeader(const AString & a_Key, const AString & a_Value) override + { + LOG("HTTP Header: \"%s\" -> \"%s\"", a_Key.c_str(), a_Value.c_str()); + } + + virtual void OnHeadersFinished() override + { + LOG("HTTP headers finished."); + } + + virtual void OnBodyData(const void * a_Data, size_t a_Size) override + { + AString body(reinterpret_cast(a_Data), a_Size); + LOG("Body part:\n%s", body.c_str()); + } + + /** Called after the response body has been fully reported by OnBody() calls. + There will be no more OnBody() calls. */ + virtual void OnBodyFinished() override + { + LOG("Body finished."); + m_Event.Set(); + } + + virtual void OnRedirecting(const AString & a_RedirectUrl) override + { + LOG("Redirecting to \"%s\".", a_RedirectUrl.c_str()); + } + + virtual void OnError(const AString & a_ErrorMsg) override + { + LOG("Error: %s", a_ErrorMsg.c_str()); + m_Event.Set(); + } + +protected: + cEvent & m_Event; +}; + + + + + +int TestRequest1() +{ + LOG("Running test 1"); + cEvent evtFinished; + cCallbacks callbacks(evtFinished); + AStringMap options; + options["MaxRedirects"] = "0"; + auto res = cUrlClient::Get("http://github.com", callbacks, AStringMap(), AString(), options); + if (res.first) + { + evtFinished.Wait(); + } + else + { + LOG("Immediate error: %s", res.second.c_str()); + return 1; + } + return 0; +} + + + + + +int TestRequest2() +{ + LOG("Running test 2"); + cEvent evtFinished; + cCallbacks callbacks(evtFinished); + auto res = cUrlClient::Get("http://github.com", callbacks); + if (res.first) + { + evtFinished.Wait(); + } + else + { + LOG("Immediate error: %s", res.second.c_str()); + return 1; + } + return 0; +} + + + + + +int TestRequests() +{ + auto res = TestRequest1(); + if (res != 0) + { + return res; + } + res = TestRequest2(); + if (res != 0) + { + return res; + } + return 0; +} + + + + + +int main() +{ + LOGD("Test started"); + + LOGD("Initializing cNetwork..."); + cNetworkSingleton::Get().Initialise(); + + LOGD("Testing..."); + auto res = TestRequests(); + + LOGD("Terminating cNetwork..."); + cNetworkSingleton::Get().Terminate(); + LOGD("cUrlClient test finished"); + + return res; +} + + + + -- cgit v1.2.3 From 641cb063bc71acc7f29d25b12c8713a8beb2018c Mon Sep 17 00:00:00 2001 From: Mattes D Date: Mon, 22 Aug 2016 19:53:34 +0200 Subject: cTCPLink supports TLS out of the box. --- tests/HTTP/CMakeLists.txt | 4 ++ tests/HTTP/UrlClientTest.cpp | 105 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 96 insertions(+), 13 deletions(-) (limited to 'tests/HTTP') diff --git a/tests/HTTP/CMakeLists.txt b/tests/HTTP/CMakeLists.txt index 1e2eb356a..cb2329adc 100644 --- a/tests/HTTP/CMakeLists.txt +++ b/tests/HTTP/CMakeLists.txt @@ -2,6 +2,7 @@ enable_testing() include_directories(${CMAKE_SOURCE_DIR}/src/) include_directories(${CMAKE_SOURCE_DIR}/lib/libevent/include) +include_directories(${CMAKE_SOURCE_DIR}/lib/polarssl/include) add_definitions(-DTEST_GLOBALS=1) @@ -75,6 +76,9 @@ add_test(NAME HTTPMessageParser_file-test3-2 COMMAND HTTPMessageParser_file-exe # Test parsing the request file in 512-byte chunks (should process everything in a single call): add_test(NAME HTTPMessageParser_file-test4-512 COMMAND HTTPMessageParser_file-exe ${CMAKE_CURRENT_SOURCE_DIR}/HTTPRequest1.data 512) +# Test the URLClient +add_test(NAME UrlClient-test COMMAND UrlClientTest-exe) + diff --git a/tests/HTTP/UrlClientTest.cpp b/tests/HTTP/UrlClientTest.cpp index 5f70855fb..97cdc6d6e 100644 --- a/tests/HTTP/UrlClientTest.cpp +++ b/tests/HTTP/UrlClientTest.cpp @@ -7,6 +7,7 @@ +/** Simple callbacks that dump the events to the console and signalize a cEvent when the request is finished. */ class cCallbacks: public cUrlClient::cCallbacks { @@ -14,53 +15,79 @@ public: cCallbacks(cEvent & a_Event): m_Event(a_Event) { + LOGD("Created a cCallbacks instance at %p", reinterpret_cast(this)); } + + ~cCallbacks() + { + LOGD("Deleting the cCallbacks instance at %p", reinterpret_cast(this)); + } + + virtual void OnConnected(cTCPLink & a_Link) override { LOG("Link connected to %s:%u", a_Link.GetRemoteIP().c_str(), a_Link.GetRemotePort()); } + virtual bool OnCertificateReceived() override { LOG("Server certificate received"); return true; } + + virtual void OnTlsHandshakeCompleted() override + { + LOG("TLS handshake has completed."); + } + + virtual void OnRequestSent() override { LOG("Request has been sent"); } + virtual void OnHeader(const AString & a_Key, const AString & a_Value) override { LOG("HTTP Header: \"%s\" -> \"%s\"", a_Key.c_str(), a_Value.c_str()); } + virtual void OnHeadersFinished() override { LOG("HTTP headers finished."); } + virtual void OnBodyData(const void * a_Data, size_t a_Size) override { - AString body(reinterpret_cast(a_Data), a_Size); - LOG("Body part:\n%s", body.c_str()); + #if 0 + // Output the whole received data blob: + AString body(reinterpret_cast(a_Data), a_Size); + LOG("Body part:\n%s", body.c_str()); + #else + // Output only the data size, to keep the log short: + LOG("Body part: %u bytes", static_cast(a_Size)); + #endif } - /** Called after the response body has been fully reported by OnBody() calls. - There will be no more OnBody() calls. */ + virtual void OnBodyFinished() override { LOG("Body finished."); m_Event.Set(); } + virtual void OnRedirecting(const AString & a_RedirectUrl) override { LOG("Redirecting to \"%s\".", a_RedirectUrl.c_str()); } + virtual void OnError(const AString & a_ErrorMsg) override { LOG("Error: %s", a_ErrorMsg.c_str()); @@ -75,7 +102,7 @@ protected: -int TestRequest1() +static int TestRequest1() { LOG("Running test 1"); cEvent evtFinished; @@ -99,7 +126,7 @@ int TestRequest1() -int TestRequest2() +static int TestRequest2() { LOG("Running test 2"); cEvent evtFinished; @@ -121,17 +148,69 @@ int TestRequest2() -int TestRequests() +static int TestRequest3() +{ + LOG("Running test 3"); + cEvent evtFinished; + cCallbacks callbacks(evtFinished); + AStringMap options; + options["MaxRedirects"] = "0"; + auto res = cUrlClient::Get("https://github.com", callbacks, AStringMap(), AString(), options); + if (res.first) + { + evtFinished.Wait(); + } + else + { + LOG("Immediate error: %s", res.second.c_str()); + return 1; + } + return 0; +} + + + + + +static int TestRequest4() { - auto res = TestRequest1(); - if (res != 0) + LOG("Running test 4"); + cEvent evtFinished; + cCallbacks callbacks(evtFinished); + auto res = cUrlClient::Get("https://github.com", callbacks); + if (res.first) { - return res; + evtFinished.Wait(); } - res = TestRequest2(); - if (res != 0) + else { - return res; + LOG("Immediate error: %s", res.second.c_str()); + return 1; + } + return 0; +} + + + + + +static int TestRequests() +{ + std::function tests[] = + { + &TestRequest1, + &TestRequest2, + &TestRequest3, + &TestRequest4, + }; + for (const auto & test: tests) + { + LOG("%s", AString(60, '-').c_str()); + auto res = test(); + if (res != 0) + { + return res; + } } return 0; } -- cgit v1.2.3 From 74918ce805de260371ad1be0604ee7369f5f809b Mon Sep 17 00:00:00 2001 From: Mattes D Date: Tue, 16 Aug 2016 11:55:49 +0200 Subject: cUrlClient: Refactored callbacks to use UniquePtr. --- tests/HTTP/UrlClientTest.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'tests/HTTP') diff --git a/tests/HTTP/UrlClientTest.cpp b/tests/HTTP/UrlClientTest.cpp index 97cdc6d6e..d8412fddf 100644 --- a/tests/HTTP/UrlClientTest.cpp +++ b/tests/HTTP/UrlClientTest.cpp @@ -106,10 +106,10 @@ static int TestRequest1() { LOG("Running test 1"); cEvent evtFinished; - cCallbacks callbacks(evtFinished); + auto callbacks = cpp14::make_unique(evtFinished); AStringMap options; options["MaxRedirects"] = "0"; - auto res = cUrlClient::Get("http://github.com", callbacks, AStringMap(), AString(), options); + auto res = cUrlClient::Get("http://github.com", std::move(callbacks), AStringMap(), AString(), options); if (res.first) { evtFinished.Wait(); @@ -130,8 +130,8 @@ static int TestRequest2() { LOG("Running test 2"); cEvent evtFinished; - cCallbacks callbacks(evtFinished); - auto res = cUrlClient::Get("http://github.com", callbacks); + auto callbacks = cpp14::make_unique(evtFinished); + auto res = cUrlClient::Get("http://github.com", std::move(callbacks)); if (res.first) { evtFinished.Wait(); @@ -152,10 +152,10 @@ static int TestRequest3() { LOG("Running test 3"); cEvent evtFinished; - cCallbacks callbacks(evtFinished); + auto callbacks = cpp14::make_unique(evtFinished); AStringMap options; options["MaxRedirects"] = "0"; - auto res = cUrlClient::Get("https://github.com", callbacks, AStringMap(), AString(), options); + auto res = cUrlClient::Get("https://github.com", std::move(callbacks), AStringMap(), AString(), options); if (res.first) { evtFinished.Wait(); @@ -176,8 +176,8 @@ static int TestRequest4() { LOG("Running test 4"); cEvent evtFinished; - cCallbacks callbacks(evtFinished); - auto res = cUrlClient::Get("https://github.com", callbacks); + auto callbacks = cpp14::make_unique(evtFinished); + auto res = cUrlClient::Get("https://github.com", std::move(callbacks)); if (res.first) { evtFinished.Wait(); -- cgit v1.2.3