From 326a3ea2151397f49269f8cde84df1cd77dc87d3 Mon Sep 17 00:00:00 2001 From: Chunting Gu Date: Tue, 22 Jun 2021 10:16:58 +0800 Subject: [PATCH] check url scheme --- autotest/client_autotest/client_autotest.cc | 30 +++++++++++++++++++++ webcc/client.cc | 25 ++++++++++------- webcc/client_session.cc | 20 ++++++++++++++ webcc/client_session.h | 3 +++ 4 files changed, 69 insertions(+), 9 deletions(-) diff --git a/autotest/client_autotest/client_autotest.cc b/autotest/client_autotest/client_autotest.cc index 4c58dd4..ac62415 100644 --- a/autotest/client_autotest/client_autotest.cc +++ b/autotest/client_autotest/client_autotest.cc @@ -441,3 +441,33 @@ TEST(ClientTest, KeepAlive) { std::cerr << error << std::endl; } } + +// Test that URL scheme is NOT case sensitive. +TEST(ClientTest, UpperCaseUrlScheme) { + webcc::ClientSession session; + + try { + auto r = session.Send(WEBCC_GET("HTTP://httpbin.org/get")()); + + EXPECT_EQ(webcc::Status::kOK, r->status()); + + } catch (const webcc::Error& error) { + std::cerr << error << std::endl; + } +} + +TEST(ClientTest, InvalidUrlScheme) { + webcc::ClientSession session; + + webcc::Error::Code error_code = webcc::Error::kUnknownError; + + try { + // NOTE: "httb" is not a valid/supported scheme. + auto r = session.Send(WEBCC_GET("httb://httpbin.org/get")()); + + } catch (const webcc::Error& error) { + error_code = error.code(); + } + + EXPECT_EQ(webcc::Error::kSyntaxError, error_code); +} diff --git a/webcc/client.cc b/webcc/client.cc index 93ae0a0..db8cf10 100644 --- a/webcc/client.cc +++ b/webcc/client.cc @@ -1,5 +1,7 @@ #include "webcc/client.h" +#include "boost/algorithm/string.hpp" + #include "webcc/logger.h" using boost::asio::ip::tcp; @@ -99,19 +101,24 @@ void Client::DoClose() { } void Client::AsyncConnect() { - if (request_->url().scheme() == "https") { + if (boost::iequals(request_->url().scheme(), "http")) { + socket_.reset(new Socket{ io_context_ }); + AsyncResolve("80"); + return; + } + #if WEBCC_ENABLE_SSL + if (boost::iequals(request_->url().scheme(), "https")) { socket_.reset(new SslSocket{ io_context_, ssl_context_ }); AsyncResolve("443"); -#else - LOG_ERRO("SSL/HTTPS support is not enabled."); - error_.Set(Error::kSyntaxError, "SSL/HTTPS is not supported"); - FinishRequest(); -#endif // WEBCC_ENABLE_SSL - } else { - socket_.reset(new Socket{ io_context_ }); - AsyncResolve("80"); + return; } +#endif // WEBCC_ENABLE_SSL + + LOG_ERRO("URL scheme (%s) is not supported", + request_->url().scheme().c_str()); + error_.Set(Error::kSyntaxError, "URL scheme not supported"); + FinishRequest(); } void Client::AsyncResolve(string_view default_port) { diff --git a/webcc/client_session.cc b/webcc/client_session.cc index bddd2a1..5f90c9d 100644 --- a/webcc/client_session.cc +++ b/webcc/client_session.cc @@ -14,6 +14,8 @@ #endif // defined(_WIN32) || defined(_WIN64) #endif // WEBCC_ENABLE_SSL +#include "boost/algorithm/string.hpp" + #include "webcc/base64.h" #include "webcc/logger.h" #include "webcc/url.h" @@ -193,6 +195,10 @@ ResponsePtr ClientSession::Send(RequestPtr request, bool stream, throw Error{ Error::kStateError, "Loop is not running" }; } + if (!CheckUrlScheme(request)) { + throw Error{ Error::kSyntaxError, "Invalid URL scheme" }; + } + for (auto& h : headers_.data()) { if (!request->HasHeader(h.first)) { request->SetHeader(h.first, h.second); @@ -229,6 +235,20 @@ void ClientSession::InitHeaders() { headers_.Set(headers::kConnection, "Keep-Alive"); } +bool ClientSession::CheckUrlScheme(RequestPtr request) { + if (boost::iequals(request->url().scheme(), "http")) { + return true; + } + +#if WEBCC_ENABLE_SSL + if (boost::iequals(request->url().scheme(), "https")) { + return true; + } +#endif // WEBCC_ENABLE_SSL + + return false; +} + ResponsePtr ClientSession::DoSend(RequestPtr request, bool stream, ProgressCallback callback) { const ClientPool::Key key{ request->url() }; diff --git a/webcc/client_session.h b/webcc/client_session.h index 3fca3a1..ffd9c29 100644 --- a/webcc/client_session.h +++ b/webcc/client_session.h @@ -101,6 +101,9 @@ public: private: void InitHeaders(); + // Check if the scheme of the request is valid. + bool CheckUrlScheme(RequestPtr request); + ResponsePtr DoSend(RequestPtr request, bool stream, ProgressCallback callback);