Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Tokio gates `tokio::net` (and friends) on wasm behind `--cfg tokio_unstable`.
# `WasiConnector` in jsonrpsee-http-client uses `tokio::net::TcpStream`, so wasip2
# builds need the flag set. Scope it to the wasm32-wasip2 target so native builds
# keep their cache and don't pick up unstable APIs.
[target.wasm32-wasip2]
rustflags = ["--cfg", "tokio_unstable"]
16 changes: 12 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
[workspace]
members = [
"benches",
"client/http-client",
"client/transport",
"client/wasm-client",
Expand All @@ -16,6 +15,10 @@ members = [
"tests/proc-macro-core",
"types",
]
# benches/ pulls jsonrpc-http-server (hyper 0.14), which pins socket2 to 0.5.x and breaks
# wasm32-wasip2 builds. Keep it out of the workspace so downstream consumers' lockfiles
# aren't poisoned; run benchmarks from inside benches/ with its own lockfile.
exclude = ["benches"]
resolver = "3"

[workspace.package]
Expand Down Expand Up @@ -53,9 +56,12 @@ heck = "0.5.0"
http = "1"
http-body = "1"
http-body-util = "0.1.0"
hyper = "1.5"
cfg_aliases = "0.2"
log = "0.4"
hyper = "1.8"
hyper-rustls = { version = "0.27", default-features = false }
hyper-util = "0.1"
mio = { version = "1.2.0", default-features = false }
parking_lot = "0.12"
pin-project = "1.1.3"
proc-macro-crate = "3"
Expand All @@ -67,19 +73,21 @@ rustc-hash = "2"
rustls = { version = "0.23", default-features = false }
rustls-pki-types = "1"
rustls-platform-verifier = "0.5"
rustls-rustcrypto = "0.0.2-alpha"
serde = { version = "1", default-features = false, features = ["derive"] }
serde_json = { version = "1.0.142", default-features = false, features = ["alloc", "raw_value"] }
soketto = "0.8.1"
syn = { version = "2", default-features = false }
thiserror = "2"
tokio = "1.42"
tokio = { version = "1.51", default-features = false }
tokio-rustls = { version = "0.26", default-features = false }
tokio-stream = "0.1.7"
tokio-util = "0.7"
tower = "0.5"
tower-http = "0.6"
tracing = "0.1.34"
url = "2.4"
webpki-roots = "0.26"
wasm-bindgen-futures = "0.4.19"

# Dev dependencies
Expand All @@ -89,7 +97,7 @@ criterion = { version = "0.5", features = ["async_tokio", "html_reports"] }
fast-socks5 = "0.10"
futures = { version = "0.3.14", default-features = false, features = ["std"] }
pprof = { version = "0.15", features = ["flamegraph", "criterion"] }
socket2 = "0.6.0"
socket2 = "0.6.3"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
trybuild = "1.0.97"

Expand Down
23 changes: 13 additions & 10 deletions benches/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
[package]
name = "jsonrpsee-benchmarks"
description = "Benchmarks for jsonrpsee"
version.workspace = true
authors.workspace = true
edition.workspace = true
license.workspace = true
version = "0.26.0"
authors = ["Parity Technologies <admin@parity.io>", "Pierre Krieger <pierre.krieger1708@gmail.com>"]
edition = "2024"
license = "MIT"
publish = false

# benches/ is a standalone crate (excluded from the parent workspace) because the
# `jsonrpc-{http,ws}-server 18.0.0` deps drag in hyper 0.14, which pins socket2 to 0.5.x
# and breaks wasm32-wasip2 in the rest of the workspace.
[dependencies]
pprof = { workspace = true }
criterion = { workspace = true }
futures-util = { workspace = true }
pprof = { version = "0.15", features = ["flamegraph", "criterion"] }
criterion = { version = "0.5", features = ["async_tokio", "html_reports"] }
futures-util = { version = "0.3.14", default-features = false }
jsonrpsee = { path = "../jsonrpsee", features = ["server"] }
jsonrpsee_v0_20 = { package = "jsonrpsee", version = "=0.20.0", features = ["ws-client", "client-ws-transport-native-tls"] }
# Disable TLS for benches
jsonrpsee_v0_20_http_client = { package = "jsonrpsee-http-client", version = "=0.20.0", default-features = false }
jsonrpc-ws-server = { version = "18.0.0", optional = true }
jsonrpc-http-server = { version = "18.0.0", optional = true }
jsonrpc-pubsub = { version = "18.0.0", optional = true }
serde_json = { workspace = true }
tokio = { workspace = true, features = ["rt-multi-thread"] }
console-subscriber = { workspace = true }
serde_json = { version = "1.0.142", default-features = false, features = ["alloc", "raw_value"] }
tokio = { version = "1.51", default-features = false, features = ["rt-multi-thread"] }
console-subscriber = "0.4"

[[bench]]
name = "bench"
Expand Down
22 changes: 17 additions & 5 deletions client/http-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,22 @@ publish = true
[lints]
workspace = true

[build-dependencies]
cfg_aliases = { workspace = true }

[dependencies]
base64 = { workspace = true }
hyper = { workspace = true, features = ["client", "http1", "http2"] }
hyper-rustls = { workspace = true, features = ["http1", "http2", "tls12", "logging", "ring"], optional = true }
hyper-rustls = { workspace = true, features = ["http1", "http2", "tls12", "logging"], optional = true }
hyper-util = { workspace = true, features = ["client", "client-legacy", "tokio", "http1", "http2"] }
http-body = { workspace = true }
log = { workspace = true }
jsonrpsee-types = { workspace = true }
jsonrpsee-core = { workspace = true, features = ["client", "http-helpers"] }
rustls = { workspace = true, optional = true, features = ["logging", "std", "tls12", "ring"] }
rustls = { workspace = true, optional = true, features = ["logging", "std", "tls12"] }
rustls-platform-verifier = { workspace = true, optional = true }
rustls-rustcrypto = { workspace = true, optional = true }
webpki-roots = { workspace = true, optional = true }
serde = { workspace = true, features = ["alloc"] }
serde_json = { workspace = true }
thiserror = { workspace = true }
Expand All @@ -36,11 +42,17 @@ url = { workspace = true }
[dev-dependencies]
tracing-subscriber = { workspace = true }
jsonrpsee-test-utils = { path = "../../test-utils" }
tokio = { workspace = true, features = ["net", "rt-multi-thread", "macros"] }
tokio = { workspace = true, features = ["macros"] }

[target.'cfg(not(all(target_os = "wasi", target_env = "p2")))'.dev-dependencies]
tokio = { workspace = true, features = ["net", "rt-multi-thread"] }

[features]
default = ["tls"]
tls = ["hyper-rustls", "rustls", "rustls-platform-verifier"]
default = ["tls-rustcrypto"]
tls = ["hyper-rustls", "hyper-rustls/ring", "rustls", "rustls/ring", "rustls-platform-verifier"]
# Note: rustls-platform-verifier is used on native targets (ConfigVerifierExt) but compiled-unused
# on wasip2 where webpki_roots provides cert verification instead.
tls-rustcrypto = ["hyper-rustls", "rustls", "rustls-rustcrypto", "rustls-platform-verifier", "webpki-roots"]

[package.metadata.docs.rs]
all-features = true
Expand Down
7 changes: 7 additions & 0 deletions client/http-client/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//! Build script for jsonrpsee-http-client: sets up cfg aliases.

fn main() {
cfg_aliases::cfg_aliases! {
wasip2: { all(target_os = "wasi", target_env = "p2") },
}
}
16 changes: 8 additions & 8 deletions client/http-client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ use tokio::sync::Semaphore;
use tower::layer::util::Identity;
use tower::{Layer, Service};

#[cfg(feature = "tls")]
#[cfg(any(feature = "tls", feature = "tls-rustcrypto"))]
use crate::{CertificateStore, CustomCertStore};

type Logger = tower::layer::util::Stack<RpcLoggerLayer, tower::layer::util::Identity>;
Expand Down Expand Up @@ -82,7 +82,7 @@ pub struct HttpClientBuilder<HttpMiddleware = Identity, RpcMiddleware = Logger>
max_request_size: u32,
max_response_size: u32,
request_timeout: Duration,
#[cfg(feature = "tls")]
#[cfg(any(feature = "tls", feature = "tls-rustcrypto"))]
certificate_store: CertificateStore,
id_kind: IdKind,
headers: HeaderMap,
Expand Down Expand Up @@ -185,7 +185,7 @@ impl<HttpMiddleware, RpcMiddleware> HttpClientBuilder<HttpMiddleware, RpcMiddlew
/// // client builder with disabled certificate verification.
/// let client_builder = HttpClientBuilder::new().with_custom_cert_store(tls_cfg);
/// ```
#[cfg(feature = "tls")]
#[cfg(any(feature = "tls", feature = "tls-rustcrypto"))]
pub fn with_custom_cert_store(mut self, cfg: CustomCertStore) -> Self {
self.certificate_store = CertificateStore::Custom(cfg);
self
Expand Down Expand Up @@ -234,7 +234,7 @@ impl<HttpMiddleware, RpcMiddleware> HttpClientBuilder<HttpMiddleware, RpcMiddlew
/// Set the RPC middleware.
pub fn set_rpc_middleware<T>(self, rpc_builder: RpcServiceBuilder<T>) -> HttpClientBuilder<HttpMiddleware, T> {
HttpClientBuilder {
#[cfg(feature = "tls")]
#[cfg(any(feature = "tls", feature = "tls-rustcrypto"))]
certificate_store: self.certificate_store,
id_kind: self.id_kind,
headers: self.headers,
Expand All @@ -257,7 +257,7 @@ impl<HttpMiddleware, RpcMiddleware> HttpClientBuilder<HttpMiddleware, RpcMiddlew
service_builder: tower::ServiceBuilder<T>,
) -> HttpClientBuilder<T, RpcMiddleware> {
HttpClientBuilder {
#[cfg(feature = "tls")]
#[cfg(any(feature = "tls", feature = "tls-rustcrypto"))]
certificate_store: self.certificate_store,
id_kind: self.id_kind,
headers: self.headers,
Expand Down Expand Up @@ -291,7 +291,7 @@ where
max_request_size,
max_response_size,
request_timeout,
#[cfg(feature = "tls")]
#[cfg(any(feature = "tls", feature = "tls-rustcrypto"))]
certificate_store,
id_kind,
headers,
Expand All @@ -313,7 +313,7 @@ where
keep_alive_duration,
keep_alive_interval,
keep_alive_retries,
#[cfg(feature = "tls")]
#[cfg(any(feature = "tls", feature = "tls-rustcrypto"))]
certificate_store,
}
.build(target)
Expand All @@ -338,7 +338,7 @@ impl Default for HttpClientBuilder {
max_request_size: TEN_MB_SIZE_BYTES,
max_response_size: TEN_MB_SIZE_BYTES,
request_timeout: Duration::from_secs(60),
#[cfg(feature = "tls")]
#[cfg(any(feature = "tls", feature = "tls-rustcrypto"))]
certificate_store: CertificateStore::Native,
id_kind: IdKind::Number,
headers: HeaderMap::new(),
Expand Down
38 changes: 36 additions & 2 deletions client/http-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,44 @@
//! It is tightly-coupled to [`tokio`](https://docs.rs/tokio) because [`hyper`](https://docs.rs/hyper) is used as transport client,
//! which is not compatible with other async runtimes such as
//! [`async-std`](https://docs.rs/async-std/), [`smol`](https://docs.rs/smol) and similar.
//!
//! ## Building for `wasm32-wasip2`
//!
//! On `wasm32-wasip2` this crate uses `tokio::net::TcpStream`, which tokio gates behind the
//! unstable `--cfg tokio_unstable` rustc flag. Downstream consumers must set this flag themselves
//! when targeting `wasm32-wasip2`. The recommended way is a `.cargo/config.toml` in the consumer
//! crate:
//!
//! ```toml
//! [target.wasm32-wasip2]
//! rustflags = ["--cfg", "tokio_unstable"]
//! ```
//!
//! Without it, the build fails inside `tokio` with
//! `compile_error!("Only features sync,macros,io-util,rt,time are supported on wasm.")`.
//!
//! The default `tls` feature uses [`ring`](https://docs.rs/ring) for crypto, which has a C build
//! step that requires `clang` on the host. For wasip2 builds without a C toolchain, use the
//! pure-Rust `tls-rustcrypto` feature instead:
//!
//! ```bash
//! cargo build --target wasm32-wasip2 --no-default-features --features tls-rustcrypto
//! ```

#![cfg_attr(not(test), warn(unused_crate_dependencies))]
#![cfg_attr(docsrs, feature(doc_cfg))]

// These crates are only used behind wasip2 cfg gates, suppress unused warnings on other targets.
#[cfg(not(wasip2))]
use log as _;
#[cfg(all(feature = "tls-rustcrypto", not(wasip2)))]
use webpki_roots as _;

// rustls_platform_verifier is used on native targets (ConfigVerifierExt) but not on wasip2,
// where we use webpki_roots instead. Suppress the unused dependency warning for wasip2.
#[cfg(all(wasip2, any(feature = "tls", feature = "tls-rustcrypto")))]
use rustls_platform_verifier as _;

mod client;
mod rpc_service;

Expand Down Expand Up @@ -62,10 +96,10 @@ pub use jsonrpsee_core::middleware::{RpcServiceBuilder, RpcServiceT};
pub use transport::{HttpBackend, HttpTransportClient};

/// Custom TLS configuration.
#[cfg(feature = "tls")]
#[cfg(any(feature = "tls", feature = "tls-rustcrypto"))]
pub type CustomCertStore = rustls::ClientConfig;

#[cfg(feature = "tls")]
#[cfg(any(feature = "tls", feature = "tls-rustcrypto"))]
// rustls needs the concrete `ClientConfig` type so we can't Box it here.
#[allow(clippy::large_enum_variant)]
#[derive(Clone, Debug)]
Expand Down
6 changes: 3 additions & 3 deletions client/http-client/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,10 +251,10 @@ async fn batch_request_out_of_order_response() {
assert_eq!(response, vec!["hello".to_string(), "goodbye".to_string(), "here's your swag".to_string()]);
}

async fn run_batch_request_with_response<T: Send + DeserializeOwned + std::fmt::Debug + Clone + 'static>(
batch: BatchRequestBuilder<'_>,
async fn run_batch_request_with_response<'a, T: Send + DeserializeOwned + std::fmt::Debug + Clone + 'static>(
batch: BatchRequestBuilder<'a>,
response: String,
) -> Result<BatchResponse<T>, ClientError> {
) -> Result<BatchResponse<'a, T>, ClientError> {
let server_addr = http_server_with_hardcoded_response(response).with_default_timeout().await.unwrap();
let uri = format!("http://{server_addr}");
let client = HttpClientBuilder::default().build(&uri).unwrap();
Expand Down
Loading