arpy_actix/
lib.rs

1//! # Arpy Actix
2//!
3//! [`arpy`] integration for [`actix_web`].
4//!
5//! ## Example
6//!
7//! ```
8#![doc = include_doc::function_body!("tests/doc.rs", router_example, [my_add, MyAdd])]
9//! ```
10use std::sync::Arc;
11
12use actix_web::{
13    dev::{ServiceFactory, ServiceRequest},
14    web::{self},
15    App, Error, HttpRequest,
16};
17use arpy::FnRemote;
18use arpy_server::{FnRemoteBody, WebSocketRouter};
19use websocket::WebSocketHandler;
20
21pub mod http;
22mod websocket;
23
24/// Extension trait to add RPC routes. See [module level documentation][crate]
25/// for an example.
26pub trait RpcApp {
27    /// Add an HTTP route to handle a single RPC endpoint.
28    ///
29    /// Routes are constructed with `"{prefix}/{msg_id}"` where `msg_id = T::ID`
30    /// from [`MsgId`][arpy::protocol::MsgId].
31    fn http_rpc_route<F, T>(self, prefix: &str, f: F) -> Self
32    where
33        F: FnRemoteBody<T> + 'static,
34        T: FnRemote + 'static;
35
36    /// Add all the RPC endpoints in `router` to a websocket endpoint at `path`.
37    fn ws_rpc_route(self, path: &str, router: WebSocketRouter, max_in_flight: usize) -> Self;
38}
39
40impl<S> RpcApp for App<S>
41where
42    S: ServiceFactory<ServiceRequest, Config = (), Error = Error, InitError = ()>,
43{
44    fn http_rpc_route<F, T>(self, prefix: &str, f: F) -> Self
45    where
46        F: FnRemoteBody<T> + 'static,
47        T: FnRemote + 'static,
48    {
49        let id = T::ID;
50        let f = Arc::new(f);
51
52        self.route(
53            &format!("{prefix}/{id}"),
54            web::post().to(move |request| http::handler(f.clone(), request)),
55        )
56    }
57
58    fn ws_rpc_route(self, path: &str, router: WebSocketRouter, max_in_flight: usize) -> Self {
59        let handler = WebSocketHandler::new(router, max_in_flight);
60        self.route(
61            path,
62            web::get().to(move |req: HttpRequest, body: web::Payload| {
63                let handler = handler.clone();
64                websocket::handler(handler, req, body)
65            }),
66        )
67    }
68}