]>
Commit | Line | Data |
---|---|---|
b32b8144 FG |
1 | // |
2 | // Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com) | |
3 | // | |
4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
6 | // | |
7 | // Official repository: https://github.com/boostorg/beast | |
8 | // | |
9 | ||
10 | #ifndef BOOST_BEAST_HTTP_FIELDS_HPP | |
11 | #define BOOST_BEAST_HTTP_FIELDS_HPP | |
12 | ||
13 | #include <boost/beast/core/detail/config.hpp> | |
14 | #include <boost/beast/core/string_param.hpp> | |
15 | #include <boost/beast/core/string.hpp> | |
16 | #include <boost/beast/core/detail/allocator.hpp> | |
11fdf7f2 | 17 | #include <boost/beast/core/detail/empty_base_optimization.hpp> |
b32b8144 FG |
18 | #include <boost/beast/http/field.hpp> |
19 | #include <boost/asio/buffer.hpp> | |
20 | #include <boost/intrusive/list.hpp> | |
21 | #include <boost/intrusive/set.hpp> | |
22 | #include <boost/optional.hpp> | |
23 | #include <algorithm> | |
24 | #include <cctype> | |
25 | #include <cstring> | |
26 | #include <memory> | |
27 | #include <string> | |
28 | #include <type_traits> | |
29 | #include <utility> | |
30 | ||
31 | namespace boost { | |
32 | namespace beast { | |
33 | namespace http { | |
34 | ||
35 | /** A container for storing HTTP header fields. | |
36 | ||
37 | This container is designed to store the field value pairs that make | |
38 | up the fields and trailers in an HTTP message. Objects of this type | |
39 | are iterable, with each element holding the field name and field | |
40 | value. | |
41 | ||
42 | Field names are stored as-is, but comparisons are case-insensitive. | |
43 | The container behaves as a `std::multiset`; there will be a separate | |
44 | value for each occurrence of the same field name. When the container | |
45 | is iterated the fields are presented in the order of insertion, with | |
46 | fields having the same name following each other consecutively. | |
47 | ||
48 | Meets the requirements of @b Fields | |
49 | ||
50 | @tparam Allocator The allocator to use. This must meet the | |
51 | requirements of @b Allocator. | |
52 | */ | |
53 | template<class Allocator> | |
54 | class basic_fields | |
11fdf7f2 TL |
55 | #ifndef BOOST_BEAST_DOXYGEN |
56 | : private beast::detail::empty_base_optimization<Allocator> | |
57 | #endif | |
b32b8144 | 58 | { |
11fdf7f2 TL |
59 | // Fancy pointers are not supported |
60 | static_assert(std::is_pointer<typename | |
61 | std::allocator_traits<Allocator>::pointer>::value, | |
62 | "Allocator must use regular pointers"); | |
63 | ||
b32b8144 FG |
64 | friend class fields_test; // for `header` |
65 | ||
66 | static std::size_t constexpr max_static_buffer = 4096; | |
67 | ||
68 | using off_t = std::uint16_t; | |
69 | ||
70 | public: | |
71 | /// The type of allocator used. | |
72 | using allocator_type = Allocator; | |
73 | ||
74 | /// The type of element used to represent a field | |
75 | class value_type | |
76 | { | |
77 | friend class basic_fields; | |
78 | ||
79 | boost::asio::const_buffer | |
80 | buffer() const; | |
81 | ||
82 | value_type(field name, | |
83 | string_view sname, string_view value); | |
84 | ||
85 | boost::intrusive::list_member_hook< | |
86 | boost::intrusive::link_mode< | |
87 | boost::intrusive::normal_link>> | |
88 | list_hook_; | |
89 | boost::intrusive::set_member_hook< | |
90 | boost::intrusive::link_mode< | |
91 | boost::intrusive::normal_link>> | |
92 | set_hook_; | |
93 | off_t off_; | |
94 | off_t len_; | |
95 | field f_; | |
96 | ||
97 | public: | |
98 | /// Constructor (deleted) | |
99 | value_type(value_type const&) = delete; | |
100 | ||
101 | /// Assignment (deleted) | |
102 | value_type& operator=(value_type const&) = delete; | |
103 | ||
104 | /// Returns the field enum, which can be @ref field::unknown | |
11fdf7f2 | 105 | field |
b32b8144 FG |
106 | name() const; |
107 | ||
108 | /// Returns the field name as a string | |
109 | string_view const | |
110 | name_string() const; | |
111 | ||
112 | /// Returns the value of the field | |
113 | string_view const | |
114 | value() const; | |
115 | }; | |
116 | ||
117 | /** A strictly less predicate for comparing keys, using a case-insensitive comparison. | |
118 | ||
119 | The case-comparison operation is defined only for low-ASCII characters. | |
120 | */ | |
121 | struct key_compare : beast::iless | |
122 | { | |
123 | /// Returns `true` if lhs is less than rhs using a strict ordering | |
124 | template<class String> | |
125 | bool | |
126 | operator()( | |
127 | String const& lhs, | |
128 | value_type const& rhs) const noexcept | |
129 | { | |
130 | if(lhs.size() < rhs.name_string().size()) | |
131 | return true; | |
132 | if(lhs.size() > rhs.name_string().size()) | |
133 | return false; | |
134 | return iless::operator()(lhs, rhs.name_string()); | |
135 | } | |
136 | ||
137 | /// Returns `true` if lhs is less than rhs using a strict ordering | |
138 | template<class String> | |
139 | bool | |
140 | operator()( | |
141 | value_type const& lhs, | |
142 | String const& rhs) const noexcept | |
143 | { | |
144 | if(lhs.name_string().size() < rhs.size()) | |
145 | return true; | |
146 | if(lhs.name_string().size() > rhs.size()) | |
147 | return false; | |
148 | return iless::operator()(lhs.name_string(), rhs); | |
149 | } | |
150 | ||
151 | /// Returns `true` if lhs is less than rhs using a strict ordering | |
152 | bool | |
153 | operator()( | |
154 | value_type const& lhs, | |
155 | value_type const& rhs) const noexcept | |
156 | { | |
157 | if(lhs.name_string().size() < rhs.name_string().size()) | |
158 | return true; | |
159 | if(lhs.name_string().size() > rhs.name_string().size()) | |
160 | return false; | |
161 | return iless::operator()(lhs.name_string(), rhs.name_string()); | |
162 | } | |
163 | }; | |
164 | ||
165 | /// The algorithm used to serialize the header | |
166 | #if BOOST_BEAST_DOXYGEN | |
167 | using writer = implementation_defined; | |
168 | #else | |
169 | class writer; | |
170 | #endif | |
171 | ||
172 | private: | |
173 | using list_t = typename boost::intrusive::make_list< | |
174 | value_type, boost::intrusive::member_hook< | |
175 | value_type, boost::intrusive::list_member_hook< | |
176 | boost::intrusive::link_mode< | |
177 | boost::intrusive::normal_link>>, | |
178 | &value_type::list_hook_>, | |
179 | boost::intrusive::constant_time_size< | |
180 | false>>::type; | |
181 | ||
182 | using set_t = typename boost::intrusive::make_multiset< | |
183 | value_type, boost::intrusive::member_hook<value_type, | |
184 | boost::intrusive::set_member_hook< | |
185 | boost::intrusive::link_mode< | |
186 | boost::intrusive::normal_link>>, | |
187 | &value_type::set_hook_>, | |
188 | boost::intrusive::constant_time_size<true>, | |
189 | boost::intrusive::compare<key_compare>>::type; | |
190 | ||
11fdf7f2 TL |
191 | using align_type = typename |
192 | boost::type_with_alignment<alignof(value_type)>::type; | |
193 | ||
194 | using rebind_type = typename | |
195 | beast::detail::allocator_traits<Allocator>:: | |
196 | template rebind_alloc<align_type>; | |
197 | ||
198 | using alloc_traits = | |
199 | beast::detail::allocator_traits<rebind_type>; | |
200 | ||
201 | using size_type = typename | |
202 | beast::detail::allocator_traits<Allocator>::size_type; | |
203 | ||
b32b8144 FG |
204 | |
205 | public: | |
206 | /// Destructor | |
207 | ~basic_fields(); | |
208 | ||
209 | /// Constructor. | |
210 | basic_fields() = default; | |
211 | ||
212 | /** Constructor. | |
213 | ||
214 | @param alloc The allocator to use. | |
215 | */ | |
216 | explicit | |
11fdf7f2 | 217 | basic_fields(Allocator const& alloc) noexcept; |
b32b8144 FG |
218 | |
219 | /** Move constructor. | |
220 | ||
221 | The state of the moved-from object is | |
222 | as if constructed using the same allocator. | |
223 | */ | |
11fdf7f2 | 224 | basic_fields(basic_fields&&) noexcept; |
b32b8144 FG |
225 | |
226 | /** Move constructor. | |
227 | ||
228 | The state of the moved-from object is | |
229 | as if constructed using the same allocator. | |
230 | ||
231 | @param alloc The allocator to use. | |
232 | */ | |
233 | basic_fields(basic_fields&&, Allocator const& alloc); | |
234 | ||
235 | /// Copy constructor. | |
236 | basic_fields(basic_fields const&); | |
237 | ||
238 | /** Copy constructor. | |
239 | ||
240 | @param alloc The allocator to use. | |
241 | */ | |
242 | basic_fields(basic_fields const&, Allocator const& alloc); | |
243 | ||
244 | /// Copy constructor. | |
245 | template<class OtherAlloc> | |
246 | basic_fields(basic_fields<OtherAlloc> const&); | |
247 | ||
248 | /** Copy constructor. | |
249 | ||
250 | @param alloc The allocator to use. | |
251 | */ | |
252 | template<class OtherAlloc> | |
253 | basic_fields(basic_fields<OtherAlloc> const&, | |
254 | Allocator const& alloc); | |
255 | ||
256 | /** Move assignment. | |
257 | ||
258 | The state of the moved-from object is | |
259 | as if constructed using the same allocator. | |
260 | */ | |
11fdf7f2 TL |
261 | basic_fields& operator=(basic_fields&&) noexcept( |
262 | alloc_traits::propagate_on_container_move_assignment::value); | |
b32b8144 FG |
263 | |
264 | /// Copy assignment. | |
265 | basic_fields& operator=(basic_fields const&); | |
266 | ||
267 | /// Copy assignment. | |
268 | template<class OtherAlloc> | |
269 | basic_fields& operator=(basic_fields<OtherAlloc> const&); | |
270 | ||
271 | public: | |
272 | /// A constant iterator to the field sequence. | |
273 | #if BOOST_BEAST_DOXYGEN | |
274 | using const_iterator = implementation_defined; | |
275 | #else | |
276 | using const_iterator = typename list_t::const_iterator; | |
277 | #endif | |
278 | ||
279 | /// A constant iterator to the field sequence. | |
280 | using iterator = const_iterator; | |
281 | ||
282 | /// Return a copy of the allocator associated with the container. | |
283 | allocator_type | |
284 | get_allocator() const | |
285 | { | |
11fdf7f2 | 286 | return this->member(); |
b32b8144 FG |
287 | } |
288 | ||
289 | //-------------------------------------------------------------------------- | |
290 | // | |
291 | // Element access | |
292 | // | |
293 | //-------------------------------------------------------------------------- | |
294 | ||
295 | /** Returns the value for a field, or throws an exception. | |
296 | ||
297 | If more than one field with the specified name exists, the | |
298 | first field defined by insertion order is returned. | |
299 | ||
300 | @param name The name of the field. | |
301 | ||
302 | @return The field value. | |
303 | ||
304 | @throws std::out_of_range if the field is not found. | |
305 | */ | |
306 | string_view const | |
307 | at(field name) const; | |
308 | ||
309 | /** Returns the value for a field, or throws an exception. | |
310 | ||
311 | If more than one field with the specified name exists, the | |
312 | first field defined by insertion order is returned. | |
313 | ||
314 | @param name The name of the field. | |
315 | ||
316 | @return The field value. | |
317 | ||
318 | @throws std::out_of_range if the field is not found. | |
319 | */ | |
320 | string_view const | |
321 | at(string_view name) const; | |
322 | ||
323 | /** Returns the value for a field, or `""` if it does not exist. | |
324 | ||
325 | If more than one field with the specified name exists, the | |
326 | first field defined by insertion order is returned. | |
327 | ||
328 | @param name The name of the field. | |
329 | */ | |
330 | string_view const | |
331 | operator[](field name) const; | |
332 | ||
333 | /** Returns the value for a case-insensitive matching header, or `""` if it does not exist. | |
334 | ||
335 | If more than one field with the specified name exists, the | |
336 | first field defined by insertion order is returned. | |
337 | ||
338 | @param name The name of the field. | |
339 | */ | |
340 | string_view const | |
341 | operator[](string_view name) const; | |
342 | ||
343 | //-------------------------------------------------------------------------- | |
344 | // | |
345 | // Iterators | |
346 | // | |
347 | //-------------------------------------------------------------------------- | |
348 | ||
349 | /// Return a const iterator to the beginning of the field sequence. | |
350 | const_iterator | |
351 | begin() const | |
352 | { | |
353 | return list_.cbegin(); | |
354 | } | |
355 | ||
356 | /// Return a const iterator to the end of the field sequence. | |
357 | const_iterator | |
358 | end() const | |
359 | { | |
360 | return list_.cend(); | |
361 | } | |
362 | ||
363 | /// Return a const iterator to the beginning of the field sequence. | |
364 | const_iterator | |
365 | cbegin() const | |
366 | { | |
367 | return list_.cbegin(); | |
368 | } | |
369 | ||
370 | /// Return a const iterator to the end of the field sequence. | |
371 | const_iterator | |
372 | cend() const | |
373 | { | |
374 | return list_.cend(); | |
375 | } | |
376 | ||
377 | //-------------------------------------------------------------------------- | |
378 | // | |
379 | // Capacity | |
380 | // | |
381 | //-------------------------------------------------------------------------- | |
382 | ||
383 | private: | |
384 | // VFALCO Since the header and message derive from Fields, | |
385 | // what does the expression m.empty() mean? Its confusing. | |
386 | bool | |
387 | empty() const | |
388 | { | |
389 | return list_.empty(); | |
390 | } | |
391 | public: | |
392 | ||
393 | //-------------------------------------------------------------------------- | |
394 | // | |
395 | // Modifiers | |
396 | // | |
397 | //-------------------------------------------------------------------------- | |
398 | ||
399 | /** Remove all fields from the container | |
400 | ||
401 | All references, pointers, or iterators referring to contained | |
402 | elements are invalidated. All past-the-end iterators are also | |
403 | invalidated. | |
404 | ||
405 | @par Postconditions: | |
406 | @code | |
407 | std::distance(this->begin(), this->end()) == 0 | |
408 | @endcode | |
409 | */ | |
410 | void | |
411 | clear(); | |
412 | ||
413 | /** Insert a field. | |
414 | ||
415 | If one or more fields with the same name already exist, | |
416 | the new field will be inserted after the last field with | |
417 | the matching name, in serialization order. | |
418 | ||
419 | @param name The field name. | |
420 | ||
421 | @param value The value of the field, as a @ref string_param | |
422 | */ | |
423 | void | |
424 | insert(field name, string_param const& value); | |
425 | ||
426 | /** Insert a field. | |
427 | ||
428 | If one or more fields with the same name already exist, | |
429 | the new field will be inserted after the last field with | |
430 | the matching name, in serialization order. | |
431 | ||
432 | @param name The field name. | |
433 | ||
434 | @param value The value of the field, as a @ref string_param | |
435 | */ | |
436 | void | |
437 | insert(string_view name, string_param const& value); | |
438 | ||
439 | /** Insert a field. | |
440 | ||
441 | If one or more fields with the same name already exist, | |
442 | the new field will be inserted after the last field with | |
443 | the matching name, in serialization order. | |
444 | ||
445 | @param name The field name. | |
446 | ||
447 | @param name_string The literal text corresponding to the | |
448 | field name. If `name != field::unknown`, then this value | |
449 | must be equal to `to_string(name)` using a case-insensitive | |
450 | comparison, otherwise the behavior is undefined. | |
451 | ||
452 | @param value The value of the field, as a @ref string_param | |
453 | */ | |
454 | void | |
455 | insert(field name, string_view name_string, | |
456 | string_param const& value); | |
457 | ||
458 | /** Set a field value, removing any other instances of that field. | |
459 | ||
460 | First removes any values with matching field names, then | |
461 | inserts the new field value. | |
462 | ||
463 | @param name The field name. | |
464 | ||
465 | @param value The value of the field, as a @ref string_param | |
466 | ||
467 | @return The field value. | |
468 | */ | |
469 | void | |
470 | set(field name, string_param const& value); | |
471 | ||
472 | /** Set a field value, removing any other instances of that field. | |
473 | ||
474 | First removes any values with matching field names, then | |
475 | inserts the new field value. | |
476 | ||
477 | @param name The field name. | |
478 | ||
479 | @param value The value of the field, as a @ref string_param | |
480 | */ | |
481 | void | |
482 | set(string_view name, string_param const& value); | |
483 | ||
484 | /** Remove a field. | |
485 | ||
486 | References and iterators to the erased elements are | |
487 | invalidated. Other references and iterators are not | |
488 | affected. | |
489 | ||
490 | @param pos An iterator to the element to remove. | |
491 | ||
492 | @return An iterator following the last removed element. | |
493 | If the iterator refers to the last element, the end() | |
494 | iterator is returned. | |
495 | */ | |
496 | const_iterator | |
497 | erase(const_iterator pos); | |
498 | ||
499 | /** Remove all fields with the specified name. | |
500 | ||
501 | All fields with the same field name are erased from the | |
502 | container. | |
503 | References and iterators to the erased elements are | |
504 | invalidated. Other references and iterators are not | |
505 | affected. | |
506 | ||
507 | @param name The field name. | |
508 | ||
509 | @return The number of fields removed. | |
510 | */ | |
511 | std::size_t | |
512 | erase(field name); | |
513 | ||
514 | /** Remove all fields with the specified name. | |
515 | ||
516 | All fields with the same field name are erased from the | |
517 | container. | |
518 | References and iterators to the erased elements are | |
519 | invalidated. Other references and iterators are not | |
520 | affected. | |
521 | ||
522 | @param name The field name. | |
523 | ||
524 | @return The number of fields removed. | |
525 | */ | |
526 | std::size_t | |
527 | erase(string_view name); | |
528 | ||
529 | /** Return a buffer sequence representing the trailers. | |
530 | ||
531 | This function returns a buffer sequence holding the | |
532 | serialized representation of the trailer fields promised | |
533 | in the Accept field. Before calling this function the | |
534 | Accept field must contain the exact trailer fields | |
535 | desired. Each field must also exist. | |
536 | */ | |
537 | ||
538 | ||
539 | /// Swap this container with another | |
540 | void | |
541 | swap(basic_fields& other); | |
542 | ||
543 | /// Swap two field containers | |
544 | template<class Alloc> | |
545 | friend | |
546 | void | |
547 | swap(basic_fields<Alloc>& lhs, basic_fields<Alloc>& rhs); | |
548 | ||
549 | //-------------------------------------------------------------------------- | |
550 | // | |
551 | // Lookup | |
552 | // | |
553 | //-------------------------------------------------------------------------- | |
554 | ||
555 | /** Return the number of fields with the specified name. | |
556 | ||
557 | @param name The field name. | |
558 | */ | |
559 | std::size_t | |
560 | count(field name) const; | |
561 | ||
562 | /** Return the number of fields with the specified name. | |
563 | ||
564 | @param name The field name. | |
565 | */ | |
566 | std::size_t | |
567 | count(string_view name) const; | |
568 | ||
569 | /** Returns an iterator to the case-insensitive matching field. | |
570 | ||
571 | If more than one field with the specified name exists, the | |
572 | first field defined by insertion order is returned. | |
573 | ||
574 | @param name The field name. | |
575 | ||
576 | @return An iterator to the matching field, or `end()` if | |
577 | no match was found. | |
578 | */ | |
579 | const_iterator | |
580 | find(field name) const; | |
581 | ||
582 | /** Returns an iterator to the case-insensitive matching field name. | |
583 | ||
584 | If more than one field with the specified name exists, the | |
585 | first field defined by insertion order is returned. | |
586 | ||
587 | @param name The field name. | |
588 | ||
589 | @return An iterator to the matching field, or `end()` if | |
590 | no match was found. | |
591 | */ | |
592 | const_iterator | |
593 | find(string_view name) const; | |
594 | ||
595 | /** Returns a range of iterators to the fields with the specified name. | |
596 | ||
597 | @param name The field name. | |
598 | ||
599 | @return A range of iterators to fields with the same name, | |
600 | otherwise an empty range. | |
601 | */ | |
602 | std::pair<const_iterator, const_iterator> | |
603 | equal_range(field name) const; | |
604 | ||
605 | /** Returns a range of iterators to the fields with the specified name. | |
606 | ||
607 | @param name The field name. | |
608 | ||
609 | @return A range of iterators to fields with the same name, | |
610 | otherwise an empty range. | |
611 | */ | |
612 | std::pair<const_iterator, const_iterator> | |
613 | equal_range(string_view name) const; | |
614 | ||
615 | //-------------------------------------------------------------------------- | |
616 | // | |
617 | // Observers | |
618 | // | |
619 | //-------------------------------------------------------------------------- | |
620 | ||
621 | /// Returns a copy of the key comparison function | |
622 | key_compare | |
623 | key_comp() const | |
624 | { | |
625 | return key_compare{}; | |
626 | } | |
627 | ||
628 | protected: | |
629 | /** Returns the request-method string. | |
630 | ||
631 | @note Only called for requests. | |
632 | */ | |
633 | string_view | |
634 | get_method_impl() const; | |
635 | ||
636 | /** Returns the request-target string. | |
637 | ||
638 | @note Only called for requests. | |
639 | */ | |
640 | string_view | |
641 | get_target_impl() const; | |
642 | ||
643 | /** Returns the response reason-phrase string. | |
644 | ||
645 | @note Only called for responses. | |
646 | */ | |
647 | string_view | |
648 | get_reason_impl() const; | |
649 | ||
650 | /** Returns the chunked Transfer-Encoding setting | |
651 | */ | |
652 | bool | |
653 | get_chunked_impl() const; | |
654 | ||
655 | /** Returns the keep-alive setting | |
656 | */ | |
657 | bool | |
658 | get_keep_alive_impl(unsigned version) const; | |
659 | ||
660 | /** Returns `true` if the Content-Length field is present. | |
661 | */ | |
662 | bool | |
663 | has_content_length_impl() const; | |
664 | ||
665 | /** Set or clear the method string. | |
666 | ||
667 | @note Only called for requests. | |
668 | */ | |
669 | void | |
670 | set_method_impl(string_view s); | |
671 | ||
672 | /** Set or clear the target string. | |
673 | ||
674 | @note Only called for requests. | |
675 | */ | |
676 | void | |
677 | set_target_impl(string_view s); | |
678 | ||
679 | /** Set or clear the reason string. | |
680 | ||
681 | @note Only called for responses. | |
682 | */ | |
683 | void | |
684 | set_reason_impl(string_view s); | |
685 | ||
686 | /** Adjusts the chunked Transfer-Encoding value | |
687 | */ | |
688 | void | |
689 | set_chunked_impl(bool value); | |
690 | ||
691 | /** Sets or clears the Content-Length field | |
692 | */ | |
693 | void | |
694 | set_content_length_impl( | |
695 | boost::optional<std::uint64_t> const& value); | |
696 | ||
697 | /** Adjusts the Connection field | |
698 | */ | |
699 | void | |
700 | set_keep_alive_impl( | |
701 | unsigned version, bool keep_alive); | |
702 | ||
703 | private: | |
704 | template<class OtherAlloc> | |
705 | friend class basic_fields; | |
706 | ||
b32b8144 FG |
707 | value_type& |
708 | new_element(field name, | |
709 | string_view sname, string_view value); | |
710 | ||
711 | void | |
712 | delete_element(value_type& e); | |
713 | ||
714 | void | |
715 | set_element(value_type& e); | |
716 | ||
717 | void | |
718 | realloc_string(string_view& dest, string_view s); | |
719 | ||
720 | void | |
721 | realloc_target( | |
722 | string_view& dest, string_view s); | |
723 | ||
724 | template<class OtherAlloc> | |
725 | void | |
726 | copy_all(basic_fields<OtherAlloc> const&); | |
727 | ||
728 | void | |
729 | clear_all(); | |
730 | ||
731 | void | |
732 | delete_list(); | |
733 | ||
734 | void | |
735 | move_assign(basic_fields&, std::true_type); | |
736 | ||
737 | void | |
738 | move_assign(basic_fields&, std::false_type); | |
739 | ||
740 | void | |
741 | copy_assign(basic_fields const&, std::true_type); | |
742 | ||
743 | void | |
744 | copy_assign(basic_fields const&, std::false_type); | |
745 | ||
746 | void | |
747 | swap(basic_fields& other, std::true_type); | |
748 | ||
749 | void | |
750 | swap(basic_fields& other, std::false_type); | |
751 | ||
b32b8144 FG |
752 | set_t set_; |
753 | list_t list_; | |
754 | string_view method_; | |
755 | string_view target_or_reason_; | |
756 | }; | |
757 | ||
758 | /// A typical HTTP header fields container | |
759 | using fields = basic_fields<std::allocator<char>>; | |
760 | ||
761 | } // http | |
762 | } // beast | |
763 | } // boost | |
764 | ||
765 | #include <boost/beast/http/impl/fields.ipp> | |
766 | ||
767 | #endif |