diff --git a/console/embedded/explore_css.cpp b/console/embedded/explore_css.cpp
index 750b68079..ae3dd116c 100644
--- a/console/embedded/explore_css.cpp
+++ b/console/embedded/explore_css.cpp
@@ -21,7 +21,13 @@
namespace libbitcoin {
namespace server {
-DEFINE_EMBEDDED_PAGE(explore_pages, char, css, "")
+// Simple test css for embedded page, links in font.
+DEFINE_EMBEDDED_PAGE(explore_pages, char, css,
+R"(@font-face
+{
+ font-family: 'Boston';
+ src: url('boston.woff2');
+})")
} // namespace server
} // namespace libbitcoin
diff --git a/console/embedded/explore_ecma.cpp b/console/embedded/explore_ecma.cpp
index b66e06145..81b4d3250 100644
--- a/console/embedded/explore_ecma.cpp
+++ b/console/embedded/explore_ecma.cpp
@@ -21,7 +21,12 @@
namespace libbitcoin {
namespace server {
-DEFINE_EMBEDDED_PAGE(explore_pages, char, ecma, "")
+// Simple test ecma script for embedded page.
+DEFINE_EMBEDDED_PAGE(explore_pages, char, ecma,
+R"(document.addEventListener('DOMContentLoaded', function()
+{
+ console.log('pong');
+});)")
} // namespace server
} // namespace libbitcoin
diff --git a/console/embedded/explore_font.cpp b/console/embedded/explore_font.cpp
index 75c755454..552880e5f 100644
--- a/console/embedded/explore_font.cpp
+++ b/console/embedded/explore_font.cpp
@@ -21,7 +21,17 @@
namespace libbitcoin {
namespace server {
-DEFINE_EMBEDDED_PAGE(explore_pages, char, font, "")
+DEFINE_EMBEDDED_PAGE(explore_pages, uint8_t, font,
+{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+})
} // namespace server
} // namespace libbitcoin
diff --git a/console/embedded/explore_html.cpp b/console/embedded/explore_html.cpp
index 93a288d18..f15a62e14 100644
--- a/console/embedded/explore_html.cpp
+++ b/console/embedded/explore_html.cpp
@@ -21,8 +21,22 @@
namespace libbitcoin {
namespace server {
-// Empty page disabled embedded size.
-DEFINE_EMBEDDED_PAGE(explore_pages, char, html, "")
+// Simple test html for embedded page, links in css and page icon.
+DEFINE_EMBEDDED_PAGE(explore_pages, char, html,
+R"(
+
+ Libbitcoin Block Explorer
+
+
+
+
+
+
+
+
+ Hello world!
+
+)")
} // namespace server
} // namespace libbitcoin
diff --git a/console/embedded/explore_icon.cpp b/console/embedded/explore_icon.cpp
index 6d0efef1d..35b939569 100644
--- a/console/embedded/explore_icon.cpp
+++ b/console/embedded/explore_icon.cpp
@@ -21,7 +21,17 @@
namespace libbitcoin {
namespace server {
-DEFINE_EMBEDDED_PAGE(explore_pages, char, icon, "")
+DEFINE_EMBEDDED_PAGE(explore_pages, uint8_t, icon,
+{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+})
} // namespace server
} // namespace libbitcoin
diff --git a/console/main.cpp b/console/main.cpp
index 0900a4ca2..f0decbf52 100644
--- a/console/main.cpp
+++ b/console/main.cpp
@@ -86,10 +86,9 @@ int bc::system::main(int argc, char* argv[])
std::ios_base::sync_with_stdio(false);
set_utf8_stdio();
- // HACK: web_server used for both!
const server::web_pages web_server{};
const server::explore_pages block_explorer{};
- parser metadata(chain::selection::mainnet, web_server, web_server);
+ parser metadata(chain::selection::mainnet, block_explorer, web_server);
const auto& args = const_cast(argv);
@@ -100,11 +99,11 @@ int bc::system::main(int argc, char* argv[])
symbols_path = metadata.configured.log.symbols;
#endif
-// requires _WIN32_WINNT set to 0x0602 (defaults 0x0602 in vc++ 2022).
-#if defined(HAVE_MSC) && defined(MEMORY_PRIORITY_INFORMATION)
+// Requires _WIN32_WINNT set to 0x0602 (defaults 0x0602 in vc++ 2022).
+#if defined(HAVE_MSC) && (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
- // Set low memory priority on the current process.
- const MEMORY_PRIORITY_INFORMATION priority{ MEMORY_PRIORITY_LOW };
+ // Set low memory priority on the current process (testing).
+ MEMORY_PRIORITY_INFORMATION priority{ MEMORY_PRIORITY_LOW };
SetProcessInformation(
GetCurrentProcess(),
ProcessMemoryPriority,
diff --git a/include/bitcoin/node/protocols/protocol_explore.hpp b/include/bitcoin/node/protocols/protocol_explore.hpp
index 49c3fd8a7..376e7c81a 100644
--- a/include/bitcoin/node/protocols/protocol_explore.hpp
+++ b/include/bitcoin/node/protocols/protocol_explore.hpp
@@ -51,6 +51,10 @@ class BCN_API protocol_explore
/// Receivers.
void handle_receive_get(const code& ec,
const network::http::method::get& request) NOEXCEPT override;
+
+ /// Dispatch.
+ virtual bool dispatch_object(
+ const network::http::request& request) NOEXCEPT;
};
} // namespace node
diff --git a/include/bitcoin/node/protocols/protocol_html.hpp b/include/bitcoin/node/protocols/protocol_html.hpp
index df4258825..aea4b7efc 100644
--- a/include/bitcoin/node/protocols/protocol_html.hpp
+++ b/include/bitcoin/node/protocols/protocol_html.hpp
@@ -51,6 +51,10 @@ class BCN_API protocol_html
void handle_receive_get(const code& ec,
const network::http::method::get& request) NOEXCEPT override;
+ /// Dispatch.
+ virtual bool dispatch_embedded(
+ const network::http::request& request) NOEXCEPT;
+
/// Senders.
virtual void send_json(const network::http::request& request,
boost::json::value&& model, size_t size_hint) NOEXCEPT;
@@ -67,6 +71,8 @@ class BCN_API protocol_html
/// Utilities.
bool is_allowed_origin(const network::http::fields& fields,
size_t version) const NOEXCEPT;
+ std::filesystem::path to_path(
+ const std::string& target = "/") const NOEXCEPT;
std::filesystem::path to_local_path(
const std::string& target = "/") const NOEXCEPT;
diff --git a/src/protocols/protocol_explore.cpp b/src/protocols/protocol_explore.cpp
index eb8ded214..7d332fb3a 100644
--- a/src/protocols/protocol_explore.cpp
+++ b/src/protocols/protocol_explore.cpp
@@ -34,87 +34,11 @@ BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
// Handle get method.
// ----------------------------------------------------------------------------
-// TODO: performance timing header.
-// TODO: formatted error responses.
-// TODO: formatted error responses.
-// TODO: priority accept media type sort and dispatch.
-// TODO: URI path parse (see API doc).
-
-/// TODO: move to own source.
-/// Pagination and filtering are via query string.
-enum targets
-{
- /// /v[]/block/hash/[bkhash] {1}
- /// /v[]/block/height/[height] {1}
- block,
-
- /// /v[]/block/hash/[bkhash]/filter {1}
- /// /v[]/block/height/[height]/filter {1}
- filter,
-
- /// /v[]/block/hash/[bkhash]/header {1}
- /// /v[]/block/height/[height]/header {1}
- header,
-
- /// /v[]/transaction/hash/[txhash] {1}
- /// /v[]/block/hash/[bkhash]/transaction/position/[position] {1}
- /// /v[]/block/height/[height]/transaction/position/[position] {1}
- transaction,
-
- /// /v[]/block/hash/[bkhash]/transactions {all txs in the block}
- /// /v[]/block/height/[height]/transactions {all txs in the block}
- transactions,
-
- // --------------------------------------------------------------------
-
- /// /v[]/input/[txhash]/[index] {1}
- input,
-
- /// /v[]/inputs/[txhash] {all inputs in the tx}
- inputs,
-
- /// /v[]/input/[txhash]/[index]/script {1}
- input_script,
-
- /// /v[]/input/[txhash]/scripts {all input scripts in the tx}
- input_scripts,
-
- /// /v[]/input/[txhash]/[index]/witness {1}
- input_witness,
-
- /// /v[]/input/[txhash]/witnesses {all witnesses in the tx}
- input_witnesses,
-
- // --------------------------------------------------------------------
-
- /// /v[]/output/[txhash]/[index] {1}
- output,
-
- /// /v[]/outputs/[txhash] {all outputs in the tx}
- outputs,
-
- /// /v[]/output/[txhash]/[index]/script {1}
- output_script,
-
- /// /v[]/output/[txhash]/scripts {all output scripts in the tx}
- output_scripts,
-
- /// /v[]/output/[txhash]/[index]/spender {1 - confirmed}
- output_spender,
-
- /// /v[]/output/[txhash]/spenders {all}
- output_spenders,
-
- // --------------------------------------------------------------------
-
- /// /v[]/address/[output-script-hash] {all}
- address
-};
void protocol_explore::handle_receive_get(const code& ec,
const method::get& request) NOEXCEPT
{
- BC_ASSERT_MSG(stranded(), "strand");
+ BC_ASSERT(stranded());
if (stopped(ec))
return;
@@ -133,207 +57,194 @@ void protocol_explore::handle_receive_get(const code& ec,
return;
}
- const auto target = request->target();
- if (!is_origin_form(target))
- {
- send_bad_target(*request);
+ // Dispatch object with specified encoding.
+ if (dispatch_object(*request))
return;
- }
- wallet::uri uri{};
- if (!uri.decode(target))
+ // Embedded page site.
+ if (dispatch_embedded(*request))
+ return;
+
+ // Empty path implies malformed target (terminal).
+ auto path = to_local_path(request->target());
+ if (path.empty())
{
send_bad_target(*request);
return;
}
- if (const auto parts = split(uri.path(), "/");
- parts.size() == two)
+ // If no file extension it's REST on the single/default html page.
+ if (!path.has_extension())
{
- constexpr auto data = mime_type::application_octet_stream;
- constexpr auto json = mime_type::application_json;
- constexpr auto text = mime_type::text_plain;
-
- const auto hd = parts.front() == "header" || parts.front() == "hd";
- const auto bk = parts.front() == "block" || parts.front() == "bk";
- const auto tx = parts.front() == "transaction" || parts.front() == "tx";
- if (!hd && !bk && !tx)
- {
- send_bad_target(*request);
- return;
- }
+ path = to_local_path();
- auto params = uri.decode_query();
- const auto format = params["format"];
- const auto accepts = to_mime_types((*request)[field::accept]);
- const auto is_json = contains(accepts, json) || format == "json";
- const auto is_text = contains(accepts, text) || format == "text";
- const auto is_data = contains(accepts, data) || format == "data";
- const auto wit = params["witness"] != "false";
- const auto hex = parts.back();
-
- hash_digest hash{};
- if ((is_json || is_text || is_data) && !decode_hash(hash, hex))
+ // Default html page (e.g. index.html) is not configured.
+ if (path.empty())
{
- send_bad_target(*request);
+ send_not_implemented(*request);
return;
}
+ }
- const auto& query = archive();
+ // Get the single/default or explicitly requested page.
+ auto file = get_file_body(path);
+ if (!file.is_open())
+ {
+ send_not_found(*request);
+ return;
+ }
- if (is_json)
+ send_file(*request, std::move(file),
+ file_mime_type(path, mime_type::application_octet_stream));
+}
+
+// Dispatch.
+// ----------------------------------------------------------------------------
+
+bool protocol_explore::dispatch_object(
+ const network::http::request& request) NOEXCEPT
+{
+ const auto target = request.target();
+ if (!is_origin_form(target))
+ {
+ send_bad_target(request);
+ return true;
+ }
+
+ wallet::uri uri{};
+ if (!uri.decode(target))
+ {
+ send_bad_target(request);
+ return true;
+ }
+
+ const auto parts = split(uri.path(), "/");
+ if (parts.size() != two)
+ return false;
+
+ const auto hd = parts.front() == "header" || parts.front() == "hd";
+ const auto bk = parts.front() == "block" || parts.front() == "bk";
+ const auto tx = parts.front() == "transaction" || parts.front() == "tx";
+ if (!hd && !bk && !tx)
+ {
+ send_bad_target(request);
+ return true;
+ }
+
+ auto params = uri.decode_query();
+ const auto format = params["format"];
+ constexpr auto text = mime_type::text_plain;
+ constexpr auto json = mime_type::application_json;
+ constexpr auto data = mime_type::application_octet_stream;
+ const auto accepts = to_mime_types((request)[field::accept]);
+ const auto is_json = contains(accepts, json) || format == "json";
+ const auto is_text = contains(accepts, text) || format == "text";
+ const auto is_data = contains(accepts, data) || format == "data";
+ if (!is_json && !is_text && !is_data)
+ return false;
+
+ hash_digest hash{};
+ if (!decode_hash(hash, parts.back()))
+ {
+ send_bad_target(request);
+ return true;
+ }
+
+ const auto& query = archive();
+ const auto wit = params["witness"] != "false";
+
+ if (is_json)
+ {
+ if (hd)
{
- if (hd)
- {
- if (const auto ptr = query.get_header(query.to_header(hash)))
- {
- send_json(*request, value_from(ptr), ptr->serialized_size());
- return;
- }
- }
- else if (bk)
- {
- if (const auto ptr = query.get_block(query.to_header(hash), wit))
- {
- send_json(*request, value_from(ptr), ptr->serialized_size(wit));
- return;
- }
- }
- else
+ if (const auto ptr = query.get_header(query.to_header(hash)))
{
- if (const auto ptr = query.get_transaction(query.to_tx(hash), wit))
- {
- send_json(*request, value_from(ptr), ptr->serialized_size(wit));
- return;
- }
+ send_json(request, value_from(ptr), ptr->serialized_size());
+ return true;
}
-
- send_not_found(*request);
- return;
}
- else if (is_text)
+ else if (bk)
{
- if (hd)
- {
- if (const auto ptr = query.get_header(query.to_header(hash)))
- {
- send_text(*request, encode_base16(ptr->to_data()));
- return;
- }
- }
- else if (bk)
+ if (const auto ptr = query.get_block(query.to_header(hash), wit))
{
- if (const auto ptr = query.get_block(query.to_header(hash), wit))
- {
- send_text(*request, encode_base16(ptr->to_data(wit)));
- return;
- }
+ send_json(request, value_from(ptr), ptr->serialized_size(wit));
+ return true;
}
- else
+ }
+ else
+ {
+ if (const auto ptr = query.get_transaction(query.to_tx(hash), wit))
{
- if (const auto ptr = query.get_transaction(query.to_tx(hash), wit))
- {
- send_text(*request, encode_base16(ptr->to_data(wit)));
- return;
- }
+ send_json(request, value_from(ptr), ptr->serialized_size(wit));
+ return true;
}
-
- send_not_found(*request);
- return;
}
- else if (is_data)
+
+ send_not_found(request);
+ return true;
+ }
+
+ if (is_text)
+ {
+ if (hd)
{
- if (hd)
+ if (const auto ptr = query.get_header(query.to_header(hash)))
{
- if (const auto ptr = query.get_header(query.to_header(hash)))
- {
- send_data(*request, ptr->to_data());
- return;
- }
+ send_text(request, encode_base16(ptr->to_data()));
+ return true;
}
- else if (bk)
+ }
+ else if (bk)
+ {
+ if (const auto ptr = query.get_block(query.to_header(hash), wit))
{
- if (const auto ptr = query.get_block(query.to_header(hash), wit))
- {
- send_data(*request, ptr->to_data(wit));
- return;
- }
+ send_text(request, encode_base16(ptr->to_data(wit)));
+ return true;
}
- else
+ }
+ else
+ {
+ if (const auto ptr = query.get_transaction(query.to_tx(hash), wit))
{
- if (const auto ptr = query.get_transaction(query.to_tx(hash), wit))
- {
- send_data(*request, ptr->to_data(wit));
- return;
- }
+ send_text(request, encode_base16(ptr->to_data(wit)));
+ return true;
}
-
- send_not_found(*request);
- return;
}
+
+ send_not_found(request);
+ return true;
}
- // Embedded page site.
- if (config().server.explore.pages.enabled())
+ ////if (is_data)
{
- const auto& pages = config().server.explore.pages;
- const auto mime = extension_mime_type(to_extension(request->target()));
- switch (mime)
+ if (hd)
{
- case mime_type::text_css:
- send_span(*request, pages.css(), mime);
- break;
- case mime_type::text_html:
- send_span(*request, pages.html(), mime);
- break;
- case mime_type::application_javascript:
- send_span(*request, pages.ecma(), mime);
- break;
- case mime_type::font_woff:
- case mime_type::font_woff2:
- send_span(*request, pages.font(), mime);
- return;
- case mime_type::image_png:
- case mime_type::image_gif:
- case mime_type::image_jpeg:
- case mime_type::image_x_icon:
- case mime_type::image_svg_xml:
- send_span(*request, pages.icon(), mime);
- break;
- default:
- send_not_implemented(*request);
- return;
+ if (const auto ptr = query.get_header(query.to_header(hash)))
+ {
+ send_data(request, ptr->to_data());
+ return true;
+ }
}
- }
-
- // Empty path implies malformed target (terminal).
- auto path = to_local_path(request->target());
- if (path.empty())
- {
- send_bad_target(*request);
- return;
- }
-
- if (!path.has_extension())
- {
- // Empty implies default page invalid or not configured (terminal).
- path = to_local_path();
- if (path.empty())
+ else if (bk)
{
- send_not_implemented(*request);
- return;
+ if (const auto ptr = query.get_block(query.to_header(hash), wit))
+ {
+ send_data(request, ptr->to_data(wit));
+ return true;
+ }
+ }
+ else
+ {
+ if (const auto ptr = query.get_transaction(query.to_tx(hash), wit))
+ {
+ send_data(request, ptr->to_data(wit));
+ return true;
+ }
}
- }
- // Not open implies file not found (non-terminal).
- auto file = get_file_body(path);
- if (!file.is_open())
- {
- send_not_found(*request);
- return;
+ send_not_found(request);
+ return true;
}
-
- send_file(*request, std::move(file), file_mime_type(path));
}
BC_POP_WARNING()
diff --git a/src/protocols/protocol_html.cpp b/src/protocols/protocol_html.cpp
index d6b82a90e..22bcb125d 100644
--- a/src/protocols/protocol_html.cpp
+++ b/src/protocols/protocol_html.cpp
@@ -36,7 +36,7 @@ BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
void protocol_html::handle_receive_get(const code& ec,
const method::get& request) NOEXCEPT
{
- BC_ASSERT_MSG(stranded(), "strand");
+ BC_ASSERT(stranded());
if (stopped(ec))
return;
@@ -55,10 +55,16 @@ void protocol_html::handle_receive_get(const code& ec,
return;
}
+ // Embedded page site.
+ if (dispatch_embedded(*request))
+ return;
+
// Empty path implies malformed target (terminal).
const auto path = to_local_path(request->target());
if (path.empty())
{
+ // TODO: split out sanitize from canonicalize so that this can return
+ // send_not_found() when the request is sanitary but not found.
send_bad_target(*request);
return;
}
@@ -71,8 +77,43 @@ void protocol_html::handle_receive_get(const code& ec,
return;
}
- const auto default_type = mime_type::application_octet_stream;
- send_file(*request, std::move(file), file_mime_type(path, default_type));
+ send_file(*request, std::move(file),
+ file_mime_type(path, mime_type::application_octet_stream));
+}
+
+// Dispatch.
+// ----------------------------------------------------------------------------
+
+bool protocol_html::dispatch_embedded(const request& request) NOEXCEPT
+{
+ // False only if not enabled, otherwise handled below.
+ if (!options_.pages.enabled())
+ return false;
+
+ const auto& pages = config().server.explore.pages;
+ switch (const auto mime = file_mime_type(to_path(request.target())))
+ {
+ case mime_type::text_css:
+ send_span(request, pages.css(), mime);
+ return true;
+ case mime_type::text_html:
+ send_span(request, pages.html(), mime);
+ return true;
+ case mime_type::application_javascript:
+ send_span(request, pages.ecma(), mime);
+ return true;
+ case mime_type::font_woff:
+ case mime_type::font_woff2:
+ send_span(request, pages.font(), mime);
+ return true;
+ case mime_type::image_png:
+ case mime_type::image_gif:
+ case mime_type::image_jpeg:
+ send_span(request, pages.icon(), mime);
+ return true;
+ default:
+ return false;
+ }
}
// Senders.
@@ -85,7 +126,7 @@ constexpr auto text = mime_type::text_plain;
void protocol_html::send_json(const request& request,
boost::json::value&& model, size_t size_hint) NOEXCEPT
{
- BC_ASSERT_MSG(stranded(), "strand");
+ BC_ASSERT(stranded());
response response{ status::ok, request.version() };
add_common_headers(response, request);
response.set(field::content_type, from_mime_type(json));
@@ -97,7 +138,7 @@ void protocol_html::send_json(const request& request,
void protocol_html::send_text(const request& request,
std::string&& hexidecimal) NOEXCEPT
{
- BC_ASSERT_MSG(stranded(), "strand");
+ BC_ASSERT(stranded());
response response{ status::ok, request.version() };
add_common_headers(response, request);
response.set(field::content_type, from_mime_type(text));
@@ -109,7 +150,7 @@ void protocol_html::send_text(const request& request,
void protocol_html::send_data(const request& request,
system::data_chunk&& bytes) NOEXCEPT
{
- BC_ASSERT_MSG(stranded(), "strand");
+ BC_ASSERT(stranded());
response response{ status::ok, request.version() };
add_common_headers(response, request);
response.set(field::content_type, from_mime_type(data));
@@ -121,7 +162,7 @@ void protocol_html::send_data(const request& request,
void protocol_html::send_file(const request& request, file&& file,
mime_type type) NOEXCEPT
{
- BC_ASSERT_MSG(stranded(), "strand");
+ BC_ASSERT(stranded());
BC_ASSERT_MSG(file.is_open(), "sending closed file handle");
response response{ status::ok, request.version() };
add_common_headers(response, request);
@@ -134,7 +175,7 @@ void protocol_html::send_file(const request& request, file&& file,
void protocol_html::send_span(const request& request,
span_body::value_type&& span, mime_type type) NOEXCEPT
{
- BC_ASSERT_MSG(stranded(), "strand");
+ BC_ASSERT(stranded());
response response{ status::ok, request.version() };
add_common_headers(response, request);
response.set(field::content_type, from_mime_type(type));
@@ -159,11 +200,16 @@ bool protocol_html::is_allowed_origin(const fields& fields,
network::config::to_normal_host(origin, default_port()));
}
+std::filesystem::path protocol_html::to_path(
+ const std::string& target) const NOEXCEPT
+{
+ return target == "/" ? target + options_.default_ : target;
+}
+
std::filesystem::path protocol_html::to_local_path(
const std::string& target) const NOEXCEPT
{
- return sanitize_origin(options_.path,
- target == "/" ? target + options_.default_ : target);
+ return sanitize_origin(options_.path, to_path(target).string());
}
BC_POP_WARNING()