• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

libbitcoin / libbitcoin-server / 42675974756

09 Nov 2026 06:39PM UTC coverage: 95.065% (+0.1%) from 94.917%
42675974756

push

github

web-flow
Merge pull request #1133 from evoskuil/master

Check cpu extensions at startup, normalize http response path.

178 of 192 new or added lines in 10 files covered. (92.71%)

11983 of 12605 relevant lines covered (95.07%)

246.05 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.45
/src/protocols/protocol_http.cpp
1
/**
2
 * Copyright (c) 2011-2026 libbitcoin developers
3
 *
4
 * This file is part of libbitcoin.
5
 *
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU Affero General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU Affero General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Affero General Public License
17
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
 */
19
#include <bitcoin/server/protocols/protocol_http.hpp>
20

21
#include <bitcoin/server/define.hpp>
22

23
namespace libbitcoin {
24
namespace server {
25

26
#define CLASS protocol_http
27

28
using namespace network::http;
29
using namespace std::placeholders;
30

31
// Shared pointers required in handler parameters so closures control lifetime.
32
BC_PUSH_WARNING(NO_VALUE_OR_CONST_REF_SHARED_PTR)
33
BC_PUSH_WARNING(SMART_PTR_NOT_NEEDED)
34

35
// Websocket dispatch.
36
// ----------------------------------------------------------------------------
37

38
void protocol_http::handle_receive_websocket(const code& ec,
11,197 ✔
39
    const method::websocket::cptr& websocket) NOEXCEPT
40
{
41
    BC_ASSERT(stranded());
11,197 ✔
42

43
    if (stopped(ec))
11,197 ✔
44
        return;
45

46
    dispatch_websocket(*websocket);
1,791 ✔
47
}
48

49
void protocol_http::handle_receive_stream(const code& ec,
10,734 ✔
50
    const method::stream::cptr& stream) NOEXCEPT
51
{
52
    BC_ASSERT(stranded());
10,734 ✔
53

54
    if (stopped(ec))
10,734 ✔
55
        return;
56

57
    dispatch_websocket(*stream);
1,325 ✔
58
}
59

60
void protocol_http::dispatch_websocket(const request& ) NOEXCEPT
×
61
{
62
    BC_ASSERT(stranded());
×
63
    stop(error::not_implemented);
×
64
}
×
65

66
// Caching for http response abstraction.
67
// ----------------------------------------------------------------------------
68

69
// Cache request for serialization, keeping it out of dispatch.
70
void protocol_http::set_request(const request_cptr& request) NOEXCEPT
1,029 ✔
71
{
72
    ////BC_ASSERT(stranded());
73
    BC_ASSERT(request);
1,029 ✔
74
    request_ = request;
1,029 ✔
75
}
1,029 ✔
76

77
/// Returns default if not set, as ws frames and a tcp downgrade carry no http
78
// envelope (asserts correctness otherwise).
79
request_cptr protocol_http::reset_request() NOEXCEPT
1,844 ✔
80
{
81
    ////BC_ASSERT(stranded());
82
    BC_ASSERT(request_ || websocket() || downgraded());
1,844 ✔
83

84
    if (request_)
1,844 ✔
85
    {
86
        auto copy = request_;
1,016 ✔
87
        request_.reset();
1,016 ✔
88
        return copy;
1,016 ✔
89
    }
1,016 ✔
90

91
    return system::to_shared<request>();
828 ✔
92
}
93

94
const request_cptr& protocol_http::get_request() const NOEXCEPT
587 ✔
95
{
96
    ////BC_ASSERT(stranded());
97
    return request_;
587 ✔
98
}
99

100
response protocol_http::to_response(status status) NOEXCEPT
1,703 ✔
101
{
102
    BC_ASSERT(stranded());
1,703 ✔
103
    const auto request = reset_request();
1,703 ✔
104
    response message{ status, request->version() };
1,703 ✔
105
    add_common_headers(message, *request);
1,703 ✔
106
    add_access_control_headers(message, *request);
1,703 ✔
107
    return message;
1,703 ✔
108
}
1,703 ✔
109

110
// Senders.
111
// ----------------------------------------------------------------------------
112

113
void protocol_http::send_json(system::json::value&& model,
163 ✔
114
    size_t size_hint) NOEXCEPT
115
{
116
    BC_ASSERT(stranded());
163 ✔
117
    auto message = to_response(status::ok);
163 ✔
118
    message.set(field::content_type,
163 ✔
119
        from_media_type(media_type::application_json));
326 ✔
120
    message.body() = json_value
163 ✔
121
    {
122
        .model = std::move(model),
163 ✔
123
        .size_hint = size_hint
124
    };
163 ✔
125
    message.prepare_payload();
163 ✔
126
    SEND(std::move(message), handle_complete, _1, error::success);
163 ✔
127
}
163 ✔
128

129
void protocol_http::send_text(std::string&& text) NOEXCEPT
64 ✔
130
{
131
    BC_ASSERT(stranded());
64 ✔
132
    auto message = to_response(status::ok);
64 ✔
133
    message.set(field::content_type, from_media_type(media_type::text_plain));
64 ✔
134
    message.body() = std::move(text);
64 ✔
135
    message.prepare_payload();
64 ✔
136
    SEND(std::move(message), handle_complete, _1, error::success);
64 ✔
137
}
64 ✔
138

139
void protocol_http::send_chunk(system::data_chunk&& bytes) NOEXCEPT
52 ✔
140
{
141
    BC_ASSERT(stranded());
52 ✔
142
    auto message = to_response(status::ok);
52 ✔
143
    message.set(field::content_type,
52 ✔
144
        from_media_type(media_type::application_octet_stream));
104 ✔
145
    message.body() = std::move(bytes);
52 ✔
146
    message.prepare_payload();
52 ✔
147
    SEND(std::move(message), handle_complete, _1, error::success);
52 ✔
148
}
52 ✔
149

150
void protocol_http::send_file(file&& file, media_type type) NOEXCEPT
3 ✔
151
{
152
    BC_ASSERT(stranded());
3 ✔
153
    BC_ASSERT_MSG(file.is_open(), "sending closed file handle");
3 ✔
154
    auto message = to_response(status::ok);
3 ✔
155
    message.set(field::content_type, from_media_type(type));
3 ✔
156
    message.body() = std::move(file);
3 ✔
157
    message.prepare_payload();
3 ✔
158
    SEND(std::move(message), handle_complete, _1, error::success);
3 ✔
159
}
3 ✔
160

161
void protocol_http::send_span(span_body::value_type&& span,
5 ✔
162
    media_type type) NOEXCEPT
163
{
164
    BC_ASSERT(stranded());
5 ✔
165
    auto message = to_response(status::ok);
5 ✔
166
    message.set(field::content_type, from_media_type(type));
5 ✔
167
    message.body() = std::move(span);
5 ✔
168
    message.prepare_payload();
5 ✔
169
    SEND(std::move(message), handle_complete, _1, error::success);
5 ✔
170
}
5 ✔
171

NEW
172
void protocol_http::send_buffer(buffer_body::value_type&& buffer,
×
173
    media_type type) NOEXCEPT
174
{
NEW
175
    BC_ASSERT(stranded());
×
NEW
176
    auto message = to_response(status::ok);
×
NEW
177
    message.set(field::content_type, from_media_type(type));
×
NEW
178
    message.body() = std::move(buffer);
×
NEW
179
    message.prepare_payload();
×
NEW
180
    SEND(std::move(message), handle_complete, _1, error::success);
×
NEW
181
}
×
182

183
void protocol_http::send_empty() NOEXCEPT
6 ✔
184
{
185
    BC_ASSERT(stranded());
6 ✔
186
    auto message = to_response(status::ok);
6 ✔
187
    message.body() = empty_value{};
6 ✔
188
    message.prepare_payload();
6 ✔
189
    SEND(std::move(message), handle_complete, _1, error::success);
6 ✔
190
}
6 ✔
191

192
void protocol_http::send_stream(size_t size, wire_writer&& writer,
14 ✔
193
    media_type type) NOEXCEPT
194
{
195
    BC_ASSERT(stranded());
14 ✔
196
    auto message = to_response(status::ok);
14 ✔
197
    message.set(field::content_type, from_media_type(type));
14 ✔
198
    message.body() = stream_value
14 ✔
199
    {
200
        .write = std::move(writer),
14 ✔
201
        .size = size
202
    };
14 ✔
203
    message.prepare_payload();
14 ✔
204
    SEND(std::move(message), handle_stream, _1);
14 ✔
205
}
14 ✔
206

207
// Error senders.
208
// ----------------------------------------------------------------------------
209

210
void protocol_http::send_bad_request() NOEXCEPT
24 ✔
211
{
212
    send_bad_request(*reset_request());
24 ✔
213
}
24 ✔
214

215
void protocol_http::send_not_found() NOEXCEPT
71 ✔
216
{
217
    send_not_found(*reset_request());
71 ✔
218
}
71 ✔
219

220
void protocol_http::send_not_acceptable() NOEXCEPT
9 ✔
221
{
222
    send_not_acceptable(*reset_request());
9 ✔
223
}
9 ✔
224

225
void protocol_http::send_forbidden() NOEXCEPT
9 ✔
226
{
227
    send_forbidden(*reset_request());
9 ✔
228
}
9 ✔
229

230
void protocol_http::send_not_implemented() NOEXCEPT
10 ✔
231
{
232
    send_not_implemented(*reset_request());
10 ✔
233
}
10 ✔
234

235
void protocol_http::send_method_not_allowed() NOEXCEPT
3 ✔
236
{
237
    send_method_not_allowed(*reset_request());
3 ✔
238
}
3 ✔
239

240
void protocol_http::send_internal_server_error(const code& reason) NOEXCEPT
10 ✔
241
{
242
    send_internal_server_error(reason, *reset_request());
10 ✔
243
}
10 ✔
244

245
void protocol_http::send_bad_request(const request& request) NOEXCEPT
24 ✔
246
{
247
    network::protocol_http::send_bad_request(request);
24 ✔
248
}
24 ✔
249

250
void protocol_http::send_not_found(const request& request) NOEXCEPT
69 ✔
251
{
252
    network::protocol_http::send_not_found(request);
69 ✔
253
}
69 ✔
254

255
void protocol_http::send_not_acceptable(const request& request) NOEXCEPT
9 ✔
256
{
257
    network::protocol_http::send_not_acceptable(request);
9 ✔
258
}
9 ✔
259

260
void protocol_http::send_forbidden(const request& request) NOEXCEPT
17 ✔
261
{
262
    network::protocol_http::send_forbidden(request);
17 ✔
263
}
17 ✔
264

265
void protocol_http::send_not_implemented(const request& request) NOEXCEPT
10 ✔
266
{
267
    network::protocol_http::send_not_implemented(request);
10 ✔
268
}
10 ✔
269

270
void protocol_http::send_method_not_allowed(const request& request) NOEXCEPT
5 ✔
271
{
272
    network::protocol_http::send_method_not_allowed(request);
5 ✔
273
}
5 ✔
274

275
void protocol_http::send_internal_server_error(const code& reason,
10 ✔
276
    const request& request) NOEXCEPT
277
{
278
    network::protocol_http::send_internal_server_error(reason, request);
10 ✔
279
}
10 ✔
280

281
// A stream body write fails as unexpected only when its writer fails.
282
void protocol_http::handle_stream(const code& ec) NOEXCEPT
14 ✔
283
{
284
    BC_ASSERT(stranded());
14 ✔
285
    if (ec == network::error::unexpected_body)
14 ✔
286
        fault(database::error::integrity);
×
287

288
    handle_complete(ec, network::error::success);
14 ✔
289
}
14 ✔
290

291
BC_POP_WARNING()
292
BC_POP_WARNING()
293

294
} // namespace server
295
} // namespace libbitcoin
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc