Unverified Commit 5fd1b9be authored by Niklas Adolfsson's avatar Niklas Adolfsson Committed by GitHub
Browse files

add `jsonrpsee` root crate (#260)



* add wrapper crate

* add jsonrpsee crate back

* [jsonrpsee]: feature gate modules

* [proc macros]: support crate renaming of `types`

* Update proc-macros/src/lib.rs

Co-authored-by: David's avatarDavid <dvdplm@gmail.com>

* re-export types

* [proc macros]: remove unused features

* Update proc-macros/Cargo.toml

* fix bad merge

Co-authored-by: David's avatarDavid <dvdplm@gmail.com>
parent e4c8da50
......@@ -5,7 +5,7 @@ members = [
"http-client",
"http-server",
"test-utils",
"tests",
"jsonrpsee",
"types",
"utils",
"ws-client",
......
......@@ -5,21 +5,16 @@ authors = ["Parity Technologies <admin@parity.io>"]
description = "Benchmarks for jsonrpsee"
edition = "2018"
license = "MIT"
[lib]
bench = false
publish = false
[dev-dependencies]
criterion = "0.3"
futures = "0.3"
jsonrpsee-types = { path = "../types" }
jsonrpsee-http-client = { path = "../http-client" }
jsonrpsee-ws-client = { path = "../ws-client" }
jsonrpsee-ws-server = { path = "../ws-server" }
jsonrpsee-http-server = { path = "../http-server" }
jsonrpsee = { path = "../jsonrpsee", features = ["full"] }
num_cpus = "1"
tokio = { version = "1", features = ["full"] }
[[bench]]
name = "bench"
path = "bench.rs"
harness = false
use criterion::*;
use jsonrpsee_http_client::HttpClientBuilder;
use jsonrpsee_types::{jsonrpc::Params, traits::Client};
use jsonrpsee_ws_client::WsClientBuilder;
use jsonrpsee::{
http_client::{jsonrpc::Params, Client, HttpClientBuilder},
ws_client::WsClientBuilder,
};
use std::sync::Arc;
use tokio::runtime::Runtime as TokioRuntime;
......
use futures::channel::oneshot;
use jsonrpsee_http_server::HttpServerBuilder;
use jsonrpsee_ws_server::WsServer;
use jsonrpsee::{http_server::HttpServerBuilder, ws_server::WsServer};
/// Run jsonrpsee HTTP server for benchmarks.
pub async fn http_server() -> String {
......
......@@ -4,17 +4,24 @@ version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
description = "Examples for jsonrpsee"
edition = "2018"
publish = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
[dev-dependencies]
anyhow = "1"
env_logger = "0.8"
futures = "0.3"
jsonrpsee = { path = "../jsonrpsee", features = ["full"] }
log = "0.4"
jsonrpsee-types = { path = "../types" }
jsonrpsee-http-client = { path = "../http-client" }
jsonrpsee-ws-client = { path = "../ws-client" }
jsonrpsee-ws-server = { path = "../ws-server" }
jsonrpsee-http-server = { path = "../http-server" }
jsonrpsee-proc-macros = { path = "../proc-macros" }
tokio = { version = "1", features = ["full"] }
[[example]]
name = "http"
path = "http.rs"
[[example]]
name = "ws"
path = "ws.rs"
[[example]]
name = "ws_subscription"
path = "ws_subscription.rs"
......@@ -24,17 +24,17 @@
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
use jsonrpsee::{
http_client::{jsonrpc::Params, Client, HttpClientBuilder},
http_server::HttpServerBuilder,
};
use std::net::SocketAddr;
use jsonrpsee_http_client::HttpClientBuilder;
use jsonrpsee_http_server::HttpServerBuilder;
use jsonrpsee_types::{jsonrpc::Params, traits::Client};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
async fn main() -> anyhow::Result<()> {
env_logger::init();
let server_addr = run_server().await;
let server_addr = run_server().await?;
let url = format!("http://{}", server_addr);
let client = HttpClientBuilder::default().build(url)?;
......@@ -44,10 +44,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
Ok(())
}
async fn run_server() -> SocketAddr {
let mut server = HttpServerBuilder::default().build("127.0.0.1:0".parse().unwrap()).unwrap();
server.register_method("say_hello", |_| Ok("lo")).unwrap();
let addr = server.local_addr().unwrap();
tokio::spawn(async move { server.start().await.unwrap() });
async fn run_server() -> anyhow::Result<SocketAddr> {
let mut server = HttpServerBuilder::default().build("127.0.0.1:0".parse()?)?;
server.register_method("say_hello", |_| Ok("lo"))?;
let addr = server.local_addr();
tokio::spawn(async move { server.start().await });
addr
}
......@@ -24,41 +24,30 @@
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
use futures::channel::oneshot::{self, Sender};
use jsonrpsee_types::{
jsonrpc::{JsonValue, Params},
traits::Client,
use jsonrpsee::{
ws_client::{jsonrpc::Params, Client, WsClientBuilder},
ws_server::WsServer,
};
use jsonrpsee_ws_client::WsClientBuilder;
use jsonrpsee_ws_server::WsServer;
use tokio::task;
const SOCK_ADDR: &str = "127.0.0.1:9944";
const SERVER_URI: &str = "ws://localhost:9944";
use std::net::SocketAddr;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
async fn main() -> anyhow::Result<()> {
env_logger::init();
let addr = run_server().await?;
let url = format!("ws://{}", addr);
let (server_started_tx, server_started_rx) = oneshot::channel::<()>();
let _server = task::spawn(async move {
run_server(server_started_tx, SOCK_ADDR).await;
});
server_started_rx.await?;
let client = WsClientBuilder::default().build(SERVER_URI).await?;
let response: JsonValue = client.request("say_hello", Params::None).await?;
let client = WsClientBuilder::default().build(&url).await?;
let response: String = client.request("say_hello", Params::None).await?;
println!("r: {:?}", response);
Ok(())
}
async fn run_server(server_started_tx: Sender<()>, addr: &str) {
let mut server = WsServer::new(addr).await.unwrap();
server.register_method("say_hello", |_| Ok("lo")).unwrap();
server_started_tx.send(()).unwrap();
async fn run_server() -> anyhow::Result<SocketAddr> {
let mut server = WsServer::new("127.0.0.1:0").await?;
server.register_method("say_hello", |_| Ok("lo"))?;
server.start().await;
let addr = server.local_addr();
tokio::spawn(async move { server.start().await });
addr
}
......@@ -24,31 +24,22 @@
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
use futures::channel::oneshot::{self, Sender};
use jsonrpsee_types::{
jsonrpc::{JsonValue, Params},
traits::SubscriptionClient,
use jsonrpsee::{
ws_client::{jsonrpc::Params, SubscriptionClient, WsClientBuilder, WsSubscription},
ws_server::WsServer,
};
use jsonrpsee_ws_client::{WsClientBuilder, WsSubscription};
use jsonrpsee_ws_server::WsServer;
use tokio::task;
use std::net::SocketAddr;
const SOCK_ADDR: &str = "127.0.0.1:9966";
const SERVER_URI: &str = "ws://localhost:9966";
const NUM_SUBSCRIPTION_RESPONSES: usize = 10;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
async fn main() -> anyhow::Result<()> {
env_logger::init();
let addr = run_server().await?;
let url = format!("ws://{}", addr);
let (server_started_tx, server_started_rx) = oneshot::channel::<()>();
let _server = task::spawn(async move {
run_server(server_started_tx, SOCK_ADDR).await;
});
server_started_rx.await?;
let client = WsClientBuilder::default().build(SERVER_URI).await?;
let mut subscribe_hello: WsSubscription<JsonValue> =
let client = WsClientBuilder::default().build(&url).await?;
let mut subscribe_hello: WsSubscription<String> =
client.subscribe("subscribe_hello", Params::None, "unsubscribe_hello").await?;
let mut i = 0;
......@@ -61,9 +52,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
Ok(())
}
async fn run_server(server_started_tx: Sender<()>, url: &str) {
let mut server = WsServer::new(url).await.unwrap();
async fn run_server() -> anyhow::Result<SocketAddr> {
let mut server = WsServer::new("127.0.0.1:0").await?;
let mut subscription = server.register_subscription("subscribe_hello", "unsubscribe_hello").unwrap();
std::thread::spawn(move || loop {
......@@ -71,7 +61,7 @@ async fn run_server(server_started_tx: Sender<()>, url: &str) {
std::thread::sleep(std::time::Duration::from_secs(1));
});
server_started_tx.send(()).unwrap();
server.start().await;
let addr = server.local_addr();
tokio::spawn(async move { server.start().await });
addr
}
......@@ -43,4 +43,4 @@ mod transport;
mod tests;
pub use client::{HttpClient, HttpClientBuilder};
pub use transport::HttpTransportClient;
pub use jsonrpsee_types::{error::Error, jsonrpc, traits::Client};
......@@ -16,7 +16,7 @@ const CONTENT_TYPE_JSON: &str = "application/json";
/// HTTP Transport Client.
#[derive(Debug, Clone)]
pub struct HttpTransportClient {
pub(crate) struct HttpTransportClient {
/// Target to connect to.
target: url::Url,
/// HTTP client
......@@ -27,7 +27,7 @@ pub struct HttpTransportClient {
impl HttpTransportClient {
/// Initializes a new HTTP client.
pub fn new(target: impl AsRef<str>, max_request_body_size: u32) -> Result<Self, Error> {
pub(crate) fn new(target: impl AsRef<str>, max_request_body_size: u32) -> Result<Self, Error> {
let target = url::Url::parse(target.as_ref()).map_err(|e| Error::Url(format!("Invalid URL: {}", e)))?;
if target.scheme() == "http" || target.scheme() == "https" {
#[cfg(feature = "tokio1")]
......@@ -65,13 +65,13 @@ impl HttpTransportClient {
}
/// Send notification.
pub async fn send_notification(&self, request: jsonrpc::Request) -> Result<(), Error> {
pub(crate) async fn send_notification(&self, request: jsonrpc::Request) -> Result<(), Error> {
let _response = self.send_request(request).await?;
Ok(())
}
/// Send request and wait for response.
pub async fn send_request_and_wait_for_response(
pub(crate) async fn send_request_and_wait_for_response(
&self,
request: jsonrpc::Request,
) -> Result<jsonrpc::Response, Error> {
......@@ -89,7 +89,7 @@ impl HttpTransportClient {
/// Error that can happen during a request.
#[derive(Debug, Error)]
pub enum Error {
pub(crate) enum Error {
/// Invalid URL.
#[error("Invalid Url: {0}")]
Url(String),
......@@ -99,10 +99,6 @@ pub enum Error {
#[error("Error while serializing the request")]
Serialization(#[source] serde_json::error::Error),
/// Response given by the server failed to decode as UTF-8.
#[error("Response body is not UTF-8")]
Utf8(#[source] std::string::FromUtf8Error),
/// Error during the HTTP request, including networking errors and HTTP protocol errors.
#[error("Error while performing the HTTP request")]
Http(Box<dyn std::error::Error + Send + Sync>),
......
......@@ -30,6 +30,7 @@ mod response;
mod server;
pub use access_control::{AccessControl, AccessControlBuilder, AllowHosts, Host};
pub use jsonrpsee_types::error::Error;
pub use module::{RpcContextModule, RpcModule};
pub use server::{Builder as HttpServerBuilder, Server as HttpServer};
......
[package]
name = "jsonrpsee"
description = "JSON-RPC crate"
version = "0.2.0-alpha.4"
authors = ["Parity Technologies <admin@parity.io>", "Pierre Krieger <pierre.krieger1708@gmail.com>"]
license = "MIT"
edition = "2018"
[dependencies]
http-client = { path = "../http-client", version = "0.2.0-alpha.4", package = "jsonrpsee-http-client", optional = true }
http-server = { path = "../http-server", version = "0.2.0-alpha.4", package = "jsonrpsee-http-server", optional = true }
ws-client = { path = "../ws-client", version = "0.2.0-alpha.4", package = "jsonrpsee-ws-client", optional = true }
ws-server = { path = "../ws-server", version = "0.2.0-alpha.4", package = "jsonrpsee-ws-server", optional = true }
proc-macros = { path = "../proc-macros", version = "0.2.0-alpha.4", package = "jsonrpsee-proc-macros", optional = true }
[dev-dependencies]
env_logger = "0.8"
futures = "0.3"
log = "0.4"
test-utils = { path = "../test-utils", version = "0.2.0-alpha.4", package = "jsonrpsee-test-utils" }
tokio = { version = "1", features = ["full"] }
[features]
client = ["http-client", "ws-client"]
server = ["http-server", "ws-server"]
macros = ["proc-macros"]
full = ["client", "server", "macros"]
\ No newline at end of file
//! jsonrpsee wrapper crate.
#[cfg(feature = "client")]
pub use http_client;
#[cfg(feature = "client")]
pub use ws_client;
#[cfg(feature = "server")]
pub use http_server;
#[cfg(feature = "server")]
pub use ws_server;
#[cfg(feature = "macros")]
pub use proc_macros;
......@@ -24,14 +24,11 @@
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
use jsonrpsee_http_server::HttpServerBuilder;
use jsonrpsee_ws_server::WsServer;
use futures::channel::oneshot;
use jsonrpsee::{http_server::HttpServerBuilder, ws_server::WsServer};
use std::net::SocketAddr;
use std::time::Duration;
use futures::channel::oneshot;
pub async fn websocket_server_with_subscription() -> SocketAddr {
let (server_started_tx, server_started_rx) = oneshot::channel();
......
......@@ -27,19 +27,17 @@
#![cfg(test)]
mod helpers;
mod proc_macros;
use std::sync::Arc;
use std::time::Duration;
use helpers::{http_server, websocket_server, websocket_server_with_subscription};
use jsonrpsee_http_client::HttpClientBuilder;
use jsonrpsee_types::{
error::Error,
jsonrpc::{JsonValue, Params},
traits::{Client, SubscriptionClient},
use jsonrpsee::{
http_client::{Client, Error, HttpClientBuilder},
ws_client::{
jsonrpc::{JsonValue, Params},
SubscriptionClient, WsClientBuilder, WsSubscription,
},
};
use jsonrpsee_ws_client::{WsClientBuilder, WsSubscription};
use std::sync::Arc;
use std::time::Duration;
#[tokio::test]
async fn ws_subscription_works() {
......
// Not all proc macros are used let's suppress it for now.
#![allow(dead_code)]
use crate::helpers;
use jsonrpsee_http_client::*;
use jsonrpsee_ws_client::*;
mod helpers;
jsonrpsee_proc_macros::rpc_client_api! {
use jsonrpsee::{http_client::*, proc_macros, ws_client::*};
proc_macros::rpc_client_api! {
Test<T> {
fn say_hello() -> T;
}
}
jsonrpsee_proc_macros::rpc_client_api! {
proc_macros::rpc_client_api! {
pub(crate) Test2<B, T> {
#[rpc(method = "say_hello")]
fn foo(b: B) -> T;
}
}
jsonrpsee_proc_macros::rpc_client_api! {
proc_macros::rpc_client_api! {
Author {
#[rpc(method = "author_submitExtrinsic", positional_params)]
fn submit_extrinsic(extrinsic: String) -> u128;
......@@ -42,14 +42,14 @@ jsonrpsee_proc_macros::rpc_client_api! {
}
// https://github.com/paritytech/jsonrpsee/issues/104
jsonrpsee_proc_macros::rpc_client_api! {
proc_macros::rpc_client_api! {
Registrar {
#[rpc(method = "say_hello")]
fn register_para(foo: i32, bar: String);
}
}
jsonrpsee_proc_macros::rpc_client_api! {
proc_macros::rpc_client_api! {
ManyReturnTypes<A, B, C, D, E> {
#[rpc(method = "say_hello")]
fn a() -> A;
......
......@@ -13,4 +13,5 @@ proc-macro = true
Inflector = "0.11.4"
proc-macro2 = "1.0"
quote = "1.0"
syn = { version = "1.0", features = ["full", "extra-traits", "parsing", "printing", "proc-macro", "visit"] }
\ No newline at end of file
syn = { version = "1.0", default-features = false, features = ["extra-traits"] }
proc-macro-crate = "1"
......@@ -28,6 +28,8 @@ extern crate proc_macro;
use inflector::Inflector as _;
use proc_macro::TokenStream;
use proc_macro2::Span;
use proc_macro_crate::{crate_name, FoundCrate};
use quote::{format_ident, quote, quote_spanned};
use std::collections::HashSet;
use syn::spanned::Spanned as _;
......@@ -189,6 +191,14 @@ fn build_client_impl(api: &api_def::ApiDefinition) -> Result<proc_macro2::TokenS
fn build_client_functions(api: &api_def::ApiDefinition) -> Result<Vec<proc_macro2::TokenStream>, syn::Error> {
let visibility = &api.visibility;
let _crate = match (crate_name("jsonrpsee-http-client"), crate_name("jsonrpsee-ws-client")) {
(Ok(FoundCrate::Name(name)), _) => syn::Ident::new(&name, Span::call_site()),
(_, Ok(FoundCrate::Name(name))) => syn::Ident::new(&name, Span::call_site()),
(_, Err(e)) => return Err(syn::Error::new(Span::call_site(), &e)),
(Err(e), _) => return Err(syn::Error::new(Span::call_site(), &e)),
(_, _) => panic!("Deriving RPC methods in the `types` crate is not supported"),
};
let mut client_functions = Vec::new();
for function in &api.definitions {
let f_name = &function.signature.ident;
......@@ -225,27 +235,27 @@ fn build_client_functions(api: &api_def::ApiDefinition) -> Result<Vec<proc_macro
params_to_json.push(quote_spanned!(pat_span=>
map.insert(
#rpc_param_name.to_string(),
jsonrpsee_types::jsonrpc::to_value(#generated_param_name.into()).map_err(|e| jsonrpsee_types::error::Error::Custom(format!("{:?}", e)))?
#_crate::jsonrpc::to_value(#generated_param_name.into()).map_err(|e| #_crate::Error::Custom(format!("{:?}", e)))?
);
));
params_to_array.push(quote_spanned!(pat_span =>
jsonrpsee_types::jsonrpc::to_value(#generated_param_name.into()).map_err(|e| jsonrpsee_types::error::Error::Custom(format!("{:?}", e)))?
#_crate::jsonrpc::to_value(#generated_param_name.into()).map_err(|e| #_crate::Error::Custom(format!("{:?}", e)))?
));
}
let params_building = if params_list.is_empty() {
quote! {jsonrpsee_types::jsonrpc::Params::None}
quote! {#_crate::jsonrpc::Params::None}
} else if function.attributes.positional_params {
quote_spanned!(function.signature.span()=>
jsonrpsee_types::jsonrpc::Params::Array(vec![
#_crate::jsonrpc::Params::Array(vec![
#(#params_to_array),*
])
)
} else {
let params_list_len = params_list.len();
quote_spanned!(function.signature.span()=>
jsonrpsee_types::jsonrpc::Params::Map({
let mut map = jsonrpsee_types::jsonrpc::JsonMap::with_capacity(#params_list_len);
#_crate::jsonrpc::Params::Map({
let mut map = #_crate::jsonrpc::JsonMap::with_capacity(#params_list_len);
#(#params_to_json)*
map
})
......@@ -264,10 +274,10 @@ fn build_client_functions(api: &api_def::ApiDefinition) -> Result<Vec<proc_macro
};
client_functions.push(quote_spanned!(function.signature.span()=>
#visibility async fn #f_name (client: &impl jsonrpsee_types::traits::Client #(, #params_list)*) -> core::result::Result<#ret_ty, jsonrpsee_types::error::Error>
#visibility async fn #f_name (client: &impl #_crate::Client #(, #params_list)*) -> core::result::Result<#ret_ty, #_crate::Error>
where
#ret_ty: jsonrpsee_types::jsonrpc::DeserializeOwned
#(, #params_tys: jsonrpsee_types::jsonrpc::Serialize)*
#ret_ty: #_crate::jsonrpc::DeserializeOwned
#(, #params_tys: #_crate::jsonrpc::Serialize)*
{
#function_body
}
......
[package]
name = "jsonrpsee-test-utils"
version = "0.1.0"
version = "0.2.0-alpha.4"
authors = ["Parity Technologies <admin@parity.io>"]
license = "MIT"
edition = "2018"
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment