1#[cfg(feature = "server")]
7use self::{
8 group_service::GroupService, notification::Notification, session_service::SessionService,
9};
10#[cfg(feature = "server")]
11use crate::state::{ClientId, State};
12#[cfg(feature = "server")]
13use axum::async_trait;
14#[cfg(feature = "server")]
15use std::{collections::HashMap, sync::Arc};
16
17pub mod group_service;
18pub mod notification;
19pub mod session_service;
20
21pub const SUBROUTE_SEPARATOR: &str = "_";
23
24#[cfg(feature = "server")]
25type ServiceResponse = Result<Option<json_rpc2::Response>, json_rpc2::Error>;
26
27#[async_trait]
29#[cfg(feature = "server")]
30pub trait Service: Send + Sync {
31 async fn handle(
39 &self,
40 request: &json_rpc2::Request,
41 ctx: (Arc<State>, Arc<tokio::sync::Mutex<Vec<Notification>>>),
42 client_id: ClientId,
43 ) -> Result<Option<json_rpc2::Response>, json_rpc2::Error>;
44}
45
46#[cfg(feature = "server")]
49pub struct ServiceHandler {
50 services: HashMap<String, Box<dyn Service>>,
52}
53
54#[cfg(feature = "server")]
55impl ServiceHandler {
56 pub fn new() -> Self {
58 let mut services: HashMap<String, Box<dyn Service>> = HashMap::new();
59 let group_service: Box<dyn Service> = Box::new(GroupService {});
60 let session_service: Box<dyn Service> = Box::new(SessionService {});
61 services.insert(group_service::ROUTE_PREFIX.into(), group_service);
62 services.insert(session_service::ROUTE_PREFIX.into(), session_service);
63 Self { services }
64 }
65
66 pub async fn serve(
70 &self,
71 request: &json_rpc2::Request,
72 ctx: (Arc<State>, Arc<tokio::sync::Mutex<Vec<Notification>>>),
73 client_id: ClientId,
74 ) -> Option<json_rpc2::Response> {
75 match self.handle(request, ctx, client_id).await {
76 Ok(response) => response,
77 Err(e) => Some((request, e).into()),
78 }
79 }
80
81 async fn handle(
86 &self,
87 req: &json_rpc2::Request,
88 ctx: (Arc<State>, Arc<tokio::sync::Mutex<Vec<Notification>>>),
89 client_id: ClientId,
90 ) -> Result<Option<json_rpc2::Response>, json_rpc2::Error> {
91 let subroute = req.method().split(SUBROUTE_SEPARATOR);
92 let subroute: Vec<&str> = subroute.collect();
93
94 if subroute.len() < 2 {
95 return Ok(Some(self.build_error_not_found_method(req)));
96 }
97
98 let subroute = subroute[0];
99 if let Some(service) = self.services.get(subroute) {
100 return service.handle(req, ctx, client_id).await;
101 }
102
103 Ok(Some(self.build_error_not_found_method(req)))
104 }
105
106 fn build_error_not_found_method(&self, req: &json_rpc2::Request) -> json_rpc2::Response {
108 let err = json_rpc2::Error::MethodNotFound {
109 name: req.method().to_string(),
110 id: req.id().clone(),
111 };
112 (req, err).into()
113 }
114}
115
116#[cfg(feature = "server")]
117impl Default for ServiceHandler {
118 fn default() -> Self {
119 Self::new()
120 }
121}