@@ -32,6 +32,34 @@ namespace fc::api {
32
32
33
33
const auto kChanCloseDelay {boost::posix_time::milliseconds (100 )};
34
34
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
+
35
63
struct SocketSession : std::enable_shared_from_this<SocketSession> {
36
64
SocketSession (tcp::socket &&socket, Rpc api_rpc, Permissions &&perms)
37
65
: socket{std::move (socket)},
@@ -64,30 +92,10 @@ namespace fc::api {
64
92
buffer.cdata ().size ()};
65
93
auto j_req{codec::json::parse (s_req)};
66
94
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,
91
99
[&]() { return next_channel++; },
92
100
[self{shared_from_this ()}](auto method, auto params, auto cb) {
93
101
Request req{self->next_request ++, method, std::move (params)};
@@ -101,7 +109,10 @@ namespace fc::api {
101
109
}
102
110
self->_write (req, std::move (cb));
103
111
},
104
- perms);
112
+ perms,
113
+ [self{shared_from_this ()}](const Response &resp) {
114
+ self->_write (resp, {});
115
+ });
105
116
}
106
117
107
118
template <typename T>
@@ -149,7 +160,7 @@ namespace fc::api {
149
160
};
150
161
151
162
std::optional<std::string> getToken (
152
- const http::request<http::dynamic_body > &request) {
163
+ const http::request<http::string_body > &request) {
153
164
auto it = request.find (http::field::authorization);
154
165
if (it != request.cend ()) {
155
166
auto auth_token = (it->value ());
@@ -176,7 +187,7 @@ namespace fc::api {
176
187
}
177
188
178
189
WrapperResponse makeErrorResponse (
179
- const http::request<http::dynamic_body > &request, http::status status) {
190
+ const http::request<http::string_body > &request, http::status status) {
180
191
http::response<http::empty_body> response;
181
192
response.version (request.version ());
182
193
response.keep_alive (false );
@@ -257,8 +268,11 @@ namespace fc::api {
257
268
if (request.target ().starts_with (route.first )) {
258
269
boost::asio::post (stream.get_executor (),
259
270
[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
+ });
262
276
});
263
277
is_handled = true ;
264
278
break ;
@@ -318,7 +332,7 @@ namespace fc::api {
318
332
319
333
beast::tcp_stream stream;
320
334
beast::flat_buffer buffer;
321
- http::request<http::dynamic_body > request;
335
+ http::request<http::string_body > request;
322
336
WrapperResponse w_response;
323
337
std::shared_ptr<Routes> routes;
324
338
std::map<std::string, std::shared_ptr<Rpc>> rpc;
@@ -370,26 +384,65 @@ namespace fc::api {
370
384
RouteHandler makeAuthRoute (AuthRouteHandler &&handler,
371
385
rpc::AuthFunction &&auth) {
372
386
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) {
375
389
Permissions perms = kDefaultPermission ;
376
390
if (auth) {
377
391
const auto maybe_token = getToken (request);
378
392
if (not maybe_token.has_value ()) {
379
- return makeErrorResponse (request, http::status::unauthorized);
393
+ return cb ( makeErrorResponse (request, http::status::unauthorized) );
380
394
}
381
395
382
396
if (not maybe_token.value ().empty ()) {
383
397
auto maybe_perms =
384
398
auth (static_cast <std::string>(maybe_token.value ()));
385
399
if (maybe_perms.has_error ()) {
386
- return makeErrorResponse (request, http::status::unauthorized);
400
+ return cb ( makeErrorResponse (request, http::status::unauthorized) );
387
401
}
388
402
perms = std::move (maybe_perms.value ());
389
403
}
390
404
}
391
405
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
+ });
393
446
};
394
447
}
395
448
0 commit comments