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

[http client]: switch to surf instead of hyper (#204)



* [http client] use surf instead of hyper

* user exposed features

* feature for surf middleware logging

* feature flag WASM support

* update ci

* fix ci nit; install wasm32

* Update http-client/src/transport.rs

Co-authored-by: default avatarMaciej Hirsz <1096222+maciejhirsz@users.noreply.github.com>

Co-authored-by: default avatarMaciej Hirsz <1096222+maciejhirsz@users.noreply.github.com>
parent 29036c83
......@@ -54,6 +54,7 @@ jobs:
profile: minimal
toolchain: stable
override: true
target: wasm32-unknown-unknown
- name: Cache Dependencies & Build Outputs
uses: actions/cache@v2.1.4
......@@ -70,11 +71,17 @@ jobs:
command: check
args: --benches --tests
- name: Cargo check all-features
- name: Cargo check HTTP client with hyper
uses: actions-rs/cargo@v1
with:
command: check
args: --benches --tests --all-features
args: --manifest-path http-client/Cargo.toml --no-default-features --features hyper-client
- name: Cargo check HTTP client for WASM.
uses: actions-rs/cargo@v1
with:
command: check
args: --manifest-path http-client/Cargo.toml --no-default-features --features wasm-client --target wasm32-unknown-unknown
tests:
name: Run tests
......
......@@ -8,16 +8,21 @@ license = "MIT"
[dependencies]
futures = "0.3"
hyper = { version = "0.14", features = ["stream", "client", "server", "http1", "http2", "tcp"] }
surf = { version = "2.1", default-features = false, optional = true }
jsonrpsee-types = { path = "../types", version = "0.1" }
jsonrpsee-utils = { path = "../utils", version = "0.1" }
log = "0.4"
serde = { version = "1.0", default-features = false, features = ["derive"] }
serde_json = "1.0"
thiserror = "1.0"
unicase = "2.6"
url = "2.2"
[dev-dependencies]
jsonrpsee-test-utils = { path = "../test-utils" }
tokio = { version = "1.0", features = ["net", "rt-multi-thread", "macros"] }
[features]
default = ["surf/curl-client"]
curl-client = ["surf/curl-client"]
hyper-client = ["surf/hyper-client"]
wasm-client = ["surf/wasm-client"]
middleware-logger = ["surf/middleware-logger"]
......@@ -6,8 +6,9 @@
// that we need to be guaranteed that hyper doesn't re-use an existing connection if we ever reset
// the JSON-RPC request id to a value that might have already been used.
use futures::prelude::*;
use jsonrpsee_types::{error::GenericTransportError, http::HttpConfig, jsonrpc};
use jsonrpsee_utils::http::hyper_helpers;
use surf::http::{mime::JSON, Url};
use thiserror::Error;
const CONTENT_TYPE_JSON: &str = "application/json";
......@@ -16,9 +17,9 @@ const CONTENT_TYPE_JSON: &str = "application/json";
#[derive(Debug, Clone)]
pub struct HttpTransportClient {
/// Target to connect to.
target: url::Url,
target: Url,
/// HTTP client,
client: hyper::Client<hyper::client::HttpConnector>,
client: surf::Client,
/// Configurable max request body size
config: HttpConfig,
}
......@@ -26,16 +27,16 @@ pub struct HttpTransportClient {
impl HttpTransportClient {
/// Initializes a new HTTP client.
pub fn new(target: impl AsRef<str>, config: HttpConfig) -> Result<Self, Error> {
let target = url::Url::parse(target.as_ref()).map_err(|e| Error::Url(format!("Invalid URL: {}", e)))?;
let target = Url::parse(target.as_ref()).map_err(|e| Error::Url(format!("Invalid URL: {}", e)))?;
if target.scheme() == "http" {
Ok(HttpTransportClient { client: hyper::Client::new(), target, config })
Ok(HttpTransportClient { client: surf::Client::new(), target, config })
} else {
Err(Error::Url("URL scheme not supported, expects 'http'".into()))
}
}
/// Send request.
async fn send_request(&self, request: jsonrpc::Request) -> Result<hyper::Response<hyper::Body>, Error> {
async fn send_request(&self, request: jsonrpc::Request) -> Result<surf::Response, Error> {
let body = jsonrpc::to_vec(&request).map_err(Error::Serialization)?;
log::debug!("send: {}", request);
......@@ -43,14 +44,10 @@ impl HttpTransportClient {
return Err(Error::RequestTooLarge);
}
let req = hyper::Request::post(self.target.as_str())
.header(hyper::header::CONTENT_TYPE, hyper::header::HeaderValue::from_static(CONTENT_TYPE_JSON))
.header(hyper::header::ACCEPT, hyper::header::HeaderValue::from_static(CONTENT_TYPE_JSON))
.body(From::from(body))
.expect("URI and request headers are valid; qed");
let response = self.client.request(req).await.map_err(|e| Error::Http(Box::new(e)))?;
let request =
surf::post(&self.target).body(body).header("accept", CONTENT_TYPE_JSON).content_type(JSON).build();
let response = self.client.send(request).await.unwrap();
if response.status().is_success() {
Ok(response)
} else {
......@@ -69,13 +66,22 @@ impl HttpTransportClient {
&self,
request: jsonrpc::Request,
) -> Result<jsonrpc::Response, Error> {
let response = self.send_request(request).await?;
let (parts, body) = response.into_parts();
let body = hyper_helpers::read_response_to_body(&parts.headers, body, self.config).await?;
let mut response = self.send_request(request).await.map_err(|e| Error::Http(Box::new(e)))?;
let length = response.len().unwrap_or(0);
if length > self.config.max_request_body_size as usize {
return Err(Error::RequestTooLarge.into());
}
let mut buffer = Vec::with_capacity(length);
let reader = response.take_body().into_reader();
let mut take = reader.take(self.config.max_request_body_size as u64);
take.read_to_end(&mut buffer).await.map_err(|e| Error::Http(Box::new(e)))?;
let response: jsonrpc::Response = jsonrpc::from_slice(&buffer).map_err(Error::ParseError)?;
// Note that we don't check the Content-Type of the request. This is deemed
// unnecessary, as a parsing error while happen anyway.
let response: jsonrpc::Response = jsonrpc::from_slice(&body).map_err(Error::ParseError)?;
log::debug!("recv: {}", jsonrpc::to_string(&response).expect("request valid JSON; qed"));
Ok(response)
}
......
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