1#![cfg_attr(not(test), warn(unused_crate_dependencies))]
4#![cfg_attr(docsrs, feature(doc_cfg))]
5
6#[macro_use]
7extern crate tracing;
8
9use anvil_rpc::{
10 error::RpcError,
11 request::RpcMethodCall,
12 response::{ResponseResult, RpcResponse},
13};
14use axum::{
15 Router,
16 extract::DefaultBodyLimit,
17 http::{HeaderValue, Method, header},
18 routing::{MethodRouter, post},
19};
20use serde::de::DeserializeOwned;
21use std::fmt;
22use tower_http::{cors::CorsLayer, trace::TraceLayer};
23
24mod config;
25pub use config::ServerConfig;
26
27mod error;
28mod handler;
29
30mod pubsub;
31pub use pubsub::{PubSubContext, PubSubRpcHandler};
32
33mod ws;
34
35#[cfg(feature = "ipc")]
36pub mod ipc;
37
38pub trait RpcHandler: Clone + Send + Sync + 'static {
40 type Request: DeserializeOwned + Send + Sync + fmt::Debug;
42
43 fn on_request(&self, request: Self::Request) -> impl Future<Output = ResponseResult> + Send;
45
46 fn on_call(&self, call: RpcMethodCall) -> impl Future<Output = RpcResponse> + Send {
56 async move {
57 trace!(target: "rpc", id = ?call.id , method = ?call.method, params = ?call.params, "received method call");
58 let RpcMethodCall { method, params, id, .. } = call;
59
60 let params: serde_json::Value = params.into();
61 let call = serde_json::json!({
62 "method": &method,
63 "params": params
64 });
65
66 match serde_json::from_value::<Self::Request>(call) {
67 Ok(req) => {
68 let result = self.on_request(req).await;
69 RpcResponse::new(id, result)
70 }
71 Err(err) => {
72 let err = err.to_string();
73 let method_not_found = serde_json::from_value::<Self::Request>(
74 serde_json::json!({ "method": &method }),
75 )
76 .is_err_and(|err| err.to_string().contains("unknown variant"));
77 if method_not_found {
78 error!(target: "rpc", ?method, "failed to deserialize method due to unknown variant");
79 RpcResponse::new(id, RpcError::method_not_found())
80 } else {
81 error!(target: "rpc", ?method, ?err, "failed to deserialize method");
82 RpcResponse::new(id, RpcError::invalid_params(err))
83 }
84 }
85 }
86 }
87 }
88}
89
90pub fn http_ws_router<Http, Ws>(config: ServerConfig, http: Http, ws: Ws) -> Router
92where
93 Http: RpcHandler,
94 Ws: PubSubRpcHandler,
95{
96 router_inner(config, post(handler::handle).get(ws::handle_ws), (http, ws))
97}
98
99pub fn http_router<Http>(config: ServerConfig, http: Http) -> Router
101where
102 Http: RpcHandler,
103{
104 router_inner(config, post(handler::handle), (http, ()))
105}
106
107fn router_inner<S: Clone + Send + Sync + 'static>(
108 config: ServerConfig,
109 root_method_router: MethodRouter<S>,
110 state: S,
111) -> Router {
112 let ServerConfig { allow_origin, no_cors, no_request_size_limit } = config;
113
114 let mut router = Router::new()
115 .route("/", root_method_router)
116 .with_state(state)
117 .layer(TraceLayer::new_for_http());
118 if !no_cors {
119 router = router.layer(
122 CorsLayer::new()
123 .allow_origin(allow_origin.0)
124 .allow_headers([header::CONTENT_TYPE])
125 .allow_methods([Method::GET, Method::POST]),
126 );
127 }
128 if no_request_size_limit {
129 router = router.layer(DefaultBodyLimit::disable());
130 }
131 router
132}