NetServices: Add custom error message to BNetworkRequestError

Change-Id: I03970762531a689e25cd78a1091aecf755ee87ce
This commit is contained in:
Niels Sascha Reedijk
2022-08-07 08:47:19 +01:00
parent 6d1bb0e7ad
commit 9cb56a4881
5 changed files with 75 additions and 14 deletions
+28 -2
View File
@@ -212,15 +212,31 @@ namespace Network {
/*! /*!
\fn BNetworkRequestError::BNetworkRequestError(const char *origin, ErrorType type, \fn BNetworkRequestError::BNetworkRequestError(const char *origin, ErrorType type,
status_t errorCode=B_OK) status_t errorCode, const BString& customMessage = BString())
\brief Create a new network request error. \brief Create a new network request error.
\param origin A string representing where this error occured. It is advised \param origin A string representing where this error occured. It is advised
to initialize it to \c __PRETTY_FUNCTION__ by default. to initialize it to \c __PRETTY_FUNCTION__ by default.
\param type The error type that describes what the issue was that prevented the completion of \param type The error type that describes what the issue was that prevented the completion of
the request. the request.
\param errorCode Optional underlying system error. See the \ref BNetworkRequestError::ErrorType \param errorCode The underlying system error. See the \ref BNetworkRequestError::ErrorType
documentation on which error types expect a system error. documentation on which error types expect a system error.
\param customMessage Optional custom message describing the reason or cause for the error.
\since Haiku R1
*/
/*!
\fn BNetworkRequestError::BNetworkRequestError(const char *origin, ErrorType type,
const BString& customMessage = BString())
\brief Create a new network request error.
\param origin A string representing where this error occured. It is advised
to initialize it to \c __PRETTY_FUNCTION__ by default.
\param type The error type that describes what the issue was that prevented the completion of
the request.
\param customMessage Optional custom message describing the reason or cause for the error.
\since Haiku R1 \since Haiku R1
*/ */
@@ -248,6 +264,16 @@ namespace Network {
*/ */
/*!
\fn const char* BNetworkRequestError::CustomMessage() const noexcept
\brief Get the custom error message.
\return Get the custom error message. This may be an empty string if it was not set.
\since Haiku R1
*/
/*! /*!
\fn BString encode_to_base64(const BString& string) \fn BString encode_to_base64(const BString& string)
\brief Utility function that encodes a \a string to base64 and returns the result. \brief Utility function that encodes a \a string to base64 and returns the result.
@@ -61,7 +61,9 @@ public:
}; };
BNetworkRequestError(const char* origin, ErrorType type, BNetworkRequestError(const char* origin, ErrorType type,
status_t errorCode = B_OK); status_t errorCode, const BString& customMessage = BString());
BNetworkRequestError(const char* origin, ErrorType type,
const BString& customMessage = BString());
virtual const char* Message() const noexcept override; virtual const char* Message() const noexcept override;
virtual BString DebugMessage() const override; virtual BString DebugMessage() const override;
@@ -69,9 +71,12 @@ public:
ErrorType Type() const noexcept; ErrorType Type() const noexcept;
status_t ErrorCode() const noexcept; status_t ErrorCode() const noexcept;
const char* CustomMessage() const noexcept;
private: private:
ErrorType fErrorType; ErrorType fErrorType;
status_t fErrorCode = B_OK; status_t fErrorCode = B_OK;
BString fCustomMessage;
}; };
@@ -204,8 +204,10 @@ HttpBuffer::Data() const noexcept
HttpBuffer& HttpBuffer&
HttpBuffer::operator<<(const std::string_view& data) HttpBuffer::operator<<(const std::string_view& data)
{ {
if (data.size() > (fBuffer.capacity() - fBuffer.size())) if (data.size() > (fBuffer.capacity() - fBuffer.size())) {
throw BNetworkRequestError(__PRETTY_FUNCTION__, BNetworkRequestError::ProtocolError); throw BNetworkRequestError(__PRETTY_FUNCTION__, BNetworkRequestError::ProtocolError,
"No capacity left in buffer to append data.");
}
for (const auto& character: data) for (const auto& character: data)
fBuffer.push_back(static_cast<const std::byte>(character)); fBuffer.push_back(static_cast<const std::byte>(character));
@@ -954,13 +954,18 @@ BHttpSession::Request::ReceiveResult()
auto locationField = fFields.FindField("Location"); auto locationField = fFields.FindField("Location");
if (locationField == fFields.end()) { if (locationField == fFields.end()) {
throw BNetworkRequestError(__PRETTY_FUNCTION__, throw BNetworkRequestError(__PRETTY_FUNCTION__,
BNetworkRequestError::ProtocolError); BNetworkRequestError::ProtocolError,
"Redirect; the Location field must be present and cannot be found");
} }
auto locationString = BString((*locationField).Value().data(), auto locationString = BString((*locationField).Value().data(),
(*locationField).Value().size()); (*locationField).Value().size());
auto redirect = BHttpSession::Redirect{BUrl(fRequest.Url(), locationString), redirectToGet}; auto redirect =
if (!redirect.url.IsValid()) BHttpSession::Redirect{BUrl(fRequest.Url(), locationString), redirectToGet};
throw BNetworkRequestError(__PRETTY_FUNCTION__, BNetworkRequestError::ProtocolError); if (!redirect.url.IsValid()) {
throw BNetworkRequestError(__PRETTY_FUNCTION__,
BNetworkRequestError::ProtocolError,
"Redirect; invalid URL in the Location field");
}
// Notify of redirect // Notify of redirect
SendMessage(UrlEvent::HttpRedirect, [&locationString](BMessage& msg) { SendMessage(UrlEvent::HttpRedirect, [&locationString](BMessage& msg) {
@@ -1009,12 +1014,16 @@ BHttpSession::Request::ReceiveResult()
fNoContent = true; fNoContent = true;
fParser.SetContentLength(bodyBytesTotal); fParser.SetContentLength(bodyBytesTotal);
} catch (const std::logic_error& e) { } catch (const std::logic_error& e) {
throw BNetworkRequestError(__PRETTY_FUNCTION__, BNetworkRequestError::ProtocolError); throw BNetworkRequestError(__PRETTY_FUNCTION__,
BNetworkRequestError::ProtocolError,
"Cannot parse Content-Length field value (logic_error)");
} }
} }
if (bodyBytesTotal == std::nullopt) if (bodyBytesTotal == std::nullopt) {
throw BNetworkRequestError(__PRETTY_FUNCTION__, BNetworkRequestError::ProtocolError); throw BNetworkRequestError(__PRETTY_FUNCTION__,
BNetworkRequestError::ProtocolError, "Expected Content-Length field");
}
} }
// Move headers to the result and inform listener // Move headers to the result and inform listener
@@ -98,8 +98,17 @@ BInvalidUrl::Url() const
// #pragma mark -- BNetworkRequestError // #pragma mark -- BNetworkRequestError
BNetworkRequestError::BNetworkRequestError(const char* origin, ErrorType type, status_t errorCode) BNetworkRequestError::BNetworkRequestError(const char* origin, ErrorType type, status_t errorCode,
: BError(origin), fErrorType(type), fErrorCode(errorCode) const BString& customMessage)
: BError(origin), fErrorType(type), fErrorCode(errorCode), fCustomMessage(customMessage)
{
}
BNetworkRequestError::BNetworkRequestError(const char* origin, ErrorType type,
const BString& customMessage)
: BError(origin), fErrorType(type), fCustomMessage(customMessage)
{ {
} }
@@ -134,6 +143,9 @@ BNetworkRequestError::DebugMessage() const
debugMessage << "\n\tUnderlying System Error: " << fErrorCode << " (" debugMessage << "\n\tUnderlying System Error: " << fErrorCode << " ("
<< strerror(fErrorCode) << ")"; << strerror(fErrorCode) << ")";
} }
if (fCustomMessage.Length() > 0) {
debugMessage << "\n\tAdditional Info: " << fCustomMessage;
}
return debugMessage; return debugMessage;
} }
@@ -152,6 +164,13 @@ BNetworkRequestError::ErrorCode() const noexcept
} }
const char*
BNetworkRequestError::CustomMessage() const noexcept
{
return fCustomMessage.String();
}
// #pragma mark -- Public functions // #pragma mark -- Public functions