Skip to content

Commit 04b39ff

Browse files
authored
Merge pull request #875 from evoskuil/master
Add some sloppy URI parsing (header|block|tx?format=&witness=).
2 parents a4ff608 + 658c0ee commit 04b39ff

File tree

2 files changed

+123
-55
lines changed

2 files changed

+123
-55
lines changed

include/bitcoin/node/protocols/protocol_explore.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,10 @@ class BCN_API protocol_explore
123123
/// Senders.
124124
void send_json(const network::http::request& request,
125125
boost::json::value&& model) NOEXCEPT;
126-
void send_data(const network::http::request& request,
127-
system::data_chunk&& data) NOEXCEPT;
128126
void send_text(const network::http::request& request,
129127
std::string&& hexidecimal) NOEXCEPT;
128+
void send_data(const network::http::request& request,
129+
system::data_chunk&& bytes) NOEXCEPT;
130130

131131
/// Receivers.
132132
void handle_receive_get(const code& ec,

src/protocols/protocol_explore.cpp

Lines changed: 121 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,18 @@ using namespace std::placeholders;
3030
using namespace network::http;
3131
using namespace system;
3232

33-
const auto binary = mime_type::application_octet_stream;
33+
const auto data = mime_type::application_octet_stream;
3434
const auto json = mime_type::application_json;
3535
const auto text = mime_type::text_plain;
3636

3737
BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
3838

3939
// Handle get method.
4040
// ----------------------------------------------------------------------------
41+
// TODO: performance timing header.
42+
// TODO: formatted error responses.
43+
// TODO: priority sort and dispatch.
44+
// TODO: URI path parse (see API doc).
4145

4246
void protocol_explore::handle_receive_get(const code& ec,
4347
const method::get& request) NOEXCEPT
@@ -75,67 +79,131 @@ void protocol_explore::handle_receive_get(const code& ec,
7579
return;
7680
}
7781

78-
///////////////////////////////////////////////////////////////////////////
79-
// TODO: formatted error responses.
80-
// TODO: priority sort and dispatch.
81-
// TODO: URI path parse (see API doc).
82-
// TODO: performance timing header.
83-
///////////////////////////////////////////////////////////////////////////
82+
if (const auto parts = split(uri.path(), "/");
83+
!parts.empty() && parts.size() != two)
84+
{
85+
send_bad_target(*request);
86+
return;
87+
}
88+
else
89+
{
90+
const auto hd = parts.front() == "header" || parts.front() == "hd";
91+
const auto bk = parts.front() == "block" || parts.front() == "bk";
92+
const auto tx = parts.front() == "transaction" || parts.front() == "tx";
93+
if (!hd && !bk && !tx)
94+
{
95+
send_bad_target(*request);
96+
return;
97+
}
98+
99+
auto params = uri.decode_query();
100+
const auto format = params["format"];
101+
const auto accepts = to_mime_types((*request)[field::accept]);
102+
const auto is_json = contains(accepts, json) || format == "json";
103+
const auto is_text = contains(accepts, text) || format == "text";
104+
const auto is_data = contains(accepts, data) || format == "data";
105+
const auto wit = params["witness"] != "false";
106+
const auto hex = parts.back();
84107

85-
const auto get_tx = [&](const auto& path) NOEXCEPT
86-
{
87108
hash_digest hash{};
88-
if (!decode_hash(hash, path))
109+
if ((is_json || is_text || is_data) && !decode_hash(hash, hex))
89110
{
90111
send_bad_target(*request);
91-
return chain::transaction::cptr{};
112+
return;
92113
}
93114

94115
const auto& query = archive();
95-
return query.get_transaction(query.to_tx(hash), true);
96-
};
97116

98-
auto params = uri.decode_query();
99-
const auto hex = trim_copy(uri.path(), { "/" });
100-
const auto accepts = to_mime_types((*request)[field::accept]);
101-
102-
if (contains(accepts, json) || params["format"] == "json")
103-
{
104-
const auto tx = get_tx(hex);
105-
if (!tx)
117+
if (is_json)
106118
{
119+
if (hd)
120+
{
121+
if (const auto ptr = query.get_header(query.to_header(hash)))
122+
{
123+
send_json(*request, value_from(*ptr));
124+
return;
125+
}
126+
}
127+
else if (bk)
128+
{
129+
if (const auto ptr = query.get_block(query.to_header(hash), wit))
130+
{
131+
send_json(*request, value_from(*ptr));
132+
return;
133+
}
134+
}
135+
else
136+
{
137+
if (const auto ptr = query.get_transaction(query.to_tx(hash), wit))
138+
{
139+
send_json(*request, value_from(*ptr));
140+
return;
141+
}
142+
}
143+
107144
send_not_found(*request);
108145
return;
109146
}
110-
111-
send_json(*request, value_from(*tx));
112-
return;
113-
}
114-
115-
if (contains(accepts, binary) || params["format"] == "binary")
116-
{
117-
const auto tx = get_tx(hex);
118-
if (!tx)
147+
else if (is_text)
119148
{
149+
if (hd)
150+
{
151+
if (const auto ptr = query.get_header(query.to_header(hash)))
152+
{
153+
send_text(*request, encode_base16(ptr->to_data()));
154+
return;
155+
}
156+
}
157+
else if (bk)
158+
{
159+
if (const auto ptr = query.get_block(query.to_header(hash), wit))
160+
{
161+
send_text(*request, encode_base16(ptr->to_data(wit)));
162+
return;
163+
}
164+
}
165+
else
166+
{
167+
if (const auto ptr = query.get_transaction(query.to_tx(hash), wit))
168+
{
169+
send_text(*request, encode_base16(ptr->to_data(wit)));
170+
return;
171+
}
172+
}
173+
120174
send_not_found(*request);
121175
return;
122176
}
123-
124-
send_data(*request, tx->to_data(true));
125-
return;
126-
}
127-
128-
if (contains(accepts, text) || params["format"] == "text")
129-
{
130-
const auto tx = get_tx(hex);
131-
if (!tx)
177+
else if (is_data)
132178
{
179+
if (hd)
180+
{
181+
if (const auto ptr = query.get_header(query.to_header(hash)))
182+
{
183+
send_data(*request, ptr->to_data());
184+
return;
185+
}
186+
}
187+
else if (bk)
188+
{
189+
if (const auto ptr = query.get_block(query.to_header(hash), wit))
190+
{
191+
send_data(*request, ptr->to_data(wit));
192+
return;
193+
}
194+
}
195+
else
196+
{
197+
if (const auto ptr = query.get_transaction(query.to_tx(hash), wit))
198+
{
199+
send_data(*request, ptr->to_data(wit));
200+
return;
201+
}
202+
}
203+
133204
send_not_found(*request);
134205
return;
135206
}
136-
137-
send_text(*request, encode_base16(tx->to_data(true)));
138-
return;
139207
}
140208

141209
// Default to html (single page site).
@@ -179,31 +247,31 @@ void protocol_explore::send_json(const request& request,
179247
response response{ status::ok, request.version() };
180248
add_common_headers(response, request);
181249
response.set(field::content_type, from_mime_type(json));
182-
response.body() = { std::move(model) };
250+
response.body() = { std::move(model), std::make_shared<flat_buffer>(10 * 1024 * 1024) };
183251
response.prepare_payload();
184252
SEND(std::move(response), handle_complete, _1, error::success);
185253
}
186254

187-
void protocol_explore::send_data(const request& request,
188-
data_chunk&& data) NOEXCEPT
255+
void protocol_explore::send_text(const request& request,
256+
std::string&& hexidecimal) NOEXCEPT
189257
{
190258
BC_ASSERT_MSG(stranded(), "strand");
191-
data_response response{ status::ok, request.version() };
259+
string_response response{ status::ok, request.version() };
192260
add_common_headers(response, request);
193-
response.set(field::content_type, from_mime_type(binary));
194-
response.body() = std::move(data);
261+
response.set(field::content_type, from_mime_type(text));
262+
response.body() = std::move(hexidecimal);
195263
response.prepare_payload();
196264
SEND(std::move(response), handle_complete, _1, error::success);
197265
}
198266

199-
void protocol_explore::send_text(const request& request,
200-
std::string&& hexidecimal) NOEXCEPT
267+
void protocol_explore::send_data(const request& request,
268+
data_chunk&& bytes) NOEXCEPT
201269
{
202270
BC_ASSERT_MSG(stranded(), "strand");
203-
string_response response{ status::ok, request.version() };
271+
data_response response{ status::ok, request.version() };
204272
add_common_headers(response, request);
205-
response.set(field::content_type, from_mime_type(text));
206-
response.body() = std::move(hexidecimal);
273+
response.set(field::content_type, from_mime_type(data));
274+
response.body() = std::move(bytes);
207275
response.prepare_payload();
208276
SEND(std::move(response), handle_complete, _1, error::success);
209277
}

0 commit comments

Comments
 (0)