Skip to content
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

Infer 80/443 ports for http/https rpc-url #576

Merged
merged 3 commits into from
Apr 11, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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 Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions cmd/soroban-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ csv = "1.1.6"
ed25519-dalek = "1.0.1"
jsonrpsee-http-client = "0.15.1"
jsonrpsee-core = "0.15.1"
http = "0.2.9"
paulbellamy marked this conversation as resolved.
Show resolved Hide resolved
regex = "1.6.0"
wasm-opt = "0.112.0"
chrono = "0.4.23"
Expand Down
2 changes: 1 addition & 1 deletion cmd/soroban-cli/src/commands/contract/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ impl Cmd {
None => rand::thread_rng().gen::<[u8; 32]>(),
};

let client = Client::new(&network.rpc_url);
let client = Client::new(&network.rpc_url)?;
let key = self.config.key_pair()?;

// Get the account sequence number
Expand Down
2 changes: 1 addition & 1 deletion cmd/soroban-cli/src/commands/contract/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ impl Cmd {

async fn run_against_rpc_server(&self, contract: Vec<u8>) -> Result<Hash, Error> {
let network = self.config.get_network()?;
let client = Client::new(&network.rpc_url);
let client = Client::new(&network.rpc_url)?;
let key = self.config.key_pair()?;

// Get the account sequence number
Expand Down
2 changes: 1 addition & 1 deletion cmd/soroban-cli/src/commands/contract/invoke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ impl Cmd {
pub async fn run_against_rpc_server(&self) -> Result<String, Error> {
let contract_id = self.contract_id()?;
let network = &self.config.get_network()?;
let client = Client::new(&network.rpc_url);
let client = Client::new(&network.rpc_url)?;
let key = self.config.key_pair()?;

// Get the account sequence number
Expand Down
2 changes: 1 addition & 1 deletion cmd/soroban-cli/src/commands/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ impl Cmd {
})?;
}

let client = rpc::Client::new(&rpc_url);
let client = rpc::Client::new(&rpc_url)?;
client
.get_events(
start,
Expand Down
2 changes: 1 addition & 1 deletion cmd/soroban-cli/src/commands/lab/token/wrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ impl Cmd {

async fn run_against_rpc_server(&self, asset: Asset) -> Result<String, Error> {
let network = self.config.get_network()?;
let client = Client::new(&network.rpc_url);
let client = Client::new(&network.rpc_url)?;
let key = self.config.key_pair()?;

// Get the account sequence number
Expand Down
64 changes: 61 additions & 3 deletions cmd/soroban-cli/src/rpc/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use http::{uri::Authority, Uri};
use itertools::Itertools;
use jsonrpsee_core::{self, client::ClientT, rpc_params};
use jsonrpsee_http_client::{types, HeaderMap, HttpClient, HttpClientBuilder};
Expand All @@ -10,6 +11,7 @@ use soroban_env_host::xdr::{
use std::{
collections,
fmt::Display,
str::FromStr,
time::{Duration, Instant},
};
use termcolor::{Color, ColorChoice, StandardStream, WriteColor};
Expand All @@ -26,6 +28,10 @@ pub enum Error {
InvalidResponse,
#[error("xdr processing error: {0}")]
Xdr(#[from] XdrError),
#[error("invalid rpc url: {0}")]
InvalidRpcUrl(http::uri::InvalidUri),
#[error("invalid rpc url: {0}")]
InvalidRpcUrlFromUriParts(http::uri::InvalidUriParts),
#[error("jsonrpc error: {0}")]
JsonRpc(#[from] jsonrpsee_core::Error),
#[error("json decoding error: {0}")]
Expand Down Expand Up @@ -300,10 +306,33 @@ pub struct Client {
}

impl Client {
pub fn new(base_url: &str) -> Self {
Self {
base_url: base_url.to_string(),
pub fn new(base_url: &str) -> Result<Self, Error> {
// Add the port to the base URL if there is no port explicitly included
// in the URL and the scheme allows us to infer a default port.
// Jsonrpsee requires a port to always be present even if one can be
// inferred. This may change: https://github.com/paritytech/jsonrpsee/issues/1048.
let uri = base_url.parse::<Uri>().map_err(Error::InvalidRpcUrl)?;
let mut parts = uri.into_parts();
if let (Some(scheme), Some(authority)) = (&parts.scheme, &parts.authority) {
if authority.port().is_none() {
let port = match scheme.as_str() {
"http" => Some(80),
"https" => Some(443),
_ => None,
};
if let Some(port) = port {
let host = authority.host();
parts.authority = Some(
Authority::from_str(&format!("{host}:{port}"))
.map_err(Error::InvalidRpcUrl)?,
);
}
}
}
let uri = Uri::from_parts(parts).map_err(Error::InvalidRpcUrlFromUriParts)?;
Ok(Self {
base_url: uri.to_string(),
})
}

fn client(&self) -> Result<HttpClient, Error> {
Expand Down Expand Up @@ -493,6 +522,35 @@ pub fn parse_cursor(c: &str) -> Result<(u64, i32), Error> {
mod tests {
use super::*;

#[test]
fn test_rpc_url_default_ports() {
// Default ports are added.
let client = Client::new("http://example.com").unwrap();
assert_eq!(client.base_url, "http://example.com:80/");
let client = Client::new("https://example.com").unwrap();
assert_eq!(client.base_url, "https://example.com:443/");

// Ports are not added when already present.
let client = Client::new("http://example.com:8080").unwrap();
assert_eq!(client.base_url, "http://example.com:8080/");
let client = Client::new("https://example.com:8080").unwrap();
assert_eq!(client.base_url, "https://example.com:8080/");

// Paths are not modified.
let client = Client::new("http://example.com/a/b/c").unwrap();
assert_eq!(client.base_url, "http://example.com:80/a/b/c");
let client = Client::new("https://example.com/a/b/c").unwrap();
assert_eq!(client.base_url, "https://example.com:443/a/b/c");
let client = Client::new("http://example.com/a/b/c/").unwrap();
assert_eq!(client.base_url, "http://example.com:80/a/b/c/");
let client = Client::new("https://example.com/a/b/c/").unwrap();
assert_eq!(client.base_url, "https://example.com:443/a/b/c/");
let client = Client::new("http://example.com/a/b:80/c/").unwrap();
assert_eq!(client.base_url, "http://example.com:80/a/b:80/c/");
let client = Client::new("https://example.com/a/b:80/c/").unwrap();
assert_eq!(client.base_url, "https://example.com:443/a/b:80/c/");
}

#[test]
// Taken from [RPC server
// tests](https://github.com/stellar/soroban-tools/blob/main/cmd/soroban-rpc/internal/methods/get_events_test.go#L21).
Expand Down