|
|
|||
File indexing completed on 2025-12-16 09:44:02
0001 // 0002 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) 0003 // 0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying 0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 0006 // 0007 // Official repository: https://github.com/boostorg/beast 0008 // 0009 0010 #ifndef BOOST_BEAST_HTTP_FIELDS_HPP 0011 #define BOOST_BEAST_HTTP_FIELDS_HPP 0012 0013 #include <boost/beast/http/fields_fwd.hpp> 0014 0015 #include <boost/beast/core/detail/allocator.hpp> 0016 #include <boost/beast/core/detail/config.hpp> 0017 #include <boost/beast/core/error.hpp> 0018 #include <boost/beast/core/string.hpp> 0019 #include <boost/beast/http/field.hpp> 0020 #include <boost/asio/buffer.hpp> 0021 #include <boost/core/empty_value.hpp> 0022 #include <boost/intrusive/list.hpp> 0023 #include <boost/intrusive/set.hpp> 0024 #include <boost/optional.hpp> 0025 #include <cctype> 0026 #include <cstring> 0027 #include <memory> 0028 #include <type_traits> 0029 #include <utility> 0030 0031 namespace boost { 0032 namespace beast { 0033 namespace http { 0034 0035 /** A container for storing HTTP header fields. 0036 0037 This container is designed to store the field value pairs that make 0038 up the fields and trailers in an HTTP message. Objects of this type 0039 are iterable, with each element holding the field name and field 0040 value. 0041 0042 Field names are stored as-is, but comparisons are case-insensitive. 0043 The container behaves as a `std::multiset`; there will be a separate 0044 value for each occurrence of the same field name. When the container 0045 is iterated the fields are presented in the order of insertion, with 0046 fields having the same name following each other consecutively. 0047 0048 Meets the requirements of <em>Fields</em> 0049 0050 @tparam Allocator The allocator to use. 0051 */ 0052 template<class Allocator> 0053 class basic_fields 0054 #if ! BOOST_BEAST_DOXYGEN 0055 : private boost::empty_value<Allocator> 0056 #endif 0057 { 0058 // Fancy pointers are not supported 0059 static_assert(std::is_pointer<typename 0060 std::allocator_traits<Allocator>::pointer>::value, 0061 "Allocator must use regular pointers"); 0062 0063 #ifndef BOOST_BEAST_DOXYGEN 0064 friend class fields_test; // for `header` 0065 #endif 0066 0067 struct element; 0068 0069 using off_t = std::uint16_t; 0070 0071 public: 0072 /// The type of allocator used. 0073 using allocator_type = Allocator; 0074 0075 /// The type of element used to represent a field 0076 class value_type 0077 { 0078 #ifndef BOOST_BEAST_DOXYGEN 0079 friend class basic_fields; 0080 #endif 0081 0082 off_t off_; 0083 off_t len_; 0084 field f_; 0085 0086 char* 0087 data() const; 0088 0089 net::const_buffer 0090 buffer() const; 0091 0092 protected: 0093 value_type(field name, 0094 string_view sname, string_view value); 0095 0096 public: 0097 /// Constructor (deleted) 0098 value_type(value_type const&) = delete; 0099 0100 /// Assignment (deleted) 0101 value_type& operator=(value_type const&) = delete; 0102 0103 /// Returns the field enum, which can be @ref boost::beast::http::field::unknown 0104 field 0105 name() const; 0106 0107 /// Returns the field name as a string 0108 string_view const 0109 name_string() const; 0110 0111 /// Returns the value of the field 0112 string_view const 0113 value() const; 0114 }; 0115 0116 /** A strictly less predicate for comparing keys, using a case-insensitive comparison. 0117 0118 The case-comparison operation is defined only for low-ASCII characters. 0119 */ 0120 #if BOOST_BEAST_DOXYGEN 0121 using key_compare = __implementation_defined__; 0122 #else 0123 struct key_compare : beast::iless 0124 #endif 0125 { 0126 /// Returns `true` if lhs is less than rhs using a strict ordering 0127 bool 0128 operator()( 0129 string_view lhs, 0130 value_type const& rhs) const noexcept 0131 { 0132 if(lhs.size() < rhs.name_string().size()) 0133 return true; 0134 if(lhs.size() > rhs.name_string().size()) 0135 return false; 0136 return iless::operator()(lhs, rhs.name_string()); 0137 } 0138 0139 /// Returns `true` if lhs is less than rhs using a strict ordering 0140 bool 0141 operator()( 0142 value_type const& lhs, 0143 string_view rhs) const noexcept 0144 { 0145 if(lhs.name_string().size() < rhs.size()) 0146 return true; 0147 if(lhs.name_string().size() > rhs.size()) 0148 return false; 0149 return iless::operator()(lhs.name_string(), rhs); 0150 } 0151 0152 /// Returns `true` if lhs is less than rhs using a strict ordering 0153 bool 0154 operator()( 0155 value_type const& lhs, 0156 value_type const& rhs) const noexcept 0157 { 0158 if(lhs.name_string().size() < rhs.name_string().size()) 0159 return true; 0160 if(lhs.name_string().size() > rhs.name_string().size()) 0161 return false; 0162 return iless::operator()(lhs.name_string(), rhs.name_string()); 0163 } 0164 }; 0165 0166 /// The algorithm used to serialize the header 0167 #if BOOST_BEAST_DOXYGEN 0168 using writer = __implementation_defined__; 0169 #else 0170 class writer; 0171 #endif 0172 0173 private: 0174 struct element 0175 : public boost::intrusive::list_base_hook< 0176 boost::intrusive::link_mode< 0177 boost::intrusive::normal_link>> 0178 , public boost::intrusive::set_base_hook< 0179 boost::intrusive::link_mode< 0180 boost::intrusive::normal_link>> 0181 , public value_type 0182 { 0183 element(field name, 0184 string_view sname, string_view value); 0185 }; 0186 0187 using list_t = typename boost::intrusive::make_list< 0188 element, 0189 boost::intrusive::constant_time_size<false> 0190 >::type; 0191 0192 using set_t = typename boost::intrusive::make_multiset< 0193 element, 0194 boost::intrusive::constant_time_size<false>, 0195 boost::intrusive::compare<key_compare> 0196 >::type; 0197 0198 using align_type = typename 0199 boost::type_with_alignment<alignof(element)>::type; 0200 0201 using rebind_type = typename 0202 beast::detail::allocator_traits<Allocator>:: 0203 template rebind_alloc<align_type>; 0204 0205 using alloc_traits = 0206 beast::detail::allocator_traits<rebind_type>; 0207 0208 using pocma = typename 0209 alloc_traits::propagate_on_container_move_assignment; 0210 0211 using pocca = typename 0212 alloc_traits::propagate_on_container_copy_assignment; 0213 0214 using pocs = typename 0215 alloc_traits::propagate_on_container_swap; 0216 0217 using size_type = typename 0218 beast::detail::allocator_traits<Allocator>::size_type; 0219 0220 0221 public: 0222 /// Maximum field name size 0223 static std::size_t constexpr max_name_size = 0224 (std::numeric_limits<std::uint16_t>::max)() - 2; 0225 0226 /// Maximum field value size 0227 static std::size_t constexpr max_value_size = 0228 (std::numeric_limits<std::uint16_t>::max)() - 2; 0229 0230 /// Destructor 0231 ~basic_fields(); 0232 0233 /// Constructor. 0234 basic_fields() = default; 0235 0236 /** Constructor. 0237 0238 @param alloc The allocator to use. 0239 */ 0240 explicit 0241 basic_fields(Allocator const& alloc) noexcept; 0242 0243 /** Move constructor. 0244 0245 The state of the moved-from object is 0246 as if constructed using the same allocator. 0247 */ 0248 basic_fields(basic_fields&&) noexcept; 0249 0250 /** Move constructor. 0251 0252 The state of the moved-from object is 0253 as if constructed using the same allocator. 0254 0255 @param alloc The allocator to use. 0256 */ 0257 basic_fields(basic_fields&&, Allocator const& alloc); 0258 0259 /// Copy constructor. 0260 basic_fields(basic_fields const&); 0261 0262 /** Copy constructor. 0263 0264 @param alloc The allocator to use. 0265 */ 0266 basic_fields(basic_fields const&, Allocator const& alloc); 0267 0268 /// Copy constructor. 0269 template<class OtherAlloc> 0270 basic_fields(basic_fields<OtherAlloc> const&); 0271 0272 /** Copy constructor. 0273 0274 @param alloc The allocator to use. 0275 */ 0276 template<class OtherAlloc> 0277 basic_fields(basic_fields<OtherAlloc> const&, 0278 Allocator const& alloc); 0279 0280 /** Move assignment. 0281 0282 The state of the moved-from object is 0283 as if constructed using the same allocator. 0284 */ 0285 basic_fields& operator=(basic_fields&&) noexcept( 0286 pocma::value && std::is_nothrow_move_assignable<Allocator>::value); 0287 0288 /// Copy assignment. 0289 basic_fields& operator=(basic_fields const&); 0290 0291 /// Copy assignment. 0292 template<class OtherAlloc> 0293 basic_fields& operator=(basic_fields<OtherAlloc> const&); 0294 0295 public: 0296 /// A constant iterator to the field sequence. 0297 #if BOOST_BEAST_DOXYGEN 0298 using const_iterator = __implementation_defined__; 0299 #else 0300 using const_iterator = typename list_t::const_iterator; 0301 #endif 0302 0303 /// A constant iterator to the field sequence. 0304 using iterator = const_iterator; 0305 0306 /// Return a copy of the allocator associated with the container. 0307 allocator_type 0308 get_allocator() const 0309 { 0310 return this->get(); 0311 } 0312 0313 //-------------------------------------------------------------------------- 0314 // 0315 // Element access 0316 // 0317 //-------------------------------------------------------------------------- 0318 0319 /** Returns the value for a field, or throws an exception. 0320 0321 If more than one field with the specified name exists, the 0322 first field defined by insertion order is returned. 0323 0324 @param name The name of the field. 0325 0326 @return The field value. 0327 0328 @throws std::out_of_range if the field is not found. 0329 */ 0330 string_view const 0331 at(field name) const; 0332 0333 /** Returns the value for a field, or throws an exception. 0334 0335 If more than one field with the specified name exists, the 0336 first field defined by insertion order is returned. 0337 0338 @param name The name of the field. It is interpreted as a case-insensitive string. 0339 0340 @return The field value. 0341 0342 @throws std::out_of_range if the field is not found. 0343 */ 0344 string_view const 0345 at(string_view name) const; 0346 0347 /** Returns the value for a field, or `""` if it does not exist. 0348 0349 If more than one field with the specified name exists, the 0350 first field defined by insertion order is returned. 0351 0352 @param name The name of the field. 0353 */ 0354 string_view const 0355 operator[](field name) const; 0356 0357 /** Returns the value for a case-insensitive matching header, or `""` if it does not exist. 0358 0359 If more than one field with the specified name exists, the 0360 first field defined by insertion order is returned. 0361 0362 @param name The name of the field. It is interpreted as a case-insensitive string. 0363 */ 0364 string_view const 0365 operator[](string_view name) const; 0366 0367 //-------------------------------------------------------------------------- 0368 // 0369 // Iterators 0370 // 0371 //-------------------------------------------------------------------------- 0372 0373 /// Return a const iterator to the beginning of the field sequence. 0374 const_iterator 0375 begin() const 0376 { 0377 return list_.cbegin(); 0378 } 0379 0380 /// Return a const iterator to the end of the field sequence. 0381 const_iterator 0382 end() const 0383 { 0384 return list_.cend(); 0385 } 0386 0387 /// Return a const iterator to the beginning of the field sequence. 0388 const_iterator 0389 cbegin() const 0390 { 0391 return list_.cbegin(); 0392 } 0393 0394 /// Return a const iterator to the end of the field sequence. 0395 const_iterator 0396 cend() const 0397 { 0398 return list_.cend(); 0399 } 0400 0401 //-------------------------------------------------------------------------- 0402 // 0403 // Capacity 0404 // 0405 //-------------------------------------------------------------------------- 0406 0407 private: 0408 // VFALCO Since the header and message derive from Fields, 0409 // what does the expression m.empty() mean? Its confusing. 0410 bool 0411 empty() const 0412 { 0413 return list_.empty(); 0414 } 0415 public: 0416 0417 //-------------------------------------------------------------------------- 0418 // 0419 // Modifiers 0420 // 0421 //-------------------------------------------------------------------------- 0422 0423 /** Remove all fields from the container 0424 0425 All references, pointers, or iterators referring to contained 0426 elements are invalidated. All past-the-end iterators are also 0427 invalidated. 0428 0429 @par Postconditions: 0430 @code 0431 std::distance(this->begin(), this->end()) == 0 0432 @endcode 0433 */ 0434 void 0435 clear(); 0436 0437 /** Insert a field. 0438 0439 If one or more fields with the same name already exist, 0440 the new field will be inserted after the last field with 0441 the matching name, in serialization order. 0442 The value can be an empty string. 0443 0444 @param name The field name. 0445 0446 @param value The field value. 0447 0448 @throws boost::system::system_error Thrown if an error occurs: 0449 @li If the size of @c value exceeds @ref max_value_size, the 0450 error code will be @ref error::header_field_value_too_large. 0451 */ 0452 void 0453 insert(field name, string_view value); 0454 0455 void 0456 insert(field, std::nullptr_t) = delete; 0457 0458 /** Insert a field. 0459 0460 If one or more fields with the same name already exist, 0461 the new field will be inserted after the last field with 0462 the matching name, in serialization order. 0463 The value can be an empty string. 0464 0465 @param name The field name. It is interpreted as a case-insensitive string. 0466 0467 @param value The field value. 0468 0469 @throws boost::system::system_error Thrown if an error occurs: 0470 @li If the size of @c name exceeds @ref max_name_size, the 0471 error code will be @ref error::header_field_name_too_large. 0472 @li If the size of @c value exceeds @ref max_value_size, the 0473 error code will be @ref error::header_field_value_too_large. 0474 */ 0475 void 0476 insert(string_view name, string_view value); 0477 0478 void 0479 insert(string_view, std::nullptr_t) = delete; 0480 0481 /** Insert a field. 0482 0483 If one or more fields with the same name already exist, 0484 the new field will be inserted after the last field with 0485 the matching name, in serialization order. 0486 The value can be an empty string. 0487 0488 @param name The field name. 0489 0490 @param name_string The literal text corresponding to the 0491 field name. If `name != field::unknown`, then this value 0492 must be equal to `to_string(name)` using a case-insensitive 0493 comparison, otherwise the behavior is undefined. 0494 0495 @param value The field value. 0496 0497 @throws boost::system::system_error Thrown if an error occurs: 0498 @li If the size of @c name_string exceeds @ref max_name_size, 0499 the error code will be @ref error::header_field_name_too_large. 0500 @li If the size of @c value exceeds @ref max_value_size, the 0501 error code will be @ref error::header_field_value_too_large. 0502 */ 0503 void 0504 insert(field name, string_view name_string, 0505 string_view value); 0506 0507 void 0508 insert(field, string_view, std::nullptr_t) = delete; 0509 0510 /** Insert a field. 0511 0512 If one or more fields with the same name already exist, 0513 the new field will be inserted after the last field with 0514 the matching name, in serialization order. 0515 The value can be an empty string. 0516 0517 @param name The field name. 0518 0519 @param name_string The literal text corresponding to the 0520 field name. If `name != field::unknown`, then this value 0521 must be equal to `to_string(name)` using a case-insensitive 0522 comparison, otherwise the behavior is undefined. 0523 0524 @param value The field value. 0525 0526 @param ec Set to indicate what error occurred: 0527 @li If the size of @c name_string exceeds @ref max_name_size, 0528 the error code will be @ref error::header_field_name_too_large. 0529 @li If the size of @c value exceeds @ref max_value_size, the 0530 error code will be @ref error::header_field_value_too_large. 0531 */ 0532 void 0533 insert(field name, string_view name_string, 0534 string_view value, error_code& ec); 0535 0536 void 0537 insert(field, string_view, std::nullptr_t, error_code& ec) = delete; 0538 0539 /** Set a field value, removing any other instances of that field. 0540 0541 First removes any values with matching field names, then 0542 inserts the new field value. The value may be an empty string. 0543 0544 @param name The field name. 0545 0546 @param value The field value. 0547 0548 @throws boost::system::system_error Thrown if an error occurs: 0549 @li If the size of @c value exceeds @ref max_value_size, the 0550 error code will be @ref error::header_field_value_too_large. 0551 */ 0552 void 0553 set(field name, string_view value); 0554 0555 void 0556 set(field, std::nullptr_t) = delete; 0557 0558 /** Set a field value, removing any other instances of that field. 0559 0560 First removes any values with matching field names, then 0561 inserts the new field value. The value can be an empty string. 0562 0563 @param name The field name. It is interpreted as a case-insensitive string. 0564 0565 @param value The field value. 0566 0567 @throws boost::system::system_error Thrown if an error occurs: 0568 @li If the size of @c name exceeds @ref max_name_size, the 0569 error code will be @ref error::header_field_name_too_large. 0570 @li If the size of @c value exceeds @ref max_value_size, the 0571 error code will be @ref error::header_field_value_too_large. 0572 */ 0573 void 0574 set(string_view name, string_view value); 0575 0576 void 0577 set(string_view, std::nullptr_t) = delete; 0578 0579 /** Remove a field. 0580 0581 References and iterators to the erased elements are 0582 invalidated. Other references and iterators are not 0583 affected. 0584 0585 @param pos An iterator to the element to remove. 0586 0587 @return An iterator following the last removed element. 0588 If the iterator refers to the last element, the end() 0589 iterator is returned. 0590 */ 0591 const_iterator 0592 erase(const_iterator pos); 0593 0594 /** Remove all fields with the specified name. 0595 0596 All fields with the same field name are erased from the 0597 container. 0598 References and iterators to the erased elements are 0599 invalidated. Other references and iterators are not 0600 affected. 0601 0602 @param name The field name. 0603 0604 @return The number of fields removed. 0605 */ 0606 std::size_t 0607 erase(field name); 0608 0609 /** Remove all fields with the specified name. 0610 0611 All fields with the same field name are erased from the 0612 container. 0613 References and iterators to the erased elements are 0614 invalidated. Other references and iterators are not 0615 affected. 0616 0617 @param name The field name. It is interpreted as a case-insensitive string. 0618 0619 @return The number of fields removed. 0620 */ 0621 std::size_t 0622 erase(string_view name); 0623 0624 /** Return a buffer sequence representing the trailers. 0625 0626 This function returns a buffer sequence holding the 0627 serialized representation of the trailer fields promised 0628 in the Accept field. Before calling this function the 0629 Accept field must contain the exact trailer fields 0630 desired. Each field must also exist. 0631 */ 0632 0633 0634 /// Swap this container with another 0635 void 0636 swap(basic_fields& other); 0637 0638 /// Swap two field containers 0639 template<class Alloc> 0640 friend 0641 void 0642 swap(basic_fields<Alloc>& lhs, basic_fields<Alloc>& rhs); 0643 0644 //-------------------------------------------------------------------------- 0645 // 0646 // Lookup 0647 // 0648 //-------------------------------------------------------------------------- 0649 0650 /** Return the number of fields with the specified name. 0651 0652 @param name The field name. 0653 */ 0654 std::size_t 0655 count(field name) const; 0656 0657 /** Return the number of fields with the specified name. 0658 0659 @param name The field name. It is interpreted as a case-insensitive string. 0660 */ 0661 std::size_t 0662 count(string_view name) const; 0663 0664 /** Returns an iterator to the case-insensitive matching field. 0665 0666 If more than one field with the specified name exists, the 0667 first field defined by insertion order is returned. 0668 0669 @param name The field name. 0670 0671 @return An iterator to the matching field, or `end()` if 0672 no match was found. 0673 */ 0674 const_iterator 0675 find(field name) const; 0676 0677 /** Returns an iterator to the case-insensitive matching field name. 0678 0679 If more than one field with the specified name exists, the 0680 first field defined by insertion order is returned. 0681 0682 @param name The field name. It is interpreted as a case-insensitive string. 0683 0684 @return An iterator to the matching field, or `end()` if 0685 no match was found. 0686 */ 0687 const_iterator 0688 find(string_view name) const; 0689 0690 /** Returns a range of iterators to the fields with the specified name. 0691 0692 This function returns the first and last iterators to the ordered 0693 fields with the specified name. 0694 0695 @note The fields represented by the range are ordered. Its elements 0696 are guaranteed to match the field ordering of the message. This 0697 means users do not need to sort this range when comparing fields 0698 of the same name in different messages. 0699 0700 @param name The field name. 0701 0702 @return A range of iterators to fields with the same name, 0703 otherwise an empty range. 0704 */ 0705 std::pair<const_iterator, const_iterator> 0706 equal_range(field name) const; 0707 0708 /// @copydoc boost::beast::http::basic_fields::equal_range(boost::beast::http::field) const 0709 std::pair<const_iterator, const_iterator> 0710 equal_range(string_view name) const; 0711 0712 //-------------------------------------------------------------------------- 0713 // 0714 // Observers 0715 // 0716 //-------------------------------------------------------------------------- 0717 0718 /// Returns a copy of the key comparison function 0719 key_compare 0720 key_comp() const 0721 { 0722 return key_compare{}; 0723 } 0724 0725 protected: 0726 /** Returns the request-method string. 0727 0728 @note Only called for requests. 0729 */ 0730 string_view 0731 get_method_impl() const; 0732 0733 /** Returns the request-target string. 0734 0735 @note Only called for requests. 0736 */ 0737 string_view 0738 get_target_impl() const; 0739 0740 /** Returns the response reason-phrase string. 0741 0742 @note Only called for responses. 0743 */ 0744 string_view 0745 get_reason_impl() const; 0746 0747 /** Returns the chunked Transfer-Encoding setting 0748 */ 0749 bool 0750 get_chunked_impl() const; 0751 0752 /** Returns the keep-alive setting 0753 */ 0754 bool 0755 get_keep_alive_impl(unsigned version) const; 0756 0757 /** Returns `true` if the Content-Length field is present. 0758 */ 0759 bool 0760 has_content_length_impl() const; 0761 0762 /** Set or clear the method string. 0763 0764 @note Only called for requests. 0765 */ 0766 void 0767 set_method_impl(string_view s); 0768 0769 /** Set or clear the target string. 0770 0771 @note Only called for requests. 0772 */ 0773 void 0774 set_target_impl(string_view s); 0775 0776 /** Set or clear the reason string. 0777 0778 @note Only called for responses. 0779 */ 0780 void 0781 set_reason_impl(string_view s); 0782 0783 /** Adjusts the chunked Transfer-Encoding value 0784 */ 0785 void 0786 set_chunked_impl(bool value); 0787 0788 /** Sets or clears the Content-Length field 0789 */ 0790 void 0791 set_content_length_impl( 0792 boost::optional<std::uint64_t> const& value); 0793 0794 /** Adjusts the Connection field 0795 */ 0796 void 0797 set_keep_alive_impl( 0798 unsigned version, bool keep_alive); 0799 0800 private: 0801 template<class OtherAlloc> 0802 friend class basic_fields; 0803 0804 element* 0805 try_create_new_element( 0806 field name, 0807 string_view sname, 0808 string_view value, 0809 error_code& ec); 0810 0811 element& 0812 new_element( 0813 field name, 0814 string_view sname, 0815 string_view value); 0816 0817 void 0818 insert_element(element& e); 0819 0820 void 0821 delete_element(element& e); 0822 0823 void 0824 set_element(element& e); 0825 0826 void 0827 realloc_string(string_view& dest, string_view s); 0828 0829 void 0830 realloc_target( 0831 string_view& dest, string_view s); 0832 0833 template<class OtherAlloc> 0834 void 0835 copy_all(basic_fields<OtherAlloc> const&); 0836 0837 void 0838 clear_all(); 0839 0840 void 0841 delete_list(); 0842 0843 void 0844 move_assign(basic_fields&, std::true_type); 0845 0846 void 0847 move_assign(basic_fields&, std::false_type); 0848 0849 void 0850 copy_assign(basic_fields const&, std::true_type); 0851 0852 void 0853 copy_assign(basic_fields const&, std::false_type); 0854 0855 void 0856 swap(basic_fields& other, std::true_type); 0857 0858 void 0859 swap(basic_fields& other, std::false_type); 0860 0861 set_t set_; 0862 list_t list_; 0863 string_view method_; 0864 string_view target_or_reason_; 0865 }; 0866 0867 #if BOOST_BEAST_DOXYGEN 0868 /// A typical HTTP header fields container 0869 using fields = basic_fields<std::allocator<char>>; 0870 #endif 0871 0872 } // http 0873 } // beast 0874 } // boost 0875 0876 #include <boost/beast/http/impl/fields.hpp> 0877 0878 #endif
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|