Skip to content

[http client]: support HTTPS #207

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
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
1 change: 1 addition & 0 deletions http-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ edition = "2018"
license = "MIT"

[dependencies]
anyhow = "1.0"
futures = "0.3"
surf = { version = "2.1", default-features = false, optional = true }
jsonrpsee-types = { path = "../types", version = "0.1" }
Expand Down
38 changes: 20 additions & 18 deletions http-client/src/transport.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 anyhow::anyhow;
use futures::prelude::*;
use jsonrpsee_types::{error::GenericTransportError, http::HttpConfig, jsonrpc};
use jsonrpsee_types::{http::HttpConfig, jsonrpc};
use surf::http::{mime::JSON, Url};
use thiserror::Error;

Expand All @@ -28,7 +29,7 @@ impl HttpTransportClient {
/// Initializes a new HTTP client.
pub fn new(target: impl AsRef<str>, config: HttpConfig) -> Result<Self, Error> {
let target = Url::parse(target.as_ref()).map_err(|e| Error::Url(format!("Invalid URL: {}", e)))?;
if target.scheme() == "http" {
if target.scheme() == "http" || target.scheme() == "https" {
Ok(HttpTransportClient { client: surf::Client::new(), target, config })
} else {
Err(Error::Url("URL scheme not supported, expects 'http'".into()))
Expand All @@ -47,7 +48,7 @@ impl HttpTransportClient {
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();
let response = self.client.send(request).await.map_err(|e| Error::Http(e.into_inner()))?;
if response.status().is_success() {
Ok(response)
} else {
Expand All @@ -66,7 +67,7 @@ impl HttpTransportClient {
&self,
request: jsonrpc::Request,
) -> Result<jsonrpc::Response, Error> {
let mut response = self.send_request(request).await.map_err(|e| Error::Http(Box::new(e)))?;
let mut response = self.send_request(request).await.map_err(|e| Error::Http(anyhow!(e)))?;

let length = response.len().unwrap_or(0);

Expand All @@ -77,7 +78,7 @@ impl HttpTransportClient {
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)))?;
take.read_to_end(&mut buffer).await.map_err(|e| Error::Http(anyhow!(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
Expand Down Expand Up @@ -105,7 +106,7 @@ pub enum Error {

/// 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>),
Http(#[source] anyhow::Error),

/// Server returned a non-success status code.
#[error("Server returned an error status code: {:?}", status_code)]
Expand All @@ -123,18 +124,6 @@ pub enum Error {
RequestTooLarge,
}

impl<T> From<GenericTransportError<T>> for Error
where
T: std::error::Error + Send + Sync + 'static,
{
fn from(err: GenericTransportError<T>) -> Self {
match err {
GenericTransportError::<T>::TooLarge => Self::RequestTooLarge,
GenericTransportError::<T>::Inner(e) => Self::Http(Box::new(e)),
}
}
}

#[cfg(test)]
mod tests {
use super::{Error, HttpTransportClient};
Expand Down Expand Up @@ -167,4 +156,17 @@ mod tests {
let response = client.send_request(request).await.unwrap_err();
assert!(matches!(response, Error::RequestTooLarge));
}

#[tokio::test]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe a little bit heavy for a test

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can remove it but just to demonstrate that it works :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd move it to the separate tests, it's more of integration test than unit test.

async fn https_works() {
let client = HttpTransportClient::new("https://kusama-rpc.polkadot.io/", HttpConfig::default()).unwrap();
let request = Request::Single(Call::MethodCall(MethodCall {
jsonrpc: Version::V2,
method: "system_chain".to_string(),
params: Params::None,
id: Id::Num(1),
}));
let response: String = client.send_request(request).await.unwrap().body_string().await.unwrap();
assert!(response.contains("Kusama"));
}
}