From 6ce6e96470c1832bf07ed07f329e2239ba152ff7 Mon Sep 17 00:00:00 2001 From: Niels Sascha Reedijk Date: Fri, 25 Feb 2022 08:41:14 +0000 Subject: [PATCH] NetServices: Introduce BHttpRequest class Objects of this class describe a HTTP request. It contains several convenience functions that will allow a user to describe the properties of the request. More options to be added later. Change-Id: If6a00d26808c5ed4b121cb36dc75a2a1cc449f95 --- docs/user/netservices/HttpRequest.dox | 225 ++++++++++++++++++ headers/private/netservices2/HttpRequest.h | 33 ++- .../network/libnetservices2/HttpRequest.cpp | 99 ++++++++ .../net/netservices2/HttpProtocolTest.cpp | 16 ++ .../kits/net/netservices2/HttpProtocolTest.h | 1 + 5 files changed, 373 insertions(+), 1 deletion(-) diff --git a/docs/user/netservices/HttpRequest.dox b/docs/user/netservices/HttpRequest.dox index 2461b1d528..b3bd172901 100644 --- a/docs/user/netservices/HttpRequest.dox +++ b/docs/user/netservices/HttpRequest.dox @@ -248,6 +248,231 @@ namespace Network { */ +/*! + \class BHttpRequest + \ingroup netservices + \brief Represent a HTTP request. + + This class can be used to construct HTTP requests that can be executed by the Network Services + Kit. A request has two states, either it is is a valid request, or it is an empty request. The + criterium is whether or not the request has a URL. + + This class has all kinds of convenience methods set and retrieve particular options. Most + options are wrapped in specialized container classes that do some form of validation. + + The default options are: + + + + + + + + + + + + + + +
GetterSetterDescriptionDefault
\ref Url() \ref SetUrl() The URL. This must start with http or https. Defaults to an empty \ref BUrl
\ref Method() \ref SetMethod() The HTTP method for the request Defaults to \ref BHttpMethod::Get
+ + \since Haiku R1 +*/ + + +/*! + \name Constructors and Destructor +*/ + + +//! @{ + + +/*! + \fn BHttpRequest::BHttpRequest() + \brief Construct an empty HTTP request. + + \exception std::bad_alloc This exception may be raised if it is impossible to allocate memory. + + \since Haiku R1 +*/ + + +/*! + \fn BHttpRequest::BHttpRequest(const BUrl &url) + \brief Construct a HTTP request for an \a url. + + \param url A valid URL with the \c http or \c https protocol. + + \exception std::bad_alloc This exception may be raised if it is impossible to allocate memory. + \exception BUnsupportedProtocol This exception is raised when the protocol of the URL cannot be + handled. + \exception BInvalidUrl This exception is raised when the \a url is invalid. + + \since Haiku R1 +*/ + + +/*! + \fn BHttpRequest::BHttpRequest(const BHttpRequest &other)=delete + \brief Copying is not allowed. + + \since Haiku R1 +*/ + + +/*! + \fn BHttpRequest::BHttpRequest(BHttpRequest &&other) noexcept + \brief Move constructor. + + After a move, the \a other object is left in an empty state. + + \param other The request to move data from. + + \since Haiku R1 +*/ + + +/*! + \fn BPrivate::Network::BHttpRequest::~BHttpRequest() + \brief Destructor + + \since Haiku R1 +*/ + + +//! @} + + +/*! + \name Assignment operators +*/ + + +//! @{ + + +/*! + \fn BHttpRequest& BHttpRequest::operator=(const BHttpRequest &other)=delete + \brief Copy assignment is not allowed. + + \since Haiku R1 +*/ + + +/*! + \fn BHttpRequest& BHttpRequest::operator=(BHttpRequest &&other) noexcept + \brief Move assignment + + After a move, the \a other object is left in an empty state. + + \param other The request to move data from. + + \since Haiku R1 +*/ + + +//! @} + + +/*! + \name Valid or empty +*/ + + +//! @{ + + +/*! + \fn bool BHttpRequest::IsEmpty() const noexcept + \brief Check if the request is valid or empty + + \retval true The request is empty. + \retval false The request is valid. + + \since Haiku R1 +*/ + + +//! @} + + +/*! + \name Current Options +*/ + + +//! @{ + + +/*! + \fn const BHttpMethod& BHttpRequest::Method() const noexcept + \brief Get the current method for the request. + + This will either return the custom value set for this request, or the default as is listed in + the overview documentation of this class. + + \since Haiku R1 +*/ + + +/*! + \fn const BUrl& BHttpRequest::Url() const noexcept + \brief Get the current Url for the request. + + This will either return the custom value set for this request, or the default as is listed in + the overview documentation of this class. + + \since Haiku R1 +*/ + + +//! @} + + +/*! + \name Setting Options +*/ + + +//! @{ + + +/*! + \fn void BHttpRequest::SetMethod(const BHttpMethod &method) + \brief Set the \a method for this request. + + Note that there currently is no additional validation done on any semantical incompatibilities. + This means that it is currently allowed to do a \c GET or \c HEAD request with data, while that + is forbidden by the standard. + + \param method The method to use for the request. + + \exception std::bad_alloc This exception may be raised if it is impossible to allocate memory. + + \since Haiku R1 +*/ + + +/*! + \fn void BHttpRequest::SetUrl(const BUrl &url) + \brief Set the \a url for this request. + + \param url A valid URL with the \c http or \c https protocol. + + \exception std::bad_alloc This exception may be raised if it is impossible to allocate memory. + \exception BUnsupportedProtocol This exception is raised when the protocol of the URL cannot be + handled. + \exception BInvalidUrl This exception is raised when the \a url is invalid. + + \since Haiku R1 +*/ + + +//! @} + + } // namespace Network } // namespace BPrivate diff --git a/headers/private/netservices2/HttpRequest.h b/headers/private/netservices2/HttpRequest.h index 341b08f773..e66e96b642 100644 --- a/headers/private/netservices2/HttpRequest.h +++ b/headers/private/netservices2/HttpRequest.h @@ -6,12 +6,15 @@ #ifndef _B_HTTP_REQUEST_H_ #define _B_HTTP_REQUEST_H_ +#include #include #include #include #include +class BUrl; + namespace BPrivate { @@ -62,8 +65,36 @@ private: }; +class BHttpRequest { +public: + // Constructors and Destructor + BHttpRequest(); + BHttpRequest(const BUrl& url); + BHttpRequest(const BHttpRequest& other) = delete; + BHttpRequest(BHttpRequest&& other) noexcept; + ~BHttpRequest(); + + // Assignment operators + BHttpRequest& operator=(const BHttpRequest& other) = delete; + BHttpRequest& operator=(BHttpRequest&&) noexcept; + + // Access + bool IsEmpty() const noexcept; + const BHttpMethod& Method() const noexcept; + const BUrl& Url() const noexcept; + + // Named Setters + void SetMethod(const BHttpMethod& method); + void SetUrl(const BUrl& url); + +private: + struct Impl; + std::unique_ptr fData; +}; + + } // namespace Network } // namespace BPrivate -#endif // B_HTTP_REQUEST +#endif // _B_HTTP_REQUEST_H_ diff --git a/src/kits/network/libnetservices2/HttpRequest.cpp b/src/kits/network/libnetservices2/HttpRequest.cpp index 892a9b266a..dd80172b4e 100644 --- a/src/kits/network/libnetservices2/HttpRequest.cpp +++ b/src/kits/network/libnetservices2/HttpRequest.cpp @@ -12,6 +12,9 @@ #include #include +#include +#include + #include "HttpPrivate.h" using namespace std::literals; @@ -125,3 +128,99 @@ BHttpMethod::Method() const noexcept return std::string_view(methodString.String()); } } + + +// #pragma mark -- BHttpRequest::Impl +static const BUrl kDefaultUrl = BUrl(); +static const BHttpMethod kDefaultMethod = BHttpMethod::Get; + + +struct BHttpRequest::Impl { + BUrl url; + BHttpMethod method = kDefaultMethod; + bool ssl = false; +}; + + +// #pragma mark -- BHttpRequest + + +BHttpRequest::BHttpRequest() + : fData(std::make_unique()) +{ + +} + + +BHttpRequest::BHttpRequest(const BUrl& url) + : fData(std::make_unique()) +{ + SetUrl(url); +} + + +BHttpRequest::BHttpRequest(BHttpRequest&& other) noexcept = default; + + +BHttpRequest::~BHttpRequest() = default; + + +BHttpRequest& +BHttpRequest::operator=(BHttpRequest&&) noexcept = default; + + +bool +BHttpRequest::IsEmpty() const noexcept +{ + return (!fData || !fData->url.IsValid()); +} + + +const BHttpMethod& +BHttpRequest::Method() const noexcept +{ + if (!fData) + return kDefaultMethod; + return fData->method; +} + + +const BUrl& +BHttpRequest::Url() const noexcept +{ + if (!fData) + return kDefaultUrl; + return fData->url; +} + + +void +BHttpRequest::SetMethod(const BHttpMethod& method) +{ + if (!fData) + fData = std::make_unique(); + fData->method = method; +} + + +void +BHttpRequest::SetUrl(const BUrl& url) +{ + if (!fData) + fData = std::make_unique(); + + if (!url.IsValid()) + throw BInvalidUrl(__PRETTY_FUNCTION__, BUrl(url)); + if (url.Protocol() == "http") + fData->ssl = false; + else if (url.Protocol() == "https") + fData->ssl = true; + else { + // TODO: optimize BStringList with modern language features + BStringList list; + list.Add("http"); + list.Add("https"); + throw BUnsupportedProtocol(__PRETTY_FUNCTION__, BUrl(url), list); + } + fData->url = url; +} diff --git a/src/tests/kits/net/netservices2/HttpProtocolTest.cpp b/src/tests/kits/net/netservices2/HttpProtocolTest.cpp index 1b6d5a7292..e88cc35ca5 100644 --- a/src/tests/kits/net/netservices2/HttpProtocolTest.cpp +++ b/src/tests/kits/net/netservices2/HttpProtocolTest.cpp @@ -14,9 +14,11 @@ #include #include +#include using BPrivate::Network::BHttpFields; using BPrivate::Network::BHttpMethod; +using BPrivate::Network::BHttpRequest; using BPrivate::Network::BHttpSession; @@ -219,6 +221,18 @@ HttpProtocolTest::HttpMethodTest() } +void +HttpProtocolTest::HttpRequestTest() +{ + // Basic test + BHttpRequest request; + CPPUNIT_ASSERT(request.IsEmpty()); + auto url = BUrl("https://www.haiku-os.org"); + request.SetUrl(url); + CPPUNIT_ASSERT(request.Url() == url); +} + + /* static */ void HttpProtocolTest::AddTests(BTestSuite& parent) { @@ -228,6 +242,8 @@ HttpProtocolTest::AddTests(BTestSuite& parent) "HttpProtocolTest::HttpFieldsTest", &HttpProtocolTest::HttpFieldsTest)); suite.addTest(new CppUnit::TestCaller( "HttpProtocolTest::HttpMethodTest", &HttpProtocolTest::HttpMethodTest)); + suite.addTest(new CppUnit::TestCaller( + "HttpProtocolTest::HttpRequestTest", &HttpProtocolTest::HttpRequestTest)); parent.addTest("HttpProtocolTest", &suite); } diff --git a/src/tests/kits/net/netservices2/HttpProtocolTest.h b/src/tests/kits/net/netservices2/HttpProtocolTest.h index 9519ba4354..9ed347c2dd 100644 --- a/src/tests/kits/net/netservices2/HttpProtocolTest.h +++ b/src/tests/kits/net/netservices2/HttpProtocolTest.h @@ -19,6 +19,7 @@ public: void HttpFieldsTest(); void HttpMethodTest(); + void HttpRequestTest(); static void AddTests(BTestSuite& suite);