cuprate_rpc_interface/route/json_rpc.rs
1//! JSON-RPC 2.0 endpoint route functions.
2
3//---------------------------------------------------------------------------------------------------- Import
4use axum::{extract::State, http::StatusCode, Json};
5use tower::ServiceExt;
6
7use cuprate_json_rpc::{Id, Response};
8use cuprate_rpc_types::{
9 json::{JsonRpcRequest, JsonRpcResponse},
10 RpcCallValue,
11};
12
13use crate::rpc_handler::RpcHandler;
14
15//---------------------------------------------------------------------------------------------------- Routes
16/// The `/json_rpc` route function used in [`crate::RouterBuilder`].
17pub(crate) async fn json_rpc<H: RpcHandler>(
18 State(handler): State<H>,
19 Json(request): Json<cuprate_json_rpc::Request<JsonRpcRequest>>,
20) -> Result<Json<Response<JsonRpcResponse>>, StatusCode> {
21 // TODO: <https://www.jsonrpc.org/specification#notification>
22 //
23 // JSON-RPC notifications (requests without `id`)
24 // must not be responded too, although, the request's side-effects
25 // must remain. How to do this considering this function will
26 // always return and cause `axum` to respond?
27
28 // JSON-RPC 2.0 rule:
29 // If there was an error in detecting the `Request`'s ID,
30 // the `Response` must contain an `Id::Null`
31 let id = request.id.unwrap_or(Id::Null);
32
33 // Return early if this RPC server is restricted and
34 // the requested method is only for non-restricted RPC.
35 //
36 // INVARIANT:
37 // The RPC handler functions in `cuprated` depend on this line existing,
38 // the functions themselves do not check if they are being called
39 // from an (un)restricted context. This line must be here or all
40 // methods will be allowed to be called freely.
41 if request.body.is_restricted() && handler.is_restricted() {
42 // The error when a restricted JSON-RPC method is called as per:
43 //
44 // - <https://github.com/monero-project/monero/blob/893916ad091a92e765ce3241b94e706ad012b62a/contrib/epee/include/net/http_server_handlers_map2.h#L244-L252>
45 // - <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.h#L188>
46 return Ok(Json(Response::method_not_found(id)));
47 }
48
49 // Send request.
50 let Ok(response) = handler.oneshot(request.body).await else {
51 return Err(StatusCode::INTERNAL_SERVER_ERROR);
52 };
53
54 Ok(Json(Response::ok(id, response)))
55}
56
57//---------------------------------------------------------------------------------------------------- Tests
58#[cfg(test)]
59mod test {
60 // use super::*;
61}