src/message_base.cpp

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