@@ -32,6 +32,34 @@ namespace fc::api {
3232
3333 const auto kChanCloseDelay {boost::posix_time::milliseconds (100 )};
3434
35+ void handleJSONRpcRequest (const Outcome<Document> &j_req,
36+ const Rpc &rpc,
37+ rpc::MakeChan make_chan,
38+ rpc::Send send,
39+ const Permissions &perms,
40+ std::function<void (const Response &)> cb) {
41+ if (!j_req) {
42+ return cb (Response{{}, Response::Error{kParseError , " Parse error" }});
43+ }
44+ auto maybe_req = decode<Request>(*j_req);
45+ if (!maybe_req) {
46+ return cb (
47+ Response{{}, Response::Error{kInvalidRequest , " Invalid request" }});
48+ }
49+ auto &req = maybe_req.value ();
50+ auto respond = [id{req.id }, cb](auto res) {
51+ if (id) {
52+ cb (Response{*id, std::move (res)});
53+ }
54+ };
55+ auto it = rpc.ms .find (req.method );
56+ if (it == rpc.ms .end () || !it->second ) {
57+ spdlog::error (" rpc method {} not implemented" , req.method );
58+ return respond (Response::Error{kMethodNotFound , " Method not found" });
59+ }
60+ it->second (req.params , std::move (respond), make_chan, send, perms);
61+ }
62+
3563 struct SocketSession : std::enable_shared_from_this<SocketSession> {
3664 SocketSession (tcp::socket &&socket, Rpc api_rpc, Permissions &&perms)
3765 : socket{std::move (socket)},
@@ -64,30 +92,10 @@ namespace fc::api {
6492 buffer.cdata ().size ()};
6593 auto j_req{codec::json::parse (s_req)};
6694 buffer.clear ();
67- if (!j_req) {
68- return _write (Response{{}, Response::Error{kParseError , " Parse error" }},
69- {});
70- }
71- auto maybe_req = decode<Request>(*j_req);
72- if (!maybe_req) {
73- return _write (
74- Response{{}, Response::Error{kInvalidRequest , " Invalid request" }},
75- {});
76- }
77- auto &req = maybe_req.value ();
78- auto respond = [id{req.id }, self{shared_from_this ()}](auto res) {
79- if (id) {
80- self->_write (Response{*id, std::move (res)}, {});
81- }
82- };
83- auto it = rpc.ms .find (req.method );
84- if (it == rpc.ms .end () || !it->second ) {
85- spdlog::error (" rpc method {} not implemented" , req.method );
86- return respond (Response::Error{kMethodNotFound , " Method not found" });
87- }
88- it->second (
89- req.params ,
90- std::move (respond),
95+
96+ handleJSONRpcRequest (
97+ j_req,
98+ rpc,
9199 [&]() { return next_channel++; },
92100 [self{shared_from_this ()}](auto method, auto params, auto cb) {
93101 Request req{self->next_request ++, method, std::move (params)};
@@ -101,7 +109,10 @@ namespace fc::api {
101109 }
102110 self->_write (req, std::move (cb));
103111 },
104- perms);
112+ perms,
113+ [self{shared_from_this ()}](const Response &resp) {
114+ self->_write (resp, {});
115+ });
105116 }
106117
107118 template <typename T>
@@ -149,7 +160,7 @@ namespace fc::api {
149160 };
150161
151162 std::optional<std::string> getToken (
152- const http::request<http::dynamic_body > &request) {
163+ const http::request<http::string_body > &request) {
153164 auto it = request.find (http::field::authorization);
154165 if (it != request.cend ()) {
155166 auto auth_token = (it->value ());
@@ -176,7 +187,7 @@ namespace fc::api {
176187 }
177188
178189 WrapperResponse makeErrorResponse (
179- const http::request<http::dynamic_body > &request, http::status status) {
190+ const http::request<http::string_body > &request, http::status status) {
180191 http::response<http::empty_body> response;
181192 response.version (request.version ());
182193 response.keep_alive (false );
@@ -257,8 +268,11 @@ namespace fc::api {
257268 if (request.target ().starts_with (route.first )) {
258269 boost::asio::post (stream.get_executor (),
259270 [self{shared_from_this ()}, fn{route.second }]() {
260- self->w_response = fn (self->request );
261- self->doWrite ();
271+ fn (self->request ,
272+ [self](WrapperResponse response) {
273+ self->w_response = std::move (response);
274+ self->doWrite ();
275+ });
262276 });
263277 is_handled = true ;
264278 break ;
@@ -318,7 +332,7 @@ namespace fc::api {
318332
319333 beast::tcp_stream stream;
320334 beast::flat_buffer buffer;
321- http::request<http::dynamic_body > request;
335+ http::request<http::string_body > request;
322336 WrapperResponse w_response;
323337 std::shared_ptr<Routes> routes;
324338 std::map<std::string, std::shared_ptr<Rpc>> rpc;
@@ -370,26 +384,65 @@ namespace fc::api {
370384 RouteHandler makeAuthRoute (AuthRouteHandler &&handler,
371385 rpc::AuthFunction &&auth) {
372386 return [handler{std::move (handler)}, auth{std::move (auth)}](
373- const http::request<http::dynamic_body > &request)
374- -> WrapperResponse {
387+ const http::request<http::string_body > &request,
388+ const RouteCB &cb) {
375389 Permissions perms = kDefaultPermission ;
376390 if (auth) {
377391 const auto maybe_token = getToken (request);
378392 if (not maybe_token.has_value ()) {
379- return makeErrorResponse (request, http::status::unauthorized);
393+ return cb ( makeErrorResponse (request, http::status::unauthorized) );
380394 }
381395
382396 if (not maybe_token.value ().empty ()) {
383397 auto maybe_perms =
384398 auth (static_cast <std::string>(maybe_token.value ()));
385399 if (maybe_perms.has_error ()) {
386- return makeErrorResponse (request, http::status::unauthorized);
400+ return cb ( makeErrorResponse (request, http::status::unauthorized) );
387401 }
388402 perms = std::move (maybe_perms.value ());
389403 }
390404 }
391405
392- return handler (request, perms);
406+ handler (request, perms, cb);
407+ };
408+ }
409+
410+ AuthRouteHandler makeHttpRpc (std::shared_ptr<Rpc> rpc) {
411+ return [rpc](const http::request<http::string_body> &request,
412+ const api::Permissions &perms,
413+ const RouteCB &cb) {
414+ std::string_view s_req (request.body ().data (), request.body ().size ());
415+ auto j_req{codec::json::parse (s_req)};
416+
417+ // TODO(ortyomka): Make error if channel requested
418+ handleJSONRpcRequest (
419+ j_req, *rpc, {}, {}, perms, [cb, request](const Response &resp) {
420+ auto data = *codec::json::format (encode (resp));
421+ http::response<http::string_body> response;
422+ response.version (request.version ());
423+ response.keep_alive (false );
424+ response.set (http::field::content_type, " application/json" );
425+ response.body () = common::span::bytestr (data);
426+
427+ if (auto *error = boost::get<Response::Error>(&(resp.result ));
428+ error) {
429+ switch (error->code ) {
430+ case kInvalidRequest :
431+ response.result (http::status::bad_request);
432+ break ;
433+ case kMethodNotFound :
434+ response.result (http::status::not_found);
435+ break ;
436+ case kParseError :
437+ case kInvalidParams :
438+ case kInternalError :
439+ default :
440+ response.result (http::status::internal_server_error);
441+ }
442+ }
443+
444+ cb (api::WrapperResponse (std::move (response)));
445+ });
393446 };
394447 }
395448
0 commit comments