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}