netservices: add BHttpHeader class and BHttpHeaderMap skeleton
Change-Id: I36a7c757a6909604d749355ecb1a9d42d05d7306
This commit is contained in:
parent
892cbe10b6
commit
34522da9e3
332
docs/user/netservices/HttpHeaders.dox
Executable file
332
docs/user/netservices/HttpHeaders.dox
Executable file
@ -0,0 +1,332 @@
|
||||
/*
|
||||
* Copyright 2021 Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Niels Sascha Reedijk, niels.reedijk@gmail.com
|
||||
*
|
||||
* Corresponds to:
|
||||
* headers/private/netservices2/HttpHeaders.h hrev?????
|
||||
* src/kits/network/libnetservices2/HttpHeaders.cpp hrev?????
|
||||
*/
|
||||
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
|
||||
|
||||
/*!
|
||||
\file HttpHeaders.h
|
||||
\ingroup netservices
|
||||
\brief Provides the BHttpHeader and BHttpHeaderMap classes.
|
||||
*/
|
||||
|
||||
namespace BPrivate {
|
||||
|
||||
namespace Network {
|
||||
|
||||
|
||||
/*!
|
||||
\class BHttpHeader
|
||||
\ingroup netservices
|
||||
\brief Represent a HTTP header name and value pair.
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\class BHttpHeader::InvalidInput
|
||||
\ingroup netservices
|
||||
\brief Error that represents when a string input contains characters that are incompatible with
|
||||
the HTTP specification.
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\var BString BHttpHeader::InvalidInput::input
|
||||
\brief The input that contains the invalid contents.
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn BHttpHeader::InvalidInput::InvalidInput(const char *origin, BString input)
|
||||
\brief Constructor that sets the \a origin and the invalid \a input.
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn virtual BString BHttpHeader::InvalidInput::DebugMessage() const override
|
||||
\brief Retrieve a debug message that contains all info in this error.
|
||||
|
||||
The output will be along the lines of:
|
||||
\code
|
||||
[Origin] Invalid format or unsupported characters in input [input]
|
||||
\endcode
|
||||
|
||||
\exception std::bad_alloc In the future this method may throw this
|
||||
exception when the memory for the debug message cannot be allocated.
|
||||
|
||||
\return A \ref BString object that contains the debug message.
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn virtual const char* BHttpHeader::InvalidInput::Message() const noexcept override
|
||||
\brief Get a pointer to the message describing the error.
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\class BHttpHeader::EmptyHeader
|
||||
\ingroup netservices
|
||||
\brief Error that is raised when the HTTP header has an empty name or value when it is
|
||||
serialized to and from text.
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn BHttpHeader::EmptyHeader::EmptyHeader(const char *origin)
|
||||
\copydoc BError::BError()
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn virtual const char* BHttpHeader::EmptyHeader::Message() const noexcept override
|
||||
\brief Get a pointer to the message describing the error.
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\class BHttpHeader::HeaderName
|
||||
\ingroup netservices
|
||||
\brief Representation of a HTTP header name.
|
||||
|
||||
As per the HTTP specification, header fields have a name. There are limitations to which
|
||||
characters are supported. As per the specification, header field names are case insensitive.
|
||||
This means that the \c content-encoding is equal to \c Content-Encoding or even
|
||||
\c COnTenT-ENcOdING.
|
||||
|
||||
This particular object can be empty. Headers with empty names can still be used in the
|
||||
\ref BHttpHeaderMap object, though as soon as you try to serialize them to a string, the
|
||||
\ref BHttpHeader::EmptyHeader exception will be raised.
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn bool BHttpHeader::HeaderName::IsEmpty() const noexcept
|
||||
\brief Check if the header name has a value set.
|
||||
|
||||
\retval true This object is empty, meaning it is set to an empty string.
|
||||
\retval false This object has a valid header name.
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn BHttpHeader::HeaderName::operator BString() const
|
||||
\brief Return a copy of the header name as a string.
|
||||
|
||||
\return The header name as a \ref BString object.
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn BHttpHeader::HeaderName::operator std::string_view() const
|
||||
\brief Return a \c std::string_view over the header name.
|
||||
|
||||
\return A \c std::string_view object over the header name.
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn bool BHttpHeader::HeaderName::operator==(const BString &other) const noexcept
|
||||
\brief Compare the header name to a string.
|
||||
|
||||
\param other The \c other string to compare it to.
|
||||
|
||||
The comparison is case-insensitive. So if this header name is set to \c Content-Encoding,
|
||||
comparing it to \c content-encoding will return \c true.
|
||||
|
||||
\retval true The current header name is equal to the \a other name.
|
||||
\retval false The current header name is different from the \a other name.
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn bool BHttpHeader::HeaderName::operator==(const std::string_view other) const noexcept
|
||||
\copydoc BHttpHeader::HeaderName::operator==(const BString &other) const noexcept
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn BHttpHeader::BHttpHeader()
|
||||
\brief Construct an empty HTTP Header Field.
|
||||
|
||||
The name and the value of the field will both be empty.
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn BHttpHeader::BHttpHeader(BHttpHeader &&other) noexcept
|
||||
\brief Move constructor.
|
||||
|
||||
The name and value from the \a other header object will be moved to this object. The \a other
|
||||
object will be empty, meaning it no longer has a name or value.
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn BHttpHeader::BHttpHeader(const BHttpHeader &other)
|
||||
\brief Copy constructor.
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn BHttpHeader::BHttpHeader(std::string_view name, std::string_view value)
|
||||
\brief Constructor to create a header from a \a name and a \a value.
|
||||
|
||||
The parameters are checked whether they only contain characters that are allowed by the HTTP
|
||||
specification.
|
||||
|
||||
\param name The name of the header field.
|
||||
\param value The value of the header field.
|
||||
|
||||
\exception BHttpHeader::InvalidInput This error indicates that the \a name or the \a value
|
||||
contains invalid characters.
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn BHttpHeader::~BHttpHeader() noexcept
|
||||
\brief Destructor.
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn bool BHttpHeader::IsEmpty() noexcept
|
||||
\brief Check if the name or the value are empty.
|
||||
|
||||
A header is considered empty when it does not have a name or a value, or neither of them. An
|
||||
empty header cannot be serialized to a string.
|
||||
|
||||
\retval true The name or value are empty.
|
||||
\retval false The name and value contain valid data.
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn const HeaderName& BHttpHeader::Name() noexcept
|
||||
\brief Get the header name.
|
||||
|
||||
\return A reference to the header name object.
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn std::string_view BHttpHeader::Value() noexcept
|
||||
\brief Get the header value.
|
||||
|
||||
\return A \c std::string_view to the header value.
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn BHttpHeader& BHttpHeader::operator=(BHttpHeader &&other) noexcept
|
||||
\brief Move assignment operator.
|
||||
|
||||
Moves the name and value from the \a other header to this object. The \a other object will be
|
||||
empty.
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn BHttpHeader& BHttpHeader::operator=(const BHttpHeader &other)
|
||||
\brief Copy assignment operator.
|
||||
|
||||
Make a new header object with a copy of the name and value of the \a other header.
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn void BHttpHeader::SetName(std::string_view name)
|
||||
\brief Set the name of the header to a \a name.
|
||||
|
||||
\param name A header name with characters supported by the HTTP specification.
|
||||
|
||||
\exception BHttpHeader::InvalidInput This error indicates that the \a name contains invalid
|
||||
characters.
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn void BHttpHeader::SetValue(std::string_view value)
|
||||
\brief Set the value of the header to a \a value.
|
||||
|
||||
\param value A header value with characters supported by the HTTP specification.
|
||||
|
||||
\exception BHttpHeader::InvalidInput This error indicates that the \a value contains invalid
|
||||
characters.
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\class BHttpHeaderMap
|
||||
\ingroup netservices
|
||||
\brief Represent set of HTTP headers.
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
|
||||
} // namespace Network
|
||||
|
||||
} // namespace BPrivate
|
||||
|
||||
#endif
|
94
headers/private/netservices2/HttpHeaders.h
Executable file
94
headers/private/netservices2/HttpHeaders.h
Executable file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2021 Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef _B_HTTP_HEADERS_H_
|
||||
#define _B_HTTP_HEADERS_H_
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include <ErrorsExt.h>
|
||||
#include <String.h>
|
||||
|
||||
|
||||
namespace BPrivate {
|
||||
|
||||
namespace Network {
|
||||
|
||||
|
||||
class BHttpHeader {
|
||||
public:
|
||||
// Exceptions
|
||||
class InvalidInput : public BError {
|
||||
public:
|
||||
InvalidInput(const char* origin, BString input);
|
||||
|
||||
virtual const char* Message() const noexcept override;
|
||||
virtual BString DebugMessage() const override;
|
||||
|
||||
BString input;
|
||||
};
|
||||
|
||||
class EmptyHeader : public BError {
|
||||
public:
|
||||
EmptyHeader(const char* origin);
|
||||
|
||||
virtual const char* Message() const noexcept override;
|
||||
};
|
||||
|
||||
// Wrapper Types
|
||||
class HeaderName {
|
||||
public:
|
||||
bool IsEmpty() const noexcept { return fName.IsEmpty(); }
|
||||
|
||||
// Comparison
|
||||
bool operator==(const BString& other) const noexcept;
|
||||
bool operator==(const std::string_view other) const noexcept;
|
||||
|
||||
// Conversion
|
||||
operator BString() const;
|
||||
operator std::string_view() const;
|
||||
private:
|
||||
friend class BHttpHeader;
|
||||
HeaderName(std::string_view name);
|
||||
BString fName;
|
||||
};
|
||||
|
||||
// Constructors & Destructor
|
||||
BHttpHeader();
|
||||
BHttpHeader(std::string_view name, std::string_view value);
|
||||
BHttpHeader(const BHttpHeader& other);
|
||||
BHttpHeader(BHttpHeader&& other) noexcept;
|
||||
~BHttpHeader() noexcept;
|
||||
|
||||
// Assignment operators
|
||||
BHttpHeader& operator=(const BHttpHeader& other);
|
||||
BHttpHeader& operator=(BHttpHeader&& other) noexcept;
|
||||
|
||||
// Header data modification
|
||||
void SetName(std::string_view name);
|
||||
void SetValue(std::string_view value);
|
||||
|
||||
// Access Data
|
||||
const HeaderName& Name() noexcept;
|
||||
std::string_view Value() noexcept;
|
||||
bool IsEmpty() noexcept;
|
||||
|
||||
private:
|
||||
HeaderName fName;
|
||||
BString fValue;
|
||||
};
|
||||
|
||||
|
||||
// Placeholder for a HashMap that represents HTTP Headers
|
||||
class BHttpHeaderMap {
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // namespace Network
|
||||
|
||||
} // namespace BPrivate
|
||||
|
||||
#endif // _B_HTTP_HEADERS_H_
|
225
src/kits/network/libnetservices2/HttpHeaders.cpp
Executable file
225
src/kits/network/libnetservices2/HttpHeaders.cpp
Executable file
@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Copyright 2021 Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Niels Sascha Reedijk, niels.reedijk@gmail.com
|
||||
*/
|
||||
|
||||
#include <HttpHeaders.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <utility>
|
||||
|
||||
using namespace BPrivate::Network;
|
||||
|
||||
|
||||
// #pragma mark -- utilities
|
||||
|
||||
|
||||
/*!
|
||||
\brief Validate whether the string conforms to a HTTP token value
|
||||
|
||||
RFC 7230 section 3.2.6 determines that valid tokens for the header name are:
|
||||
!#$%&'*+=.^_`|~, any digits or alpha.
|
||||
|
||||
\returns \c true if the string is valid, or \c false if it is not.
|
||||
*/
|
||||
static inline bool
|
||||
validate_token_string(std::string_view string)
|
||||
{
|
||||
for (auto it = string.cbegin(); it < string.cend(); it++) {
|
||||
if (*it <= 31 || *it == 127 || *it == '(' || *it == ')' || *it == '<' || *it == '>'
|
||||
|| *it == '@' || *it == ',' || *it == ';' || *it == '\\' || *it == '"'
|
||||
|| *it == '/' || *it == '[' || *it == ']' || *it == '?' || *it == '='
|
||||
|| *it == '{' || *it == '}' || *it == ' ')
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Validate whether the string is a valid HTTP header value
|
||||
|
||||
RFC 7230 section 3.2.6 determines that valid tokens for the header are:
|
||||
HTAB ('\t'), SP (32), all visible ASCII characters (33-126), and all characters that
|
||||
not control characters (in the case of a char, any value < 0)
|
||||
|
||||
\note When printing out the HTTP header, sometimes the string needs to be quoted and some
|
||||
characters need to be escaped. This function is not checking for whether the string can
|
||||
be transmitted as is.
|
||||
|
||||
\returns \c true if the string is valid, or \c false if it is not.
|
||||
*/
|
||||
static inline bool
|
||||
validate_value_string(std::string_view string)
|
||||
{
|
||||
for (auto it = string.cbegin(); it < string.cend(); it++) {
|
||||
if ((*it >= 0 && *it < 32) || *it == 127 || *it == '\t')
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -- BHttpHeader::InvalidHeader
|
||||
|
||||
|
||||
BHttpHeader::InvalidInput::InvalidInput(const char* origin, BString input)
|
||||
:
|
||||
BError(origin),
|
||||
input(std::move(input))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
BHttpHeader::InvalidInput::Message() const noexcept
|
||||
{
|
||||
return "Invalid format or unsupported characters in input";
|
||||
}
|
||||
|
||||
|
||||
BString
|
||||
BHttpHeader::InvalidInput::DebugMessage() const
|
||||
{
|
||||
BString output = BError::DebugMessage();
|
||||
output << "\t " << input << "\n";
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -- BHttpHeader::EmptyHeader
|
||||
|
||||
|
||||
BHttpHeader::EmptyHeader::EmptyHeader(const char* origin)
|
||||
:
|
||||
BError(origin)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
BHttpHeader::EmptyHeader::Message() const noexcept
|
||||
{
|
||||
return "Cannot convert this object into a HTTP header string: the name or value is empty";
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -- BHttpHeader::HeaderName
|
||||
|
||||
|
||||
BHttpHeader::HeaderName::HeaderName(std::string_view name)
|
||||
{
|
||||
if (name.empty()) {
|
||||
// ignore an empty name
|
||||
} else if (!validate_token_string(name)) {
|
||||
throw InvalidInput(__PRETTY_FUNCTION__, BString(name.data(), name.size()));
|
||||
} else {
|
||||
fName.SetTo(name.data(), name.length());
|
||||
fName.CapitalizeEachWord();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BHttpHeader::HeaderName::operator==(const BString& other) const noexcept
|
||||
{
|
||||
return fName.ICompare(other) == 0;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BHttpHeader::HeaderName::operator==(const std::string_view other) const noexcept
|
||||
{
|
||||
return fName.ICompare(other.data(), other.size()) == 0;
|
||||
}
|
||||
|
||||
|
||||
BHttpHeader::HeaderName::operator BString() const
|
||||
{
|
||||
return fName;
|
||||
}
|
||||
|
||||
|
||||
BHttpHeader::HeaderName::operator std::string_view() const
|
||||
{
|
||||
return std::string_view(fName.String());
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -- BHttpHeader
|
||||
|
||||
|
||||
BHttpHeader::BHttpHeader()
|
||||
: fName(std::string_view())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
BHttpHeader::BHttpHeader(std::string_view name, std::string_view value)
|
||||
: fName(name)
|
||||
{
|
||||
SetValue(value);
|
||||
}
|
||||
|
||||
|
||||
BHttpHeader::BHttpHeader(const BHttpHeader& other) = default;
|
||||
|
||||
|
||||
BHttpHeader::BHttpHeader(BHttpHeader&& other) noexcept = default;
|
||||
|
||||
|
||||
BHttpHeader::~BHttpHeader() noexcept
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
BHttpHeader&
|
||||
BHttpHeader::operator=(const BHttpHeader& other) = default;
|
||||
|
||||
|
||||
BHttpHeader&
|
||||
BHttpHeader::operator=(BHttpHeader&& other) noexcept = default;
|
||||
|
||||
|
||||
void
|
||||
BHttpHeader::SetName(std::string_view name)
|
||||
{
|
||||
fName = BHttpHeader::HeaderName(name);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BHttpHeader::SetValue(std::string_view value)
|
||||
{
|
||||
if (!validate_value_string(value))
|
||||
throw InvalidInput(__PRETTY_FUNCTION__, BString(value.data(), value.length()));
|
||||
fValue.SetTo(value.data(), value.length());
|
||||
}
|
||||
|
||||
|
||||
const BHttpHeader::HeaderName&
|
||||
BHttpHeader::Name() noexcept
|
||||
{
|
||||
return fName;
|
||||
}
|
||||
|
||||
|
||||
std::string_view
|
||||
BHttpHeader::Value() noexcept
|
||||
{
|
||||
return std::string_view(fValue.String());
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BHttpHeader::IsEmpty() noexcept
|
||||
{
|
||||
return fName.IsEmpty() || fValue.IsEmpty();
|
||||
}
|
@ -12,8 +12,11 @@ for architectureObject in [ MultiArchSubDirSetup ] {
|
||||
continue ;
|
||||
}
|
||||
|
||||
SubDirC++Flags -std=gnu++17 ;
|
||||
|
||||
StaticLibrary [ MultiArchDefaultGristFiles libnetservices2.a ] :
|
||||
ErrorsExt.cpp
|
||||
HttpHeaders.cpp
|
||||
HttpSession.cpp
|
||||
NetServicesMisc.cpp
|
||||
;
|
||||
|
91
src/tests/kits/net/netservices2/HttpProtocolTest.cpp
Normal file
91
src/tests/kits/net/netservices2/HttpProtocolTest.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2021 Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Niels Sascha Reedijk, niels.reedijk@gmail.com
|
||||
*/
|
||||
|
||||
#include "HttpProtocolTest.h"
|
||||
|
||||
#include <cppunit/TestAssert.h>
|
||||
#include <cppunit/TestCaller.h>
|
||||
#include <cppunit/TestSuite.h>
|
||||
|
||||
#include <HttpHeaders.h>
|
||||
|
||||
using BPrivate::Network::BHttpHeader;
|
||||
using BPrivate::Network::BHttpSession;
|
||||
|
||||
|
||||
HttpProtocolTest::HttpProtocolTest()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HttpProtocolTest::HttpHeaderTest()
|
||||
{
|
||||
using namespace std::literals;
|
||||
|
||||
// Header field name validation (ignore value validation)
|
||||
{
|
||||
try {
|
||||
auto validFieldName = "Content-Encoding"sv;
|
||||
auto header = BHttpHeader{validFieldName, ""sv};
|
||||
} catch (...) {
|
||||
CPPUNIT_FAIL("Unexpected exception when passing valid field name");
|
||||
}
|
||||
try {
|
||||
auto invalidFieldName = "Cóntênt_Éncõdìng";
|
||||
auto header = BHttpHeader{invalidFieldName, ""sv};
|
||||
CPPUNIT_FAIL("Creating a header with an invalid name did not raise an exception");
|
||||
} catch (const BHttpHeader::InvalidInput& e) {
|
||||
// success
|
||||
} catch (...) {
|
||||
CPPUNIT_FAIL("Unexpected exception when creating a header with an invalid name");
|
||||
}
|
||||
}
|
||||
// Header field value validation (ignore name validation)
|
||||
{
|
||||
try {
|
||||
auto validFieldValue = "VálìdF|êldValue"sv;
|
||||
auto header = BHttpHeader{""sv, validFieldValue};
|
||||
} catch (...) {
|
||||
CPPUNIT_FAIL("Unexpected exception when passing valid field value");
|
||||
}
|
||||
try {
|
||||
auto invalidFieldValue = "Invalid\tField\0Value";
|
||||
auto header = BHttpHeader{""sv, invalidFieldValue};
|
||||
CPPUNIT_FAIL("Creating a header with an invalid value did not raise an exception");
|
||||
} catch (const BHttpHeader::InvalidInput& e) {
|
||||
// success
|
||||
} catch (...) {
|
||||
CPPUNIT_FAIL("Unexpected exception when creating a header with an invalid value");
|
||||
}
|
||||
}
|
||||
|
||||
// Header field name case insensitive comparison
|
||||
{
|
||||
BHttpHeader header = BHttpHeader{"content-type"sv, ""sv};
|
||||
CPPUNIT_ASSERT(header.Name() == "content-type"sv);
|
||||
CPPUNIT_ASSERT(header.Name() == "Content-Type"sv);
|
||||
CPPUNIT_ASSERT(header.Name() == "cOnTeNt-TyPe"sv);
|
||||
CPPUNIT_ASSERT(header.Name() != "content_type"sv);
|
||||
CPPUNIT_ASSERT(header.Name() == BString{"Content-Type"});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* static */ void
|
||||
HttpProtocolTest::AddTests(BTestSuite& parent)
|
||||
{
|
||||
CppUnit::TestSuite& suite = *new CppUnit::TestSuite("HttpProtocolTest");
|
||||
|
||||
suite.addTest(new CppUnit::TestCaller<HttpProtocolTest>(
|
||||
"HttpProtocolTest::HttpHeaderTest", &HttpProtocolTest::HttpHeaderTest));
|
||||
|
||||
// leak for now
|
||||
parent.addTest("HttpProtocolTest", &suite);
|
||||
}
|
@ -13,9 +13,11 @@
|
||||
using BPrivate::Network::BHttpSession;
|
||||
|
||||
|
||||
class HttpTest: public BTestCase {
|
||||
class HttpProtocolTest: public BTestCase {
|
||||
public:
|
||||
HttpTest(BHttpSession& session);
|
||||
HttpProtocolTest();
|
||||
|
||||
void HttpHeaderTest();
|
||||
|
||||
static void AddTests(BTestSuite& suite);
|
||||
|
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021 Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Niels Sascha Reedijk, niels.reedijk@gmail.com
|
||||
*/
|
||||
|
||||
#include "HttpTest.h"
|
||||
|
||||
#include <cppunit/TestSuite.h>
|
||||
|
||||
using BPrivate::Network::BHttpSession;
|
||||
|
||||
|
||||
HttpTest::HttpTest(BHttpSession& session)
|
||||
:fSession(session)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* static */ void
|
||||
HttpTest::AddTests(BTestSuite& parent)
|
||||
{
|
||||
CppUnit::TestSuite& suite = *new CppUnit::TestSuite("HttpTest");
|
||||
|
||||
BHttpSession session;
|
||||
|
||||
HttpTest* httpTest = new HttpTest(session);
|
||||
// leak for now
|
||||
parent.addTest("HttpTest", &suite);
|
||||
}
|
@ -4,10 +4,12 @@ if $(TARGET_PACKAGING_ARCH) != x86_gcc2 {
|
||||
# do not target the legacy platform
|
||||
UsePrivateHeaders netservices2 ;
|
||||
|
||||
SubDirC++Flags -std=gnu++17 ;
|
||||
|
||||
UnitTestLib netservicekit2test.so :
|
||||
ServicesKitTestAddon.cpp
|
||||
|
||||
HttpTest.cpp
|
||||
HttpProtocolTest.cpp
|
||||
|
||||
: be libnetservices2.a $(TARGET_NETWORK_LIBS) $(HAIKU_NETAPI_LIB)
|
||||
[ TargetLibstdc++ ]
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include <TestSuite.h>
|
||||
#include <TestSuiteAddon.h>
|
||||
|
||||
#include "HttpTest.h"
|
||||
#include "HttpProtocolTest.h"
|
||||
|
||||
|
||||
BTestSuite*
|
||||
@ -15,7 +15,7 @@ getTestSuite()
|
||||
{
|
||||
BTestSuite* suite = new BTestSuite("NetServices2Kit");
|
||||
|
||||
HttpTest::AddTests(*suite);
|
||||
HttpProtocolTest::AddTests(*suite);
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user