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