1// 2// Copyright (c) 2016-2019 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_IMPL_FIELDS_IPP 11#define BOOST_BEAST_HTTP_IMPL_FIELDS_IPP 12 13#include <boost/beast/http/fields.hpp> 14 15namespace boost { 16namespace beast { 17namespace http { 18namespace detail { 19 20// `basic_fields` assumes that `std::size_t` is larger than `uint16_t`, so we 21// verify it explicitly here, so that users that use split compilation don't 22// need to pay the (fairly small) price for this sanity check 23BOOST_STATIC_ASSERT((std::numeric_limits<std::size_t>::max)() >= 24 (std::numeric_limits<std::uint32_t>::max)()); 25 26// Filter a token list 27// 28inline 29void 30filter_token_list( 31 beast::detail::temporary_buffer& s, 32 string_view value, 33 iequals_predicate const& pred) 34{ 35 token_list te{value}; 36 auto it = te.begin(); 37 auto last = te.end(); 38 if(it == last) 39 return; 40 while(pred(*it)) 41 if(++it == last) 42 return; 43 s.append(*it); 44 while(++it != last) 45 { 46 if(! pred(*it)) 47 { 48 s.append(", ", *it); 49 } 50 } 51} 52 53void 54filter_token_list_last( 55 beast::detail::temporary_buffer& s, 56 string_view value, 57 iequals_predicate const& pred) 58{ 59 token_list te{value}; 60 if(te.begin() != te.end()) 61 { 62 auto it = te.begin(); 63 auto next = std::next(it); 64 if(next == te.end()) 65 { 66 if(! pred(*it)) 67 s.append(*it); 68 return; 69 } 70 s.append(*it); 71 for(;;) 72 { 73 it = next; 74 next = std::next(it); 75 if(next == te.end()) 76 { 77 if(! pred(*it)) 78 { 79 s.append(", ", *it); 80 } 81 return; 82 } 83 s.append(", ", *it); 84 } 85 } 86} 87 88void 89keep_alive_impl( 90 beast::detail::temporary_buffer& s, string_view value, 91 unsigned version, bool keep_alive) 92{ 93 if(version < 11) 94 { 95 if(keep_alive) 96 { 97 // remove close 98 filter_token_list(s, value, iequals_predicate{"close", {}}); 99 // add keep-alive 100 if(s.empty()) 101 s.append("keep-alive"); 102 else if(! token_list{value}.exists("keep-alive")) 103 s.append(", keep-alive"); 104 } 105 else 106 { 107 // remove close and keep-alive 108 filter_token_list(s, value, 109 iequals_predicate{"close", "keep-alive"}); 110 } 111 } 112 else 113 { 114 if(keep_alive) 115 { 116 // remove close and keep-alive 117 filter_token_list(s, value, 118 iequals_predicate{"close", "keep-alive"}); 119 } 120 else 121 { 122 // remove keep-alive 123 filter_token_list(s, value, iequals_predicate{"keep-alive", {}}); 124 // add close 125 if(s.empty()) 126 s.append("close"); 127 else if(! token_list{value}.exists("close")) 128 s.append(", close"); 129 } 130 } 131} 132 133} // detail 134} // http 135} // beast 136} // boost 137 138#endif // BOOST_BEAST_HTTP_IMPL_FIELDS_IPP 139