1/* 2 * Copyright 2022 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Niels Sascha Reedijk, niels.reedijk@gmail.com 7 * 8 * Corresponds to: 9 * headers/private/netservices2/HttpFields.h hrev????? 10 * src/kits/network/libnetservices2/HttpFields.cpp hrev????? 11 */ 12 13 14#if __cplusplus >= 201703L 15 16 17/*! 18 \file HttpFields.h 19 \ingroup netservices 20 \brief Provides the BHttpFields class. 21*/ 22 23namespace BPrivate { 24 25namespace Network { 26 27 28/*! 29 \class BHttpFields 30 \ingroup netservices 31 \brief Represents the field section of a HTTP header. 32 33 The HTTP protocol (RFC 7230) specifies that each HTTP request and response has a header. Part 34 of that header is a list of fields, which are name and value pairs. The high level protocol 35 defines what valid field names and field values look like. When adding or modifying field data, 36 the members of this class enforce those constraints. 37 38 When you are processing a HTTP response, this object gives you the methods to query the headers 39 in that response. When you are creating a HTTP request, this object gives you methods to add 40 and modify header fields on your request. When retrieving data from the header fields, this 41 data is often returned as an \c std::string_view. Please note that this object will only point 42 to valid data for the lifetime of this object, which in case of a HTTP response, will be 43 bound to the lifetime of the object that contains the HTTP response. 44 45 When adding headers, the fields are stored in the order in which they were added. However, 46 when you add additional values with an existing name, the new field will be added below the 47 existing field. 48 49 The HTTP protocol does not prohibit multiple fields with the same name, but it does note that 50 semantically this is only allowed for a limited set of explicitly named headers, like the 51 'Set-Cookie' field (see RFC 7230 section 3.2.2). Because most header fields will only exist 52 once, the interface of this class is optimized for each header field existing only once. The 53 onus is on the user to take additional steps when dealing with header fields that they know 54 can occur more than once. 55 56 \since Haiku R1 57*/ 58 59 60/*! 61 \class BHttpFields::InvalidInput 62 \ingroup netservices 63 \brief Error that represents when a string input contains characters that are incompatible with 64 the HTTP specification. 65 66 \since Haiku R1 67*/ 68 69 70/*! 71 \var BString BHttpFields::InvalidInput::input 72 \brief The input that contains the invalid contents. 73 74 \since Haiku R1 75*/ 76 77 78/*! 79 \fn BHttpFields::InvalidInput::InvalidInput(const char *origin, BString input) 80 \brief Constructor that sets the \a origin and the invalid \a input. 81 82 \since Haiku R1 83*/ 84 85 86/*! 87 \fn virtual BString BHttpFields::InvalidInput::DebugMessage() const override 88 \brief Retrieve a debug message that contains all info in this error. 89 90 The output will be along the lines of: 91 \code 92 [Origin] Invalid format or unsupported characters in input [input] 93 \endcode 94 95 \exception std::bad_alloc In the future this method may throw this 96 exception when the memory for the debug message cannot be allocated. 97 98 \return A \ref BString object that contains the debug message. 99 100 \since Haiku R1 101*/ 102 103 104/*! 105 \fn virtual const char* BHttpFields::InvalidInput::Message() const noexcept override 106 \brief Get a pointer to the message describing the error. 107 108 \since Haiku R1 109*/ 110 111 112/*! 113 \class BHttpFields::Field 114 \ingroup netservices 115 \brief Represents a HTTP header field. 116 117 This type represents a combination of a field name and a field value. In order to be used in 118 a HTTP header, each object must contain data that is in compliance with the HTTP specification 119 (RFC 7230). 120 121 Some official HTTP specifications give additional guidelines for how to interpret specific 122 fields. This class, however, does not supply any additional parsing for those specializations. 123 124 Manipulation of the contents of a HTTP field will in most cases be done through the interface 125 of the \ref BHttpFields object that owns this field. 126 127 This type has a special 'empty' state. This means that they do not have a key and value. Empty 128 objects only come into existence when explicitly instantiated with the constructor with no 129 arguments, or after the contents has been moved to another object. Empty objects cannot be 130 added to \ref BHttpFields objets. You do not have to check for empty fields when working with 131 fields coming from \ref BHttpFields objects. 132 133 \since Haiku R1 134*/ 135 136 137/*! 138 \fn BHttpFields::Field::Field() noexcept 139 \brief Construct empty field. 140 141 This constructs an empty field. Because empty fields cannot be used in combination with a 142 \ref BHttpFields object, it is unlikely that you will construct these empty fields yourself. 143 144 \since Haiku R1 145*/ 146 147 148/*! 149 \fn BHttpFields::Field::Field(const std::string_view& name, const std::string_view& value) 150 \brief Construct a field with a \a name and a \a value. 151 152 The parameters are checked whether they only contain characters that are allowed by the HTTP 153 specification. 154 155 \param name The name of the header field. 156 \param value The value of the header field. 157 158 \exception std::bad_alloc Error in case memory cannot be allocated. 159 \exception BHttpFields::InvalidInput This error indicates that the \a name or the \a value 160 is empty or contains invalid characters. 161 162 \since Haiku R1 163*/ 164 165 166/*! 167 \fn BHttpFields::Field::Field(const Field &other) 168 \brief Copy constructor. 169 170 \param other The other field to copy data from. 171 172 \exception std::bad_alloc Error in case memory cannot be allocated. 173 174 \since Haiku R1 175*/ 176 177 178/*! 179 \fn BHttpFields::Field::Field(Field&& other) noexcept 180 \brief Move constructor. 181 182 After moving, the \a other field object will be an empty field. 183 184 \since Haiku R1 185*/ 186 187 188/*! 189 \fn Field& BHttpFields::Field::operator=(const Field &other) 190 \brief Copy assignment. 191 192 \param other The other field to copy data from. 193 194 \exception std::bad_alloc Error in case memory cannot be allocated. 195 196 \since Haiku R1 197*/ 198 199 200/*! 201 \fn Field& BHttpFields::Field::operator=(Field &&other) noexcept 202 \brief Move assignment. 203 204 After moving, the \a other field object will be an empty field. 205 206 \since Haiku R1 207*/ 208 209 210/*! 211 \fn const FieldName& BHttpFields::Field::Name() const noexcept 212 \brief Get a const reference to the field name. 213 214 \return The name of the field as a \ref BHttpFields::FieldName. 215 216 \since Haiku R1 217*/ 218 219 220/*! 221 \fn std::string_view BHttpFields::Field::Value() const noexcept 222 \brief Get a const reference to the field value. 223 224 \return The contents of the field value as a \a std::string_view. 225 226 \since Haiku R1 227*/ 228 229 230/*! 231 \fn bool BHttpFields::Field::IsEmpty() const noexcept 232 \brief Check if the field is empty or has valid data. 233 234 \retval true This field is empty. 235 \retval false This field contains a valid name and value. 236 237 \since Haiku R1 238*/ 239 240 241/*! 242 \class BHttpFields::FieldName 243 \ingroup netservices 244 \brief Representation of a HTTP header name. 245 246 As per the HTTP specification, header fields have a name. There are limitations to which 247 characters are supported. As per the specification, header field names are case insensitive. 248 This means that the \c content-encoding is equal to \c Content-Encoding or even 249 \c COnTenT-ENcOdING. 250 251 A header field name can never be empty. 252 253 \since Haiku R1 254*/ 255 256 257/*! 258 \fn BHttpFields::FieldName::operator BString() const 259 \brief Return a copy of the header name as a string. 260 261 \return The header name as a \ref BString object. 262 263 \since Haiku R1 264*/ 265 266 267/*! 268 \fn BHttpFields::FieldName::operator std::string_view() const 269 \brief Return a \c std::string_view over the header name. 270 271 \return A \c std::string_view object over the header name. 272 273 \since Haiku R1 274*/ 275 276 277/*! 278 \fn bool BHttpFields::FieldName::operator==(const BString &other) const noexcept 279 \brief Compare the header name to a string. 280 281 \param other The \c other string to compare it to. 282 283 The comparison is case-insensitive. So if this header name is set to \c Content-Encoding, 284 comparing it to \c content-encoding will return \c true. 285 286 \retval true The current header name is equal to the \a other name. 287 \retval false The current header name is different from the \a other name. 288 289 \since Haiku R1 290*/ 291 292 293/*! 294 \fn bool BHttpFields::FieldName::operator==(const std::string_view& other) const noexcept 295 \copydoc BHttpFields::FieldName::operator==(const BString &other) const noexcept 296*/ 297 298 299/*! 300 \fn bool BHttpFields::FieldName::operator==(const BHttpFields::FieldName& other) const noexcept 301 \copydoc BHttpFields::FieldName::operator==(const BString &other) const noexcept 302*/ 303 304 305/*! 306 \typedef BHttpFields::ConstIterator 307 \brief Define a constant iterator to iterate through the list of header fields. 308 309 This iterator has the same semantics as other constant iterators in the C++ standard library. 310 311 \since Haiku R1 312*/ 313 314 315/*! 316 \name Constructors & Destructor 317*/ 318 319 320//! @{ 321 322 323/*! 324 \fn BHttpFields::BHttpFields() 325 \brief Construct an empty list of HTTP header fields. 326 327 \exception std::bad_alloc Error in case memory cannot be allocated. 328 329 \since Haiku R1 330*/ 331 332 333/*! 334 \fn BHttpFields::BHttpFields(std::initializer_list< Field > fields) 335 \brief Initialize the object with a list of fields. 336 337 This enables you to initialize the fields with a list of \ref BHttpFields::Field objects. Any 338 empty fields will be skipped. Like \ref AddField(), this constructor keeps the fields in the 339 original order, though duplicate keys will be grouped together in sequence. 340 341 The example below will create an object with four fields, even though five fields have been 342 passed in the initializer. The last header will be reorderd to follow the other 343 \c Accept-Encoding header. 344 \code 345 const BHttpFields defaultFields = { 346 {"Host"sv, "haiku-os.org"sv}, 347 {"Accept-Encoding"sv, "gzip"sv} 348 {"Accept"sv, "*\/*"sv}, 349 {}, 350 {"Accept-Encoding"sv, "bzip2"sv} 351 }; 352 \endcode 353 354 \exception std::bad_alloc Error in case memory cannot be allocated. 355 \exception BHttpFields::InvalidInput This error indicates that some of the names or values in 356 the list do not adhere to the HTTP specification. 357 358 \since Haiku R1 359*/ 360 361 362/*! 363 \fn BHttpFields::BHttpFields(const BHttpFields &other) 364 \brief Copy constructor. 365 366 \exception std::bad_alloc Error in case memory cannot be allocated. 367 368 \since Haiku R1 369*/ 370 371 372/*! 373 \fn BHttpFields::BHttpFields(BHttpFields &&other) 374 \brief Move constructor. 375 376 The name and value from the \a other fields object will be moved to this object. The \a other 377 object will be empty, meaning it no longer has any fields. 378 379 \exception std::bad_alloc Error in case memory cannot be allocated. 380 381 \since Haiku R1 382*/ 383 384 385/*! 386 \fn BHttpFields::~BHttpFields() noexcept 387 \brief Destructor. 388 389 \since Haiku R1 390*/ 391 392 393//! @} 394 395 396/*! 397 \name Assignment operators 398*/ 399 400 401//! @{ 402 403 404/*! 405 \fn BHttpFields& BHttpFields::operator=(BHttpFields &&other) noexcept 406 \brief Move assignment operator. 407 408 The name and value from the \a other fields object will be moved to this object. The \a other 409 object will be empty, meaning it no longer has any fields. 410 411 \since Haiku R1 412*/ 413 414 415/*! 416 \fn BHttpFields& BHttpFields::operator=(const BHttpFields &other) 417 \brief Copy assignment operator. 418 419 Make a new fields object with a copy of the fields of the \a other header. 420 421 \exception std::bad_alloc Error in case memory cannot be allocated. 422 423 \since Haiku R1 424*/ 425 426 427//! @} 428 429 430/*! 431 \name List Access 432*/ 433 434 435//! @{ 436 437/*! 438 \fn const Field& BHttpFields::operator[](size_t index) const 439 \brief Get the item at an \a index. 440 441 \param index The zero-based index of the item in the list of fields. 442 443 \return A const reference to the the field. 444 445 \exception BRuntimeError Error in case the index is out of bounds. 446 447 \since Haiku R1 448*/ 449 450 451//! @} 452 453 454/*! 455 \name Modifying the list 456*/ 457 458 459//! @{ 460 461/*! 462 \fn void BHttpFields::AddField(const std::string_view &name, const std::string_view &value) 463 \brief Append a field with \a name and a \a value to the list of headers. 464 465 The parameters are checked whether they only contain characters that are allowed by the HTTP 466 specification. 467 468 \param name The name of the header field. 469 \param value The value of the header field. 470 471 \exception std::bad_alloc Error in case memory cannot be allocated. 472 \exception BHttpFields::InvalidInput This error indicates that the \a name or the \a value 473 contains invalid characters. 474 475 \since Haiku R1 476*/ 477 478 479/*! 480 \fn void BHttpFields::AddFields(std::initializer_list< Field > fields) 481 \brief Add a list of fields. 482 483 This enables you to add a list of \ref BHttpFields::Field objects. Like \ref AddField(), the 484 fields are added in the the original order, though if there are duplicate keys within the 485 \a fields list, or there are existing keys in the object, they will be grouped together in 486 sequence. 487 488 \exception std::bad_alloc Error in case memory cannot be allocated. 489 \exception BHttpFields::InvalidInput This error indicates that some of the names or values in 490 the list do not adhere to the HTTP specification. 491 492 \since Haiku R1 493*/ 494 495 496/*! 497 \fn void BHttpFields::RemoveField(const std::string_view &name) noexcept 498 \brief Remove all fields with the \a name. 499 500 If there are no fields with this name, this method does nothing. Like all operations that 501 involve a field name, the name matching is case insensitive. 502 503 \param name The name of the field to remove. 504 505 \since Haiku R1 506*/ 507 508 509/*! 510 \fn void BHttpFields::RemoveField(ConstIterator it) noexcept 511 \brief Remove the specific field at the location of an iterator. 512 513 \param it A valid iterator to the item that must be removed. 514 515 \since Haiku R1 516*/ 517 518 519/*! 520 \fn void BHttpFields::MakeEmpty() noexcept 521 \brief Clear all fields from this header. 522 523 Removes all fields from the container. 524 525 \since Haiku R1 526*/ 527 528 529//! @} 530 531 532/*! 533 \name Querying 534*/ 535 536 537//! @{ 538 539 540/*! 541 \fn ConstIterator BHttpFields::FindField(const std::string_view &name) const noexcept 542 \brief Find a field with \a name. 543 544 In case there are more than one fields with the same name, this container will make sure that 545 these are grouped together. That means that you can use the properties of the iterator to find 546 the other fields. 547 548 \param name The name of the field to be found. 549 550 \return Returns a valid iterator to the first field with \a name in this container, or 551 BHttpFields::end() in case the name is not found. 552 553 \since Haiku R1 554*/ 555 556 557/*! 558 \fn size_t BHttpFields::CountFields() const noexcept 559 \brief Get the number of fields. 560 561 \return The number of fields in this container. If multiple fields have the same name, they 562 will be counted individually. 563 564 \since Haiku R1 565*/ 566 567 568//! @} 569 570 571/*! 572 \name Range-based iteration. 573 Allows the usage of this object in a for loop. 574*/ 575 576 577//! @{ 578 579/*! 580 \fn ConstIterator BHttpFields::begin() const noexcept 581 \brief Return an iterator to the first field. 582 583 \since Haiku R1 584*/ 585 586 587/*! 588 \fn ConstIterator BHttpFields::end() const noexcept 589 \brief Return an iterator to the end of the fields. 590 591 \since Haiku R1 592*/ 593 594 595//! @} 596 597 598} // namespace Network 599 600} // namespace BPrivate 601 602#endif 603