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_base.hpp>
13 :
14 : #include <cstring>
15 :
16 : namespace boost {
17 : namespace http_proto {
18 :
19 : void
20 20 : request_base::
21 : set_expect_100_continue(bool b)
22 : {
23 20 : if(h_.md.expect.count == 0)
24 : {
25 6 : BOOST_ASSERT(
26 : ! h_.md.expect.ec.failed());
27 6 : BOOST_ASSERT(
28 : ! h_.md.expect.is_100_continue);
29 6 : if( b )
30 : {
31 4 : append(
32 : field::expect,
33 : "100-continue");
34 4 : return;
35 : }
36 2 : return;
37 : }
38 :
39 14 : if(h_.md.expect.count == 1)
40 : {
41 6 : if(b)
42 : {
43 4 : if(! h_.md.expect.ec.failed())
44 : {
45 2 : BOOST_ASSERT(
46 : h_.md.expect.is_100_continue);
47 2 : return;
48 : }
49 2 : BOOST_ASSERT(
50 : ! h_.md.expect.is_100_continue);
51 2 : auto it = find(field::expect);
52 2 : BOOST_ASSERT(it != end());
53 2 : set(it, "100-continue");
54 2 : return;
55 : }
56 :
57 2 : auto it = find(field::expect);
58 2 : BOOST_ASSERT(it != end());
59 2 : erase(it);
60 2 : return;
61 : }
62 :
63 8 : BOOST_ASSERT(h_.md.expect.ec.failed());
64 :
65 8 : auto nc = (b ? 1 : 0);
66 8 : auto ne = h_.md.expect.count - nc;
67 8 : if( b )
68 6 : set(find(field::expect), "100-continue");
69 :
70 8 : raw_erase_n(field::expect, ne);
71 8 : h_.md.expect.count = nc;
72 8 : h_.md.expect.ec = {};
73 8 : h_.md.expect.is_100_continue = b;
74 : }
75 :
76 : //------------------------------------------------
77 :
78 : void
79 34 : request_base::
80 : set_start_line_impl(
81 : http_proto::method m,
82 : core::string_view ms,
83 : core::string_view t,
84 : http_proto::version v)
85 : {
86 : // TODO: check validity
87 34 : auto const vs = to_string(v);
88 : auto const new_prefix =
89 34 : ms.size() + 1 + // method SP
90 34 : t.size() + 1 + // request-target SP
91 34 : vs.size() + 2; // HTTP-version CRLF
92 :
93 : // Introduce a new scope so that prefix_op's
94 : // destructor runs before h_.on_start_line().
95 : {
96 : auto op = prefix_op_t(
97 34 : *this, new_prefix, &ms, &t);
98 :
99 32 : h_.version = v;
100 32 : h_.req.method = m;
101 32 : h_.req.method_len = static_cast<
102 32 : offset_type>(ms.size());
103 32 : h_.req.target_len = static_cast<
104 32 : offset_type>(t.size());
105 :
106 32 : char* m_dest = h_.buf;
107 32 : char* t_dest = h_.buf + ms.size() + 1;
108 32 : char* v_dest = t_dest + t.size() + 1;
109 :
110 32 : std::memmove(t_dest, t.data(), t.size());
111 32 : t_dest[t.size()] = ' ';
112 :
113 : // memmove after target because could overlap
114 32 : std::memmove(m_dest, ms.data(), ms.size());
115 32 : m_dest[ms.size()] = ' ';
116 :
117 32 : std::memcpy(v_dest, vs.data(), vs.size());
118 32 : v_dest[vs.size() + 0] = '\r';
119 32 : v_dest[vs.size() + 1] = '\n';
120 32 : }
121 :
122 32 : h_.on_start_line();
123 32 : }
124 :
125 : } // http_proto
126 : } // boost
|