1use crate::{
2 error::{RpcError, ServerKind},
3 middleware::{RethAuthHttpMiddleware, RethRpcMiddleware},
4};
5use alloy_provider::{IpcConnect, WsConnect};
6use alloy_rpc_client::{ClientBuilder, RpcClient};
7use alloy_transport::Authorization;
8use jsonrpsee::{
9 core::RegisterMethodError,
10 server::{
11 middleware::rpc::RpcServiceBuilder, AlreadyStoppedError, RpcModule, ServerConfig,
12 ServerConfigBuilder,
13 },
14 Methods,
15};
16use reth_rpc_api::servers::*;
17use reth_rpc_eth_types::EthSubscriptionIdProvider;
18use reth_rpc_layer::{
19 secret_to_bearer_header, AuthClientLayer, AuthLayer, JwtAuthValidator, JwtSecret,
20};
21use reth_rpc_server_types::constants;
22use std::net::{IpAddr, Ipv4Addr, SocketAddr};
23use tower::layer::util::{Identity, Stack};
24
25pub use jsonrpsee::server::ServerBuilder;
26pub use reth_ipc::server::Builder as IpcServerBuilder;
27
28#[derive(Debug)]
30pub struct AuthServerConfig<RpcMiddleware = Identity, HttpMiddleware = Identity> {
31 pub(crate) socket_addr: SocketAddr,
33 pub(crate) secret: JwtSecret,
35 pub(crate) server_config: ServerConfigBuilder,
37 pub(crate) ipc_server_config: Option<IpcServerBuilder<Identity>>,
39 pub(crate) ipc_endpoint: Option<String>,
41 pub(crate) rpc_middleware: RpcMiddleware,
43 pub(crate) http_middleware: HttpMiddleware,
45}
46
47impl AuthServerConfig {
50 pub const fn builder(secret: JwtSecret) -> AuthServerConfigBuilder {
52 AuthServerConfigBuilder::new(secret)
53 }
54}
55impl<RpcMiddleware, HttpMiddleware> AuthServerConfig<RpcMiddleware, HttpMiddleware> {
56 pub const fn address(&self) -> SocketAddr {
58 self.socket_addr
59 }
60
61 pub fn with_rpc_middleware<T>(self, rpc_middleware: T) -> AuthServerConfig<T, HttpMiddleware> {
63 let Self {
64 socket_addr,
65 secret,
66 server_config,
67 ipc_server_config,
68 ipc_endpoint,
69 http_middleware,
70 ..
71 } = self;
72 AuthServerConfig {
73 socket_addr,
74 secret,
75 server_config,
76 ipc_server_config,
77 ipc_endpoint,
78 rpc_middleware,
79 http_middleware,
80 }
81 }
82
83 pub fn with_http_middleware<T>(self, http_middleware: T) -> AuthServerConfig<RpcMiddleware, T> {
88 let Self {
89 socket_addr,
90 secret,
91 server_config,
92 ipc_server_config,
93 ipc_endpoint,
94 rpc_middleware,
95 ..
96 } = self;
97 AuthServerConfig {
98 socket_addr,
99 secret,
100 server_config,
101 ipc_server_config,
102 ipc_endpoint,
103 rpc_middleware,
104 http_middleware,
105 }
106 }
107
108 pub async fn start(self, module: AuthRpcModule) -> Result<AuthServerHandle, RpcError>
114 where
115 RpcMiddleware: RethRpcMiddleware,
116 HttpMiddleware: RethAuthHttpMiddleware<RpcMiddleware>,
117 {
118 let Self {
119 socket_addr,
120 secret,
121 server_config,
122 ipc_server_config,
123 ipc_endpoint,
124 rpc_middleware,
125 http_middleware,
126 } = self;
127
128 let middleware = tower::ServiceBuilder::new()
131 .layer(Stack::new(http_middleware, AuthLayer::new(JwtAuthValidator::new(secret))));
132
133 let rpc_middleware = RpcServiceBuilder::default().layer(rpc_middleware);
134
135 let server = ServerBuilder::new()
137 .set_config(server_config.build())
138 .set_http_middleware(middleware)
139 .set_rpc_middleware(rpc_middleware)
140 .build(socket_addr)
141 .await
142 .map_err(|err| RpcError::server_error(err, ServerKind::Auth(socket_addr)))?;
143
144 let local_addr = server
145 .local_addr()
146 .map_err(|err| RpcError::server_error(err, ServerKind::Auth(socket_addr)))?;
147
148 let handle = server.start(module.inner.clone());
149
150 let ipc_handle = if let Some(ipc_server_config) = ipc_server_config {
151 let ipc_endpoint_str = ipc_endpoint
152 .clone()
153 .unwrap_or_else(|| constants::DEFAULT_ENGINE_API_IPC_ENDPOINT.to_string());
154 let ipc_server = ipc_server_config.build(ipc_endpoint_str);
155 let res = ipc_server.start(module.inner).await?;
156 Some(res)
157 } else {
158 None
159 };
160
161 Ok(AuthServerHandle { handle: Some(handle), local_addr, secret, ipc_endpoint, ipc_handle })
162 }
163}
164
165#[derive(Debug)]
167pub struct AuthServerConfigBuilder<RpcMiddleware = Identity, HttpMiddleware = Identity> {
168 socket_addr: Option<SocketAddr>,
169 secret: JwtSecret,
170 server_config: Option<ServerConfigBuilder>,
171 ipc_server_config: Option<IpcServerBuilder<Identity>>,
172 ipc_endpoint: Option<String>,
173 rpc_middleware: RpcMiddleware,
174 http_middleware: HttpMiddleware,
175}
176
177impl AuthServerConfigBuilder {
180 pub const fn new(secret: JwtSecret) -> Self {
182 Self {
183 socket_addr: None,
184 secret,
185 server_config: None,
186 ipc_server_config: None,
187 ipc_endpoint: None,
188 rpc_middleware: Identity::new(),
189 http_middleware: Identity::new(),
190 }
191 }
192}
193
194impl<RpcMiddleware, HttpMiddleware> AuthServerConfigBuilder<RpcMiddleware, HttpMiddleware> {
195 pub fn with_rpc_middleware<T>(
197 self,
198 rpc_middleware: T,
199 ) -> AuthServerConfigBuilder<T, HttpMiddleware> {
200 let Self {
201 socket_addr,
202 secret,
203 server_config,
204 ipc_server_config,
205 ipc_endpoint,
206 http_middleware,
207 ..
208 } = self;
209 AuthServerConfigBuilder {
210 socket_addr,
211 secret,
212 server_config,
213 ipc_server_config,
214 ipc_endpoint,
215 rpc_middleware,
216 http_middleware,
217 }
218 }
219
220 pub fn with_http_middleware<T>(
225 self,
226 http_middleware: T,
227 ) -> AuthServerConfigBuilder<RpcMiddleware, T> {
228 let Self {
229 socket_addr,
230 secret,
231 server_config,
232 ipc_server_config,
233 ipc_endpoint,
234 rpc_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 const fn socket_addr(mut self, socket_addr: SocketAddr) -> Self {
250 self.socket_addr = Some(socket_addr);
251 self
252 }
253
254 pub const fn maybe_socket_addr(mut self, socket_addr: Option<SocketAddr>) -> Self {
256 self.socket_addr = socket_addr;
257 self
258 }
259
260 pub const fn secret(mut self, secret: JwtSecret) -> Self {
262 self.secret = secret;
263 self
264 }
265
266 pub fn with_server_config(mut self, config: ServerConfigBuilder) -> Self {
271 self.server_config = Some(config.set_id_provider(EthSubscriptionIdProvider::default()));
272 self
273 }
274
275 pub fn ipc_endpoint(mut self, ipc_endpoint: String) -> Self {
277 self.ipc_endpoint = Some(ipc_endpoint);
278 self
279 }
280
281 pub fn with_ipc_config(mut self, config: IpcServerBuilder<Identity>) -> Self {
285 self.ipc_server_config = Some(config.set_id_provider(EthSubscriptionIdProvider::default()));
286 self
287 }
288
289 pub fn build(self) -> AuthServerConfig<RpcMiddleware, HttpMiddleware> {
291 AuthServerConfig {
292 socket_addr: self.socket_addr.unwrap_or_else(|| {
293 SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), constants::DEFAULT_AUTH_PORT)
294 }),
295 secret: self.secret,
296 server_config: self.server_config.unwrap_or_else(|| {
297 ServerConfig::builder()
298 .max_response_body_size(750 * 1024 * 1024)
303 .max_connections(500)
309 .max_request_body_size(128 * 1024 * 1024)
312 .set_id_provider(EthSubscriptionIdProvider::default())
313 }),
314 ipc_server_config: self.ipc_server_config.map(|ipc_server_config| {
315 ipc_server_config
316 .max_response_body_size(750 * 1024 * 1024)
317 .max_connections(500)
318 .max_request_body_size(128 * 1024 * 1024)
319 .set_id_provider(EthSubscriptionIdProvider::default())
320 }),
321 ipc_endpoint: self.ipc_endpoint,
322 rpc_middleware: self.rpc_middleware,
323 http_middleware: self.http_middleware,
324 }
325 }
326}
327
328#[derive(Debug, Clone)]
330pub struct AuthRpcModule {
331 pub(crate) inner: RpcModule<()>,
332}
333
334impl AuthRpcModule {
335 pub fn new(engine: impl IntoEngineApiRpcModule) -> Self {
337 Self { inner: engine.into_rpc_module() }
338 }
339
340 pub const fn module_mut(&mut self) -> &mut RpcModule<()> {
342 &mut self.inner
343 }
344
345 pub fn merge_auth_methods(
349 &mut self,
350 other: impl Into<Methods>,
351 ) -> Result<bool, RegisterMethodError> {
352 self.module_mut().merge(other.into()).map(|_| true)
353 }
354
355 pub fn remove_auth_method(&mut self, method_name: &'static str) -> bool {
359 self.module_mut().remove_method(method_name).is_some()
360 }
361
362 pub fn remove_auth_methods(&mut self, methods: impl IntoIterator<Item = &'static str>) {
364 for name in methods {
365 self.remove_auth_method(name);
366 }
367 }
368
369 pub fn replace_auth_methods(
371 &mut self,
372 other: impl Into<Methods>,
373 ) -> Result<bool, RegisterMethodError> {
374 let other = other.into();
375 self.remove_auth_methods(other.method_names());
376 self.merge_auth_methods(other)
377 }
378
379 pub async fn start_server<RpcMiddleware, HttpMiddleware>(
381 self,
382 config: AuthServerConfig<RpcMiddleware, HttpMiddleware>,
383 ) -> Result<AuthServerHandle, RpcError>
384 where
385 RpcMiddleware: RethRpcMiddleware,
386 HttpMiddleware: RethAuthHttpMiddleware<RpcMiddleware>,
387 {
388 config.start(self).await
389 }
390}
391
392#[derive(Clone, Debug)]
397#[must_use = "Server stops if dropped"]
398pub struct AuthServerHandle {
399 local_addr: SocketAddr,
400 handle: Option<jsonrpsee::server::ServerHandle>,
401 secret: JwtSecret,
402 ipc_endpoint: Option<String>,
403 ipc_handle: Option<jsonrpsee::server::ServerHandle>,
404}
405
406impl AuthServerHandle {
409 pub fn noop() -> Self {
413 Self {
414 local_addr: SocketAddr::new(
415 IpAddr::V4(Ipv4Addr::LOCALHOST),
416 constants::DEFAULT_AUTH_PORT,
417 ),
418 handle: None,
419 secret: JwtSecret::random(),
420 ipc_endpoint: None,
421 ipc_handle: None,
422 }
423 }
424
425 pub const fn local_addr(&self) -> SocketAddr {
427 self.local_addr
428 }
429
430 pub const fn jwt_secret(&self) -> &JwtSecret {
432 &self.secret
433 }
434
435 pub fn stop(self) -> Result<(), AlreadyStoppedError> {
437 if let Some(handle) = self.handle {
438 handle.stop()?;
439 }
440
441 if let Some(ipc_handle) = self.ipc_handle {
442 ipc_handle.stop()?;
443 }
444
445 Ok(())
446 }
447
448 pub fn http_url(&self) -> String {
450 format!("http://{}", self.local_addr)
451 }
452
453 pub fn ws_url(&self) -> String {
455 format!("ws://{}", self.local_addr)
456 }
457
458 pub fn http_client(&self) -> RpcClient {
462 let url = self.http_url().parse().expect("valid http url");
463 ClientBuilder::default().layer(AuthClientLayer::new(self.secret)).http(url)
464 }
465
466 pub async fn ws_client(&self) -> RpcClient {
469 let header = secret_to_bearer_header(&self.secret);
470 let auth = Authorization::raw(header.to_str().expect("bearer header is ascii"));
471 ClientBuilder::default()
472 .ws(WsConnect::new(self.ws_url()).with_auth(auth))
473 .await
474 .expect("Failed to create ws client")
475 }
476
477 #[cfg(unix)]
479 pub async fn ipc_client(&self) -> Option<RpcClient> {
480 let ipc_endpoint = self.ipc_endpoint.as_ref()?;
481 Some(
482 ClientBuilder::default()
483 .ipc(IpcConnect::new(ipc_endpoint.clone()))
484 .await
485 .expect("Failed to create ipc client"),
486 )
487 }
488
489 pub fn ipc_handle(&self) -> Option<jsonrpsee::server::ServerHandle> {
491 self.ipc_handle.clone()
492 }
493
494 pub fn ipc_endpoint(&self) -> Option<String> {
496 self.ipc_endpoint.clone()
497 }
498}