#[cfg(all(test, feature = "support-axum", feature = "support-tungstenite"))]
mod tests {
use axum::{extract::ws::WebSocketUpgrade, response::Response, routing::get, Router};
use futures_util::{SinkExt, StreamExt};
use std::net::SocketAddr;
use tokio::net::TcpStream;
use tokio_tungstenite::client_async;
use tokio_tungstenite::tungstenite::http::StatusCode;
use tokio_tungstenite::tungstenite::Message;
use yerpc::axum::handle_ws_rpc;
use yerpc::tungstenite::tungstenite_client;
use yerpc::{rpc, RpcClient, RpcSession};
struct Api;
impl Api {
pub fn new() -> Self {
Self
}
}
#[rpc(all_positional, ts_outdir = "typescript/generated")]
impl Api {
async fn shout(&self, msg: String) -> String {
msg.to_uppercase()
}
async fn add(&self, a: f32, b: f32) -> f32 {
a + b
}
}
async fn handler(ws: WebSocketUpgrade) -> Response {
let (client, out_receiver) = RpcClient::new();
let api = Api::new();
let session = RpcSession::new(client, api);
handle_ws_rpc(ws, out_receiver, session).await
}
#[tokio::test]
async fn test_axum_websocket() -> anyhow::Result<()> {
let app = Router::new().route("/rpc", get(handler));
let addr = SocketAddr::from(([127, 0, 0, 1], 12345));
let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
tokio::spawn(async move {
axum::serve(listener, app).await.unwrap();
});
let tcp = TcpStream::connect("127.0.0.1:12345")
.await
.expect("Failed to connect");
let url = "ws://localhost:12345/rpc";
let (mut stream, response) = client_async(url, tcp)
.await
.expect("Client failed to connect");
assert_eq!(response.status(), StatusCode::SWITCHING_PROTOCOLS);
stream
.send(Message::Text(
r#"{"jsonrpc":"2.0","method":"shout","params":["foo"],"id":2}"#.into(),
))
.await?;
let res = stream.next().await.unwrap().unwrap();
match res {
Message::Text(text) => {
assert_eq!(text, r#"{"jsonrpc":"2.0","id":2,"result":"FOO"}"#);
}
_ => panic!("Received unexepcted message {:?}", res),
}
let (client, _on_close) = tungstenite_client(stream, ());
let res = client.send_request("add", Some([1.2, 2.3])).await?;
let res: f32 = serde_json::from_value(res).unwrap();
assert_eq!(res, 3.5);
let res: String =
serde_json::from_value(client.send_request("shout", Some(["foo"])).await?)?;
assert_eq!(res.as_str(), "FOO");
Ok(())
}
}