94.67% Lines (71/75) 100.00% Functions (5/5)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com) 2   // Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com)
3   // Copyright (c) 2024 Christian Mazakas 3   // Copyright (c) 2024 Christian Mazakas
4   // 4   //
5   // Distributed under the Boost Software License, Version 1.0. (See accompanying 5   // Distributed under the Boost Software License, Version 1.0. (See accompanying
6   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7   // 7   //
8   // Official repository: https://github.com/cppalliance/http 8   // Official repository: https://github.com/cppalliance/http
9   // 9   //
10   10  
11   #include <boost/http/message_base.hpp> 11   #include <boost/http/message_base.hpp>
12   #include <boost/http/rfc/list_rule.hpp> 12   #include <boost/http/rfc/list_rule.hpp>
13   #include <boost/http/rfc/token_rule.hpp> 13   #include <boost/http/rfc/token_rule.hpp>
14   #include <boost/http/detail/except.hpp> 14   #include <boost/http/detail/except.hpp>
15   #include "detail/number_string.hpp" 15   #include "detail/number_string.hpp"
16   #include <boost/url/grammar/parse.hpp> 16   #include <boost/url/grammar/parse.hpp>
17   #include <boost/url/grammar/ci_string.hpp> 17   #include <boost/url/grammar/ci_string.hpp>
18   18  
19   namespace boost { 19   namespace boost {
20   namespace http { 20   namespace http {
21   21  
22   void 22   void
HITCBC 23   37 message_base:: 23   37 message_base::
24   set_payload_size( 24   set_payload_size(
25   std::uint64_t n) 25   std::uint64_t n)
26   { 26   {
27   //if(! is_head_response()) 27   //if(! is_head_response())
28   if(true) 28   if(true)
29   { 29   {
30   // comes first for exception safety 30   // comes first for exception safety
HITCBC 31   37 set_content_length(n); 31   37 set_content_length(n);
32   32  
HITCBC 33   37 set_chunked(false); 33   37 set_chunked(false);
34   } 34   }
35   else 35   else
36   { 36   {
37   // VFALCO ? 37   // VFALCO ?
38   } 38   }
HITCBC 39   37 } 39   37 }
40   40  
41   void 41   void
HITCBC 42   37 message_base:: 42   37 message_base::
43   set_content_length( 43   set_content_length(
44   std::uint64_t n) 44   std::uint64_t n)
45   { 45   {
HITCBC 46   37 set(field::content_length, 46   37 set(field::content_length,
HITCBC 47   37 detail::number_string(n)); 47   37 detail::number_string(n));
HITCBC 48   37 } 48   37 }
49   49  
50   void 50   void
HITCBC 51   70 message_base:: 51   70 message_base::
52   set_chunked(bool value) 52   set_chunked(bool value)
53   { 53   {
HITCBC 54   70 if(value) 54   70 if(value)
55   { 55   {
56   // set chunked 56   // set chunked
HITCBC 57   33 if(! h_.md.transfer_encoding.is_chunked ) 57   33 if(! h_.md.transfer_encoding.is_chunked )
58   { 58   {
HITCBC 59   33 append( 59   33 append(
60   field::transfer_encoding, 60   field::transfer_encoding,
61   "chunked"); 61   "chunked");
HITCBC 62   33 return; 62   33 return;
63   } 63   }
64   } 64   }
65   else 65   else
66   { 66   {
67   // clear chunked 67   // clear chunked
68   // VFALCO ? 68   // VFALCO ?
69   } 69   }
70   } 70   }
71   71  
72   void 72   void
HITCBC 73   13 message_base:: 73   13 message_base::
74   set_keep_alive(bool value) 74   set_keep_alive(bool value)
75   { 75   {
HITCBC 76   13 if(h_.md.connection.ec) 76   13 if(h_.md.connection.ec)
77   { 77   {
78   // throw? return false? 78   // throw? return false?
HITCBC 79   6 return; 79   6 return;
80   } 80   }
81   81  
HITCBC 82   13 if(h_.md.connection.count == 0) 82   13 if(h_.md.connection.count == 0)
83   { 83   {
84   // no Connection field 84   // no Connection field
HITCBC 85   6 switch(h_.version) 85   6 switch(h_.version)
86   { 86   {
HITCBC 87   4 default: 87   4 default:
88   case http::version::http_1_1: 88   case http::version::http_1_1:
HITCBC 89   4 if(! value) 89   4 if(! value)
HITCBC 90   3 set(field::connection, "close"); 90   3 set(field::connection, "close");
HITCBC 91   4 break; 91   4 break;
92   92  
HITCBC 93   2 case http::version::http_1_0: 93   2 case http::version::http_1_0:
HITCBC 94   2 if(value) 94   2 if(value)
HITCBC 95   1 set(field::connection, "keep-alive"); 95   1 set(field::connection, "keep-alive");
HITCBC 96   2 break; 96   2 break;
97   } 97   }
HITCBC 98   6 return; 98   6 return;
99   } 99   }
100   100  
101   // VFALCO TODO iterate in reverse order, 101   // VFALCO TODO iterate in reverse order,
102   // and cache the last iterator to use 102   // and cache the last iterator to use
103   // for appending 103   // for appending
104   104  
105   // one or more Connection fields 105   // one or more Connection fields
HITCBC 106   7 auto it = begin(); 106   7 auto it = begin();
107   auto const erase_token = 107   auto const erase_token =
HITCBC 108   6 [&](core::string_view token) 108   6 [&](core::string_view token)
109   { 109   {
HITCBC 110   14 while(it != end()) 110   14 while(it != end())
111   { 111   {
HITCBC 112   8 if(it->id != field::connection) 112   8 if(it->id != field::connection)
113   { 113   {
MISUBC 114   ++it; 114   ++it;
HITCBC 115   4 continue; 115   4 continue;
116   } 116   }
117   auto rv = grammar::parse( 117   auto rv = grammar::parse(
HITCBC 118   8 it->value, 118   8 it->value,
HITCBC 119   16 list_rule(token_rule, 1)); 119   16 list_rule(token_rule, 1));
HITCBC 120   8 BOOST_ASSERT(! rv.has_error()); 120   8 BOOST_ASSERT(! rv.has_error());
HITCBC 121   8 BOOST_ASSERT(! rv->empty()); 121   8 BOOST_ASSERT(! rv->empty());
HITCBC 122   8 auto itv = rv->begin(); 122   8 auto itv = rv->begin();
HITCBC 123   8 if(urls::grammar::ci_is_equal( 123   8 if(urls::grammar::ci_is_equal(
HITCBC 124   8 *itv, token)) 124   8 *itv, token))
125   { 125   {
HITCBC 126   4 if(rv->size() == 1) 126   4 if(rv->size() == 1)
127   { 127   {
128   // only one token 128   // only one token
HITCBC 129   3 it = erase(it); 129   3 it = erase(it);
130   } 130   }
131   else 131   else
132   { 132   {
133   // first token matches 133   // first token matches
HITCBC 134   1 ++itv; 134   1 ++itv;
HITCBC 135   1 set(it, 135   1 set(it,
HITCBC 136   1 it->value.substr( 136   1 it->value.substr(
HITCBC 137   2 (*itv).data() - 137   2 (*itv).data() -
HITCBC 138   1 it->value.data())); 138   1 it->value.data()));
HITCBC 139   1 ++it; 139   1 ++it;
140   } 140   }
HITCBC 141   4 continue; 141   4 continue;
142   } 142   }
143   // search remaining tokens 143   // search remaining tokens
HITCBC 144   4 std::string s = *itv++; 144   4 std::string s = *itv++;
HITCBC 145   7 while(itv != rv->end()) 145   7 while(itv != rv->end())
146   { 146   {
HITCBC 147   3 if(! urls::grammar::ci_is_equal( 147   3 if(! urls::grammar::ci_is_equal(
HITCBC 148   3 *itv, token)) 148   3 *itv, token))
HITCBC 149   2 s += ", " + std::string(*itv); 149   2 s += ", " + std::string(*itv);
HITCBC 150   3 ++itv; 150   3 ++itv;
151   } 151   }
HITCBC 152   4 set(it, s); 152   4 set(it, s);
HITCBC 153   4 ++it; 153   4 ++it;
HITCBC 154   8 } 154   8 }
HITCBC 155   6 }; 155   6 };
HITCBC 156   7 if(value) 156   7 if(value)
157   { 157   {
HITCBC 158   6 if(h_.md.connection.close) 158   6 if(h_.md.connection.close)
HITCBC 159   5 erase_token("close"); 159   5 erase_token("close");
160   } 160   }
161   else 161   else
162   { 162   {
HITCBC 163   1 if(h_.md.connection.keep_alive) 163   1 if(h_.md.connection.keep_alive)
HITCBC 164   1 erase_token("keep-alive"); 164   1 erase_token("keep-alive");
165   } 165   }
HITCBC 166   7 switch(h_.version) 166   7 switch(h_.version)
167   { 167   {
HITCBC 168   5 default: 168   5 default:
169   case http::version::http_1_1: 169   case http::version::http_1_1:
HITCBC 170   5 if(! value) 170   5 if(! value)
171   { 171   {
172   // add one "close" token if needed 172   // add one "close" token if needed
MISUBC 173   if(! h_.md.connection.close) 173   if(! h_.md.connection.close)
MISUBC 174   append(field::connection, "close"); 174   append(field::connection, "close");
175   } 175   }
HITCBC 176   5 break; 176   5 break;
177   177  
HITCBC 178   2 case http::version::http_1_0: 178   2 case http::version::http_1_0:
HITCBC 179   2 if(value) 179   2 if(value)
180   { 180   {
181   // add one "keep-alive" token if needed 181   // add one "keep-alive" token if needed
HITCBC 182   1 if(! h_.md.connection.keep_alive) 182   1 if(! h_.md.connection.keep_alive)
MISUBC 183   append(field::connection, "keep-alive"); 183   append(field::connection, "keep-alive");
184   } 184   }
HITCBC 185   2 break; 185   2 break;
186   } 186   }
187   } 187   }
188   188  
189   } // http 189   } // http
190   } // boost 190   } // boost