* Copyright 2022 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Niels Sascha Reedijk, niels.reedijk@gmail.com
*/
#include <ErrorsExt.h>
#include <HttpFields.h>
#include <HttpResult.h>
#include "HttpResultPrivate.h"
using namespace BPrivate::Network;
BHttpStatusClass
BHttpStatus::StatusClass() const noexcept
{
switch (code / 100) {
case 1:
return BHttpStatusClass::Informational;
case 2:
return BHttpStatusClass::Success;
case 3:
return BHttpStatusClass::Redirection;
case 4:
return BHttpStatusClass::ClientError;
case 5:
return BHttpStatusClass::ServerError;
default:
break;
}
return BHttpStatusClass::Invalid;
}
BHttpStatusCode
BHttpStatus::StatusCode() const noexcept
{
switch (static_cast<BHttpStatusCode>(code)) {
case BHttpStatusCode::Continue:
[[fallthrough]];
case BHttpStatusCode::SwitchingProtocols:
[[fallthrough]];
case BHttpStatusCode::Ok:
[[fallthrough]];
case BHttpStatusCode::Created:
[[fallthrough]];
case BHttpStatusCode::Accepted:
[[fallthrough]];
case BHttpStatusCode::NonAuthoritativeInformation:
[[fallthrough]];
case BHttpStatusCode::NoContent:
[[fallthrough]];
case BHttpStatusCode::ResetContent:
[[fallthrough]];
case BHttpStatusCode::PartialContent:
[[fallthrough]];
case BHttpStatusCode::MultipleChoice:
[[fallthrough]];
case BHttpStatusCode::MovedPermanently:
[[fallthrough]];
case BHttpStatusCode::Found:
[[fallthrough]];
case BHttpStatusCode::SeeOther:
[[fallthrough]];
case BHttpStatusCode::NotModified:
[[fallthrough]];
case BHttpStatusCode::UseProxy:
[[fallthrough]];
case BHttpStatusCode::TemporaryRedirect:
[[fallthrough]];
case BHttpStatusCode::PermanentRedirect:
[[fallthrough]];
case BHttpStatusCode::BadRequest:
[[fallthrough]];
case BHttpStatusCode::Unauthorized:
[[fallthrough]];
case BHttpStatusCode::PaymentRequired:
[[fallthrough]];
case BHttpStatusCode::Forbidden:
[[fallthrough]];
case BHttpStatusCode::NotFound:
[[fallthrough]];
case BHttpStatusCode::MethodNotAllowed:
[[fallthrough]];
case BHttpStatusCode::NotAcceptable:
[[fallthrough]];
case BHttpStatusCode::ProxyAuthenticationRequired:
[[fallthrough]];
case BHttpStatusCode::RequestTimeout:
[[fallthrough]];
case BHttpStatusCode::Conflict:
[[fallthrough]];
case BHttpStatusCode::Gone:
[[fallthrough]];
case BHttpStatusCode::LengthRequired:
[[fallthrough]];
case BHttpStatusCode::PreconditionFailed:
[[fallthrough]];
case BHttpStatusCode::RequestEntityTooLarge:
[[fallthrough]];
case BHttpStatusCode::RequestUriTooLarge:
[[fallthrough]];
case BHttpStatusCode::UnsupportedMediaType:
[[fallthrough]];
case BHttpStatusCode::RequestedRangeNotSatisfiable:
[[fallthrough]];
case BHttpStatusCode::ExpectationFailed:
[[fallthrough]];
case BHttpStatusCode::InternalServerError:
[[fallthrough]];
case BHttpStatusCode::NotImplemented:
[[fallthrough]];
case BHttpStatusCode::BadGateway:
[[fallthrough]];
case BHttpStatusCode::ServiceUnavailable:
[[fallthrough]];
case BHttpStatusCode::GatewayTimeout:
return static_cast<BHttpStatusCode>(code);
default:
break;
}
return BHttpStatusCode::Unknown;
}
BHttpResult::BHttpResult(std::shared_ptr<HttpResultPrivate> data)
:
fData(data)
{
}
BHttpResult::BHttpResult(BHttpResult&& other) noexcept = default;
BHttpResult::~BHttpResult()
{
if (fData)
fData->SetCancel();
}
BHttpResult& BHttpResult::operator=(BHttpResult&& other) noexcept = default;
const BHttpStatus&
BHttpResult::Status() const
{
if (!fData)
throw BRuntimeError(__PRETTY_FUNCTION__, "The BHttpResult object is no longer valid");
status_t status = B_OK;
while (status == B_INTERRUPTED || status == B_OK) {
auto dataStatus = fData->GetStatusAtomic();
if (dataStatus == HttpResultPrivate::kError)
std::rethrow_exception(*(fData->error));
if (dataStatus >= HttpResultPrivate::kStatusReady)
return fData->status.value();
status = acquire_sem(fData->data_wait);
}
throw BRuntimeError(__PRETTY_FUNCTION__, "Unexpected error waiting for status!");
}
const BHttpFields&
BHttpResult::Fields() const
{
if (!fData)
throw BRuntimeError(__PRETTY_FUNCTION__, "The BHttpResult object is no longer valid");
status_t status = B_OK;
while (status == B_INTERRUPTED || status == B_OK) {
auto dataStatus = fData->GetStatusAtomic();
if (dataStatus == HttpResultPrivate::kError)
std::rethrow_exception(*(fData->error));
if (dataStatus >= HttpResultPrivate::kHeadersReady)
return *(fData->fields);
status = acquire_sem(fData->data_wait);
}
throw BRuntimeError(__PRETTY_FUNCTION__, "Unexpected error waiting for fields!");
}
BHttpBody&
BHttpResult::Body() const
{
if (!fData)
throw BRuntimeError(__PRETTY_FUNCTION__, "The BHttpResult object is no longer valid");
status_t status = B_OK;
while (status == B_INTERRUPTED || status == B_OK) {
auto dataStatus = fData->GetStatusAtomic();
if (dataStatus == HttpResultPrivate::kError)
std::rethrow_exception(*(fData->error));
if (dataStatus >= HttpResultPrivate::kBodyReady)
return *(fData->body);
status = acquire_sem(fData->data_wait);
}
throw BRuntimeError(__PRETTY_FUNCTION__, "Unexpected error waiting for the body!");
}
bool
BHttpResult::HasStatus() const
{
if (!fData)
throw BRuntimeError(__PRETTY_FUNCTION__, "The BHttpResult object is no longer valid");
return fData->GetStatusAtomic() >= HttpResultPrivate::kStatusReady;
}
bool
BHttpResult::HasFields() const
{
if (!fData)
throw BRuntimeError(__PRETTY_FUNCTION__, "The BHttpResult object is no longer valid");
return fData->GetStatusAtomic() >= HttpResultPrivate::kHeadersReady;
}
bool
BHttpResult::HasBody() const
{
if (!fData)
throw BRuntimeError(__PRETTY_FUNCTION__, "The BHttpResult object is no longer valid");
return fData->GetStatusAtomic() >= HttpResultPrivate::kBodyReady;
}
bool
BHttpResult::IsCompleted() const
{
if (!fData)
throw BRuntimeError(__PRETTY_FUNCTION__, "The BHttpResult object is no longer valid");
return HasBody();
}
int32
BHttpResult::Identity() const
{
if (!fData)
throw BRuntimeError(__PRETTY_FUNCTION__, "The BHttpResult object is no longer valid");
return fData->id;
}