@@ -25,15 +25,19 @@ namespace node {
2525
2626#define CLASS protocol_explore
2727
28- using namespace system ;
29- using namespace network ::http;
28+ using namespace boost ::json;
3029using namespace std ::placeholders;
30+ using namespace network ::http;
31+ using namespace system ;
32+
33+ const auto binary = mime_type::application_octet_stream;
34+ const auto json = mime_type::application_json;
35+ const auto text = mime_type::text_plain;
3136
3237BC_PUSH_WARNING (NO_THROW_IN_NOEXCEPT)
3338
3439// Handle get method.
3540// ----------------------------------------------------------------------------
36- // fields[], request->target(), file.is_open() are undeclared noexcept.
3741
3842void protocol_explore::handle_receive_get (const code& ec,
3943 const method::get& request) NOEXCEPT
@@ -57,6 +61,85 @@ void protocol_explore::handle_receive_get(const code& ec,
5761 return ;
5862 }
5963
64+ const auto target = request->target ();
65+ if (!is_origin_form (target))
66+ {
67+ send_bad_target (*request);
68+ return ;
69+ }
70+
71+ wallet::uri uri{};
72+ if (!uri.decode (target))
73+ {
74+ send_bad_target (*request);
75+ return ;
76+ }
77+
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+ // /////////////////////////////////////////////////////////////////////////
84+
85+ const auto get_tx = [&](const auto & path) NOEXCEPT
86+ {
87+ hash_digest hash{};
88+ if (!decode_hash (hash, path))
89+ {
90+ send_bad_target (*request);
91+ return chain::transaction::cptr{};
92+ }
93+
94+ const auto & query = archive ();
95+ return query.get_transaction (query.to_tx (hash), true );
96+ };
97+
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)
106+ {
107+ send_not_found (*request);
108+ return ;
109+ }
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)
119+ {
120+ send_not_found (*request);
121+ return ;
122+ }
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)
132+ {
133+ send_not_found (*request);
134+ return ;
135+ }
136+
137+ send_text (*request, encode_base16 (tx->to_data (true )));
138+ return ;
139+ }
140+
141+ // Default to html (single page site).
142+
60143 // Empty path implies malformed target (terminal).
61144 auto path = to_local_path (request->target ());
62145 if (path.empty ())
@@ -87,6 +170,44 @@ void protocol_explore::handle_receive_get(const code& ec,
87170 send_file (*request, std::move (file), file_mime_type (path));
88171}
89172
173+ // TODO: buffer should be reused, so set at the channel.
174+ // json_value is not a sized body, so this sets chunked encoding.
175+ void protocol_explore::send_json (const request& request,
176+ boost::json::value&& model) NOEXCEPT
177+ {
178+ BC_ASSERT_MSG (stranded (), " strand" );
179+ response response{ status::ok, request.version () };
180+ add_common_headers (response, request);
181+ response.set (field::content_type, from_mime_type (json));
182+ response.body () = { std::move (model) };
183+ response.prepare_payload ();
184+ SEND (std::move (response), handle_complete, _1, error::success);
185+ }
186+
187+ void protocol_explore::send_data (const request& request,
188+ data_chunk&& data) NOEXCEPT
189+ {
190+ BC_ASSERT_MSG (stranded (), " strand" );
191+ data_response response{ status::ok, request.version () };
192+ add_common_headers (response, request);
193+ response.set (field::content_type, from_mime_type (binary));
194+ response.body () = std::move (data);
195+ response.prepare_payload ();
196+ SEND (std::move (response), handle_complete, _1, error::success);
197+ }
198+
199+ void protocol_explore::send_text (const request& request,
200+ std::string&& hexidecimal) NOEXCEPT
201+ {
202+ BC_ASSERT_MSG (stranded (), " strand" );
203+ string_response response{ status::ok, request.version () };
204+ add_common_headers (response, request);
205+ response.set (field::content_type, from_mime_type (text));
206+ response.body () = std::move (hexidecimal);
207+ response.prepare_payload ();
208+ SEND (std::move (response), handle_complete, _1, error::success);
209+ }
210+
90211BC_POP_WARNING ()
91212
92213} // namespace node
0 commit comments