NetServices: Remove BHttpRequest::SerializeTo(BDataIO*)

The private version that serializes to a HttpBuffer is now used.

Change-Id: I034933a641e98b3a8f918470a024ba32ea7c8663
This commit is contained in:
Niels Sascha Reedijk 2022-08-07 07:17:38 +01:00
parent c7f925c3ee
commit 6d1bb0e7ad
5 changed files with 21 additions and 112 deletions

View File

@ -825,26 +825,6 @@ namespace Network {
//! @{
/*!
\fn ssize_t BHttpRequest::SerializeHeaderTo(BDataIO *target) const
\brief Serialize the HTTP Header of this request to the \a target.
The HTTP header consists of the request line, and the fields, serialized as text according to
the HTTP specification.
\param target The \ref BDataIO object to write the header to
\return The total number of byte size of the header.
\exception BSystemError In case there is an error when calling the \ref BDataIO::Write() call
of the provided \a target. Note that writing the string is \em not transactional, and that
the error can occur while a part of the header has already been written.
\exception std::bad_alloc In case it is not possible to allocate internal buffers.
\since Haiku R1
*/
/*!
\fn BString BHttpRequest::HeaderToString() const
\brief Serialize the HTTP Header of this request to a string.

View File

@ -131,7 +131,6 @@ public:
std::unique_ptr<BDataIO> ClearRequestBody() noexcept;
// Serialization
ssize_t SerializeHeaderTo(BDataIO* target) const;
BString HeaderToString() const;
private:

View File

@ -147,7 +147,7 @@ HttpBuffer::GetNextLine()
\brief Get the number of remaining bytes in this buffer.
*/
size_t
HttpBuffer::RemainingBytes() noexcept
HttpBuffer::RemainingBytes() const noexcept
{
return fBuffer.size() - fCurrentOffset;
}
@ -182,6 +182,20 @@ HttpBuffer::Clear() noexcept
}
/*!
\brief Get a view over the current data
*/
std::string_view
HttpBuffer::Data() const noexcept
{
if (RemainingBytes() > 0) {
return std::string_view(reinterpret_cast<const char*>(fBuffer.data()) + fCurrentOffset,
RemainingBytes());
} else
return std::string_view();
}
/*!
\brief Load data into the buffer

View File

@ -32,11 +32,13 @@ public:
std::optional<size_t> maxSize = std::nullopt);
std::optional<BString> GetNextLine();
size_t RemainingBytes() noexcept;
size_t RemainingBytes() const noexcept;
void Flush() noexcept;
void Clear() noexcept;
std::string_view Data() const noexcept;
// load data into the buffer
HttpBuffer& operator<<(const std::string_view& data);

View File

@ -433,99 +433,13 @@ BHttpRequest::ClearRequestBody() noexcept
}
[[nodiscard]] static inline ssize_t
_write_to_dataio(BDataIO* target, const std::string_view& data)
{
if (auto status = target->WriteExactly(data.data(), data.size()); status != B_OK)
throw BSystemError("BDataIO::WriteExactly()", status);
return data.size();
}
[[nodiscard]] static inline ssize_t
_write_to_dataio(BDataIO* target, const BString& string)
{
auto length = string.Length();
if (auto status = target->WriteExactly(string.String(), length); status != B_OK)
throw BSystemError("BDataIO::WriteExactly()", status);
return length;
}
ssize_t
BHttpRequest::SerializeHeaderTo(BDataIO* target) const
{
auto bytesWritten = _write_to_dataio(target, fData->method.Method());
bytesWritten += _write_to_dataio(target, " "sv);
// TODO: proxy
if (fData->url.HasPath() && fData->url.Path().Length() > 0)
bytesWritten += _write_to_dataio(target, fData->url.Path());
else
bytesWritten += _write_to_dataio(target, "/"sv);
// TODO: switch between HTTP 1.0 and 1.1 based on configuration
bytesWritten += _write_to_dataio(target, " HTTP/1.1\r\n"sv);
BHttpFields outputFields;
if (true /* http == 1.1 */) {
BString host = fData->url.Host();
int defaultPort = fData->url.Protocol() == "http" ? 80 : 443;
if (fData->url.HasPort() && fData->url.Port() != defaultPort)
host << ':' << fData->url.Port();
outputFields.AddFields({
{"Host"sv, std::string_view(host.String())},
{"Accept-Encoding"sv, "gzip"sv},
// Allows the server to compress data using the "gzip" format.
// "deflate" is not supported, because there are two interpretations
// of what it means (the RFC and Microsoft products), and we don't
// want to handle this. Very few websites support only deflate,
// and most of them will send gzip, or at worst, uncompressed data.
{"Connection"sv, "close"sv}
// Let the remote server close the connection after response since
// we don't handle multiple request on a single connection
});
}
if (fData->authentication) {
// This request will add a Basic authorization header
BString authorization = build_basic_http_header(fData->authentication->username,
fData->authentication->password);
outputFields.AddField("Authorization"sv, std::string_view(authorization.String()));
}
if (fData->requestBody) {
outputFields.AddField("Content-Type"sv, std::string_view(fData->requestBody->mimeType.String()));
if (fData->requestBody->size)
outputFields.AddField("Content-Length"sv, std::to_string(*fData->requestBody->size));
else
throw BRuntimeError(__PRETTY_FUNCTION__, "Transfer body with unknown content length; chunked transfer not supported");
}
for (const auto& field: outputFields) {
bytesWritten += _write_to_dataio(target, field.RawField());
bytesWritten += _write_to_dataio(target, "\r\n"sv);
}
for (const auto& field: fData->optionalFields) {
bytesWritten += _write_to_dataio(target, field.RawField());
bytesWritten += _write_to_dataio(target, "\r\n"sv);
}
bytesWritten += _write_to_dataio(target, "\r\n"sv);
return bytesWritten;
}
BString
BHttpRequest::HeaderToString() const
{
BMallocIO buffer;
auto size = SerializeHeaderTo(&buffer);
HttpBuffer buffer;
SerializeHeaderTo(buffer);
return BString(static_cast<const char*>(buffer.Buffer()), size);
return BString(static_cast<const char*>(buffer.Data().data()), buffer.RemainingBytes());
}