From b21a03ce6005e6c3a53894f6dfa061572e4c2ad0 Mon Sep 17 00:00:00 2001 From: David Palm Date: Mon, 15 Nov 2021 19:22:27 +0100 Subject: [PATCH] Implement SubscriptionClient for HttpClient Closes https://github.com/paritytech/jsonrpsee/issues/448 This PR adds an implementation for `SubscriptionClient` to the `HttpClient` struct, which makes it possible for http clients to use macro-generated RPC servers. If an http client tries to set up a subscription it will fail with a `HttpNotImplemented` error. --- http-client/src/client.rs | 28 ++++++++++++++++++++++++++-- tests/tests/proc_macros.rs | 21 ++++++++++++++++++++- types/src/error.rs | 3 +++ 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/http-client/src/client.rs b/http-client/src/client.rs index dca85ce2e1..300c248d5e 100644 --- a/http-client/src/client.rs +++ b/http-client/src/client.rs @@ -26,9 +26,9 @@ use crate::transport::HttpTransportClient; use crate::types::{ - traits::Client, + traits::{Client, SubscriptionClient}, v2::{Id, NotificationSer, ParamsSer, RequestSer, Response, RpcError}, - CertificateStore, Error, RequestIdManager, TEN_MB_SIZE_BYTES, + CertificateStore, Error, RequestIdManager, Subscription, TEN_MB_SIZE_BYTES, }; use async_trait::async_trait; use fnv::FnvHashMap; @@ -194,3 +194,27 @@ impl Client for HttpClient { Ok(responses) } } + +#[async_trait] +impl SubscriptionClient for HttpClient { + /// Send a subscription request to the server. Not implemented for HTTP; will always return [`Error::HttpNotImplemented`]. + async fn subscribe<'a, N>( + &self, + _subscribe_method: &'a str, + _params: Option>, + _unsubscribe_method: &'a str, + ) -> Result, Error> + where + N: DeserializeOwned, + { + Err(Error::HttpNotImplemented) + } + + /// Subscribe to a specific method. Not implemented for HTTP; will always return [`Error::HttpNotImplemented`]. + async fn subscribe_to_method<'a, N>(&self, _method: &'a str) -> Result, Error> + where + N: DeserializeOwned, + { + Err(Error::HttpNotImplemented) + } +} diff --git a/tests/tests/proc_macros.rs b/tests/tests/proc_macros.rs index 84f9a313ec..2597e8caf1 100644 --- a/tests/tests/proc_macros.rs +++ b/tests/tests/proc_macros.rs @@ -28,7 +28,11 @@ use std::net::SocketAddr; -use jsonrpsee::{ws_client::*, ws_server::WsServerBuilder}; +use jsonrpsee::{ + http_client::HttpClientBuilder, http_server::HttpServerBuilder, types::Error, ws_client::*, + ws_server::WsServerBuilder, +}; + use serde_json::value::RawValue; mod rpc_impl { @@ -305,3 +309,18 @@ async fn multiple_blocking_calls_overlap() { // Each request takes 50ms, added 10ms margin for scheduling assert!(elapsed < Duration::from_millis(60), "Expected less than 60ms, got {:?}", elapsed); } + +#[tokio::test] +async fn subscriptions_do_not_work_for_http_servers() { + let htserver = HttpServerBuilder::default().build("127.0.0.1:0".parse().unwrap()).unwrap(); + let addr = htserver.local_addr().unwrap(); + let htserver_url = format!("http://{}", addr); + let _handle = htserver.start(RpcServerImpl.into_rpc()).unwrap(); + + let htclient = HttpClientBuilder::default().build(&htserver_url).unwrap(); + + assert_eq!(htclient.sync_method().await.unwrap(), 10); + assert!(htclient.sub().await.is_err()); + assert!(matches!(htclient.sub().await, Err(Error::HttpNotImplemented))); + assert_eq!(htclient.sync_method().await.unwrap(), 10); +} diff --git a/types/src/error.rs b/types/src/error.rs index c0fc7e865b..16ea73b452 100644 --- a/types/src/error.rs +++ b/types/src/error.rs @@ -160,6 +160,9 @@ pub enum Error { /// Custom error. #[error("Custom error: {0}")] Custom(String), + /// Not implemented for HTTP clients. + #[error("Not implemented")] + HttpNotImplemented, } impl Error {