Line data Source code
1 : //
2 : // Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com)
3 : // Copyright (c) 2024 Christian Mazakas
4 : // Copyright (c) 2025 Mohammad Nejati
5 : //
6 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
7 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 : //
9 : // Official repository: https://github.com/cppalliance/http_proto
10 : //
11 :
12 : #include <boost/http_proto/request.hpp>
13 :
14 : #include <cstring>
15 :
16 : namespace boost {
17 : namespace http_proto {
18 :
19 : void
20 10 : request::
21 : set_expect_100_continue(bool b)
22 : {
23 10 : clone_if_needed();
24 :
25 10 : if(h_.md.expect.count == 0)
26 : {
27 3 : BOOST_ASSERT(
28 : ! h_.md.expect.ec.failed());
29 3 : BOOST_ASSERT(
30 : ! h_.md.expect.is_100_continue);
31 3 : if( b )
32 : {
33 2 : append(
34 : field::expect,
35 : "100-continue");
36 2 : return;
37 : }
38 1 : return;
39 : }
40 :
41 7 : if(h_.md.expect.count == 1)
42 : {
43 3 : if(b)
44 : {
45 2 : if(! h_.md.expect.ec.failed())
46 : {
47 1 : BOOST_ASSERT(
48 : h_.md.expect.is_100_continue);
49 1 : return;
50 : }
51 1 : BOOST_ASSERT(
52 : ! h_.md.expect.is_100_continue);
53 1 : auto it = find(field::expect);
54 1 : BOOST_ASSERT(it != end());
55 1 : set(it, "100-continue");
56 1 : return;
57 : }
58 :
59 1 : auto it = find(field::expect);
60 1 : BOOST_ASSERT(it != end());
61 1 : erase(it);
62 1 : return;
63 : }
64 :
65 4 : BOOST_ASSERT(h_.md.expect.ec.failed());
66 :
67 4 : auto nc = (b ? 1 : 0);
68 4 : auto ne = h_.md.expect.count - nc;
69 4 : if( b )
70 3 : set(find(field::expect), "100-continue");
71 :
72 4 : raw_erase_n(field::expect, ne);
73 4 : h_.md.expect.count = nc;
74 4 : h_.md.expect.ec = {};
75 4 : h_.md.expect.is_100_continue = b;
76 : }
77 :
78 : //------------------------------------------------
79 :
80 : void
81 16 : request::
82 : set_start_line_impl(
83 : http_proto::method m,
84 : core::string_view ms,
85 : core::string_view t,
86 : http_proto::version v)
87 : {
88 16 : clone_if_needed();
89 :
90 : // TODO: check validity
91 16 : auto const vs = to_string(v);
92 : auto const new_prefix =
93 16 : ms.size() + 1 + // method SP
94 16 : t.size() + 1 + // request-target SP
95 16 : vs.size() + 2; // HTTP-version CRLF
96 :
97 : // Introduce a new scope so that prefix_op's
98 : // destructor runs before h_.on_start_line().
99 : {
100 : auto op = prefix_op_t(
101 16 : *this, new_prefix, &ms, &t);
102 :
103 15 : h_.version = v;
104 15 : h_.req.method = m;
105 15 : h_.req.method_len = static_cast<
106 15 : offset_type>(ms.size());
107 15 : h_.req.target_len = static_cast<
108 15 : offset_type>(t.size());
109 :
110 15 : char* m_dest = h_.buf;
111 15 : char* t_dest = h_.buf + ms.size() + 1;
112 15 : char* v_dest = t_dest + t.size() + 1;
113 :
114 15 : std::memmove(t_dest, t.data(), t.size());
115 15 : t_dest[t.size()] = ' ';
116 :
117 : // memmove after target because could overlap
118 15 : std::memmove(m_dest, ms.data(), ms.size());
119 15 : m_dest[ms.size()] = ' ';
120 :
121 15 : std::memcpy(v_dest, vs.data(), vs.size());
122 15 : v_dest[vs.size() + 0] = '\r';
123 15 : v_dest[vs.size() + 1] = '\n';
124 15 : }
125 :
126 15 : h_.on_start_line();
127 15 : }
128 :
129 : } // http_proto
130 : } // boost
|