1use crate::{
2 error::{RpcError, ServerKind},
3 middleware::{RethAuthHttpMiddleware, RethRpcMiddleware},
4};
5use http::header::AUTHORIZATION;
6use jsonrpsee::{
7 core::{client::SubscriptionClientT, RegisterMethodError},
8 http_client::HeaderMap,
9 server::{AlreadyStoppedError, RpcModule, ServerConfig, ServerConfigBuilder},
10 ws_client::RpcServiceBuilder,
11 Methods,
12};
13use reth_rpc_api::servers::*;
14use reth_rpc_eth_types::EthSubscriptionIdProvider;
15use reth_rpc_layer::{
16 secret_to_bearer_header, AuthClientLayer, AuthLayer, JwtAuthValidator, JwtSecret,
17};
18use reth_rpc_server_types::constants;
19use std::net::{IpAddr, Ipv4Addr, SocketAddr};
20use tower::layer::util::Identity;
21
22pub use jsonrpsee::server::ServerBuilder;
23pub use reth_ipc::server::Builder as IpcServerBuilder;
24
25#[derive(Debug)]
27pub struct AuthServerConfig<RpcMiddleware = Identity, HttpMiddleware = Identity> {
28 pub(crate) socket_addr: SocketAddr,
30 pub(crate) secret: JwtSecret,
32 pub(crate) server_config: ServerConfigBuilder,
34 pub(crate) ipc_server_config: Option<IpcServerBuilder<Identity, Identity>>,
36 pub(crate) ipc_endpoint: Option<String>,
38 pub(crate) rpc_middleware: RpcMiddleware,
40 pub(crate) http_middleware: HttpMiddleware,
42}
43
44impl AuthServerConfig {
47 pub const fn builder(secret: JwtSecret) -> AuthServerConfigBuilder {
49 AuthServerConfigBuilder::new(secret)
50 }
51}
52impl<RpcMiddleware, HttpMiddleware> AuthServerConfig<RpcMiddleware, HttpMiddleware> {
53 pub const fn address(&self) -> SocketAddr {
55 self.socket_addr
56 }
57
58 pub fn with_rpc_middleware<T>(self, rpc_middleware: T) -> AuthServerConfig<T, HttpMiddleware> {
60 let Self {
61 socket_addr,
62 secret,
63 server_config,
64 ipc_server_config,
65 ipc_endpoint,
66 http_middleware,
67 ..
68 } = self;
69 AuthServerConfig {
70 socket_addr,
71 secret,
72 server_config,
73 ipc_server_config,
74 ipc_endpoint,
75 rpc_middleware,
76 http_middleware,
77 }
78 }
79
80 pub fn with_http_middleware<T>(self, http_middleware: T) -> AuthServerConfig<RpcMiddleware, T> {
85 let Self {
86 socket_addr,
87 secret,
88 server_config,
89 ipc_server_config,
90 ipc_endpoint,
91 rpc_middleware,
92 ..
93 } = self;
94 AuthServerConfig {
95 socket_addr,
96 secret,
97 server_config,
98 ipc_server_config,
99 ipc_endpoint,
100 rpc_middleware,
101 http_middleware,
102 }
103 }
104
105 pub async fn start(self, module: AuthRpcModule) -> Result<AuthServerHandle, RpcError>
111 where
112 RpcMiddleware: RethRpcMiddleware,
113 HttpMiddleware: RethAuthHttpMiddleware<RpcMiddleware>,
114 {
115 let Self {
116 socket_addr,
117 secret,
118 server_config,
119 ipc_server_config,
120 ipc_endpoint,
121 rpc_middleware,
122 http_middleware,
123 } = self;
124
125 let middleware =
128 tower::ServiceBuilder::new().layer(AuthHttpLayer::new(secret, http_middleware));
129
130 let rpc_middleware = RpcServiceBuilder::default().layer(rpc_middleware);
131
132 let server = ServerBuilder::new()
134 .set_config(server_config.build())
135 .set_http_middleware(middleware)
136 .set_rpc_middleware(rpc_middleware)
137 .build(socket_addr)
138 .await
139 .map_err(|err| RpcError::server_error(err, ServerKind::Auth(socket_addr)))?;
140
141 let local_addr = server
142 .local_addr()
143 .map_err(|err| RpcError::server_error(err, ServerKind::Auth(socket_addr)))?;
144
145 let handle = server.start(module.inner.clone());
146
147 let ipc_handle = if let Some(ipc_server_config) = ipc_server_config {
148 let ipc_endpoint_str = ipc_endpoint
149 .clone()
150 .unwrap_or_else(|| constants::DEFAULT_ENGINE_API_IPC_ENDPOINT.to_string());
151 let ipc_server = ipc_server_config.build(ipc_endpoint_str);
152 let res = ipc_server.start(module.inner).await?;
153 Some(res)
154 } else {
155 None
156 };
157
158 Ok(AuthServerHandle { handle: Some(handle), local_addr, secret, ipc_endpoint, ipc_handle })
159 }
160}
161
162struct AuthHttpLayer<HttpMiddleware> {
168 auth_layer: AuthLayer<JwtAuthValidator>,
169 http_middleware: HttpMiddleware,
170}
171
172impl<HttpMiddleware> AuthHttpLayer<HttpMiddleware> {
173 const fn new(secret: JwtSecret, http_middleware: HttpMiddleware) -> Self {
174 Self { auth_layer: AuthLayer::new(JwtAuthValidator::new(secret)), http_middleware }
175 }
176}
177
178impl<S, HttpMiddleware> tower::Layer<S> for AuthHttpLayer<HttpMiddleware>
179where
180 HttpMiddleware: tower::Layer<S> + Clone,
181 AuthLayer<JwtAuthValidator>: tower::Layer<<HttpMiddleware as tower::Layer<S>>::Service>,
182{
183 type Service = <AuthLayer<JwtAuthValidator> as tower::Layer<
184 <HttpMiddleware as tower::Layer<S>>::Service,
185 >>::Service;
186
187 fn layer(&self, inner: S) -> Self::Service {
188 let http_service = self.http_middleware.layer(inner);
189 self.auth_layer.layer(http_service)
190 }
191}
192
193#[derive(Debug)]
195pub struct AuthServerConfigBuilder<RpcMiddleware = Identity, HttpMiddleware = Identity> {
196 socket_addr: Option<SocketAddr>,
197 secret: JwtSecret,
198 server_config: Option<ServerConfigBuilder>,
199 ipc_server_config: Option<IpcServerBuilder<Identity, Identity>>,
200 ipc_endpoint: Option<String>,
201 rpc_middleware: RpcMiddleware,
202 http_middleware: HttpMiddleware,
203}
204
205impl AuthServerConfigBuilder {
208 pub const fn new(secret: JwtSecret) -> Self {
210 Self {
211 socket_addr: None,
212 secret,
213 server_config: None,
214 ipc_server_config: None,
215 ipc_endpoint: None,
216 rpc_middleware: Identity::new(),
217 http_middleware: Identity::new(),
218 }
219 }
220}
221
222impl<RpcMiddleware, HttpMiddleware> AuthServerConfigBuilder<RpcMiddleware, HttpMiddleware> {
223 pub fn with_rpc_middleware<T>(
225 self,
226 rpc_middleware: T,
227 ) -> AuthServerConfigBuilder<T, HttpMiddleware> {
228 let Self {
229 socket_addr,
230 secret,
231 server_config,
232 ipc_server_config,
233 ipc_endpoint,
234 http_middleware,
235 ..
236 } = self;
237 AuthServerConfigBuilder {
238 socket_addr,
239 secret,
240 server_config,
241 ipc_server_config,
242 ipc_endpoint,
243 rpc_middleware,
244 http_middleware,
245 }
246 }
247
248 pub fn with_http_middleware<T>(
253 self,
254 http_middleware: T,
255 ) -> AuthServerConfigBuilder<RpcMiddleware, T> {
256 let Self {
257 socket_addr,
258 secret,
259 server_config,
260 ipc_server_config,
261 ipc_endpoint,
262 rpc_middleware,
263 ..
264 } = self;
265 AuthServerConfigBuilder {
266 socket_addr,
267 secret,
268 server_config,
269 ipc_server_config,
270 ipc_endpoint,
271 rpc_middleware,
272 http_middleware,
273 }
274 }
275
276 pub const fn socket_addr(mut self, socket_addr: SocketAddr) -> Self {
278 self.socket_addr = Some(socket_addr);
279 self
280 }
281
282 pub const fn maybe_socket_addr(mut self, socket_addr: Option<SocketAddr>) -> Self {
284 self.socket_addr = socket_addr;
285 self
286 }
287
288 pub const fn secret(mut self, secret: JwtSecret) -> Self {
290 self.secret = secret;
291 self
292 }
293
294 pub fn with_server_config(mut self, config: ServerConfigBuilder) -> Self {
299 self.server_config = Some(config.set_id_provider(EthSubscriptionIdProvider::default()));
300 self
301 }
302
303 pub fn ipc_endpoint(mut self, ipc_endpoint: String) -> Self {
305 self.ipc_endpoint = Some(ipc_endpoint);
306 self
307 }
308
309 pub fn with_ipc_config(mut self, config: IpcServerBuilder<Identity, Identity>) -> Self {
313 self.ipc_server_config = Some(config.set_id_provider(EthSubscriptionIdProvider::default()));
314 self
315 }
316
317 pub fn build(self) -> AuthServerConfig<RpcMiddleware, HttpMiddleware> {
319 AuthServerConfig {
320 socket_addr: self.socket_addr.unwrap_or_else(|| {
321 SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), constants::DEFAULT_AUTH_PORT)
322 }),
323 secret: self.secret,
324 server_config: self.server_config.unwrap_or_else(|| {
325 ServerConfig::builder()
326 .max_response_body_size(750 * 1024 * 1024)
331 .max_connections(500)
337 .max_request_body_size(128 * 1024 * 1024)
340 .set_id_provider(EthSubscriptionIdProvider::default())
341 }),
342 ipc_server_config: self.ipc_server_config.map(|ipc_server_config| {
343 ipc_server_config
344 .max_response_body_size(750 * 1024 * 1024)
345 .max_connections(500)
346 .max_request_body_size(128 * 1024 * 1024)
347 .set_id_provider(EthSubscriptionIdProvider::default())
348 }),
349 ipc_endpoint: self.ipc_endpoint,
350 rpc_middleware: self.rpc_middleware,
351 http_middleware: self.http_middleware,
352 }
353 }
354}
355
356#[derive(Debug, Clone)]
358pub struct AuthRpcModule {
359 pub(crate) inner: RpcModule<()>,
360}
361
362impl AuthRpcModule {
363 pub fn new(engine: impl IntoEngineApiRpcModule) -> Self {
365 Self { inner: engine.into_rpc_module() }
366 }
367
368 pub const fn module_mut(&mut self) -> &mut RpcModule<()> {
370 &mut self.inner
371 }
372
373 pub fn merge_auth_methods(
377 &mut self,
378 other: impl Into<Methods>,
379 ) -> Result<bool, RegisterMethodError> {
380 self.module_mut().merge(other.into()).map(|_| true)
381 }
382
383 pub fn remove_auth_method(&mut self, method_name: &'static str) -> bool {
387 self.module_mut().remove_method(method_name).is_some()
388 }
389
390 pub fn remove_auth_methods(&mut self, methods: impl IntoIterator<Item = &'static str>) {
392 for name in methods {
393 self.remove_auth_method(name);
394 }
395 }
396
397 pub fn replace_auth_methods(
399 &mut self,
400 other: impl Into<Methods>,
401 ) -> Result<bool, RegisterMethodError> {
402 let other = other.into();
403 self.remove_auth_methods(other.method_names());
404 self.merge_auth_methods(other)
405 }
406
407 pub async fn start_server<RpcMiddleware, HttpMiddleware>(
409 self,
410 config: AuthServerConfig<RpcMiddleware, HttpMiddleware>,
411 ) -> Result<AuthServerHandle, RpcError>
412 where
413 RpcMiddleware: RethRpcMiddleware,
414 HttpMiddleware: RethAuthHttpMiddleware<RpcMiddleware>,
415 {
416 config.start(self).await
417 }
418}
419
420#[derive(Clone, Debug)]
425#[must_use = "Server stops if dropped"]
426pub struct AuthServerHandle {
427 local_addr: SocketAddr,
428 handle: Option<jsonrpsee::server::ServerHandle>,
429 secret: JwtSecret,
430 ipc_endpoint: Option<String>,
431 ipc_handle: Option<jsonrpsee::server::ServerHandle>,
432}
433
434impl AuthServerHandle {
437 pub fn noop() -> Self {
441 Self {
442 local_addr: SocketAddr::new(
443 IpAddr::V4(Ipv4Addr::LOCALHOST),
444 constants::DEFAULT_AUTH_PORT,
445 ),
446 handle: None,
447 secret: JwtSecret::random(),
448 ipc_endpoint: None,
449 ipc_handle: None,
450 }
451 }
452
453 pub const fn local_addr(&self) -> SocketAddr {
455 self.local_addr
456 }
457
458 pub fn stop(self) -> Result<(), AlreadyStoppedError> {
460 if let Some(handle) = self.handle {
461 handle.stop()?;
462 }
463
464 if let Some(ipc_handle) = self.ipc_handle {
465 ipc_handle.stop()?;
466 }
467
468 Ok(())
469 }
470
471 pub fn http_url(&self) -> String {
473 format!("http://{}", self.local_addr)
474 }
475
476 pub fn ws_url(&self) -> String {
478 format!("ws://{}", self.local_addr)
479 }
480
481 pub fn http_client(
485 &self,
486 ) -> impl SubscriptionClientT + use<> + Clone + Send + Sync + Unpin + 'static {
487 let secret_layer = AuthClientLayer::new(self.secret);
489 let middleware = tower::ServiceBuilder::default().layer(secret_layer);
490 jsonrpsee::http_client::HttpClientBuilder::default()
491 .set_http_middleware(middleware)
492 .build(self.http_url())
493 .expect("Failed to create http client")
494 }
495
496 pub async fn ws_client(&self) -> jsonrpsee::ws_client::WsClient {
499 jsonrpsee::ws_client::WsClientBuilder::default()
500 .set_headers(HeaderMap::from_iter([(
501 AUTHORIZATION,
502 secret_to_bearer_header(&self.secret),
503 )]))
504 .build(self.ws_url())
505 .await
506 .expect("Failed to create ws client")
507 }
508
509 #[cfg(unix)]
511 pub async fn ipc_client(&self) -> Option<jsonrpsee::async_client::Client> {
512 use reth_ipc::client::IpcClientBuilder;
513
514 if let Some(ipc_endpoint) = &self.ipc_endpoint {
515 return Some(
516 IpcClientBuilder::default()
517 .build(ipc_endpoint)
518 .await
519 .expect("Failed to create ipc client"),
520 );
521 }
522 None
523 }
524
525 pub fn ipc_handle(&self) -> Option<jsonrpsee::server::ServerHandle> {
527 self.ipc_handle.clone()
528 }
529
530 pub fn ipc_endpoint(&self) -> Option<String> {
532 self.ipc_endpoint.clone()
533 }
534}