Skip to content

Commit

Permalink
chore: re-use same instance of reqwest::blocking::Client & add brot…
Browse files Browse the repository at this point in the history
…li support (#650)

This change allows us to take advantage of reqwest's
ability to re-use connections. Their [docs](https://docs.rs/reqwest/0.11.4/reqwest/blocking/struct.Client.html)
explain that you should reuse a client by cloning it to take advantage of
its internal connection pool.
  • Loading branch information
EverlastingBugstopper committed Jul 2, 2021
1 parent b26f297 commit f57cdc4
Show file tree
Hide file tree
Showing 33 changed files with 182 additions and 135 deletions.
110 changes: 37 additions & 73 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 Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ humantime = "2.1.0"
opener = "0.5.0"
os_info = "3.0"
prettytable-rs = "0.8.0"
reqwest = {version = "0.11", default-features = false, features = ["blocking", "brotli", "gzip", "json", "rustls-tls-native-roots"]}
regex = "1"
semver = "1"
serde = "1.0"
Expand Down
3 changes: 2 additions & 1 deletion crates/rover-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ chrono = "0.4"
graphql_client = "0.9"
http = "0.2"
regex = "1.5.4"
reqwest = {version = "0.11", default-features = false, features = ["blocking", "gzip", "json", "rustls-tls-native-roots"]}
reqwest = {version = "0.11", default-features = false, features = ["blocking", "json"]}
sdl-encoder = {path = "../sdl-encoder"}
serde = "1"
serde_json = "1"
Expand All @@ -30,5 +30,6 @@ reqwest = {version = "0.11", default-features = false, features = ["json", "bloc
uuid = {version = "0.8", features = ["v4"]}

[dev-dependencies]

indoc = "1.0.3"
pretty_assertions = "0.7.1"
7 changes: 6 additions & 1 deletion crates/rover-client/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,12 @@ fn main() -> std::io::Result<()> {
let schema_url = env::var("APOLLO_GPAPHQL_SCHEMA_URL")
.unwrap_or_else(|_| "https://graphql.api.apollographql.com/api/schema".to_owned());

let client = Client::new();
let client = Client::builder()
.use_rustls_tls()
.tls_built_in_root_certs(true)
.build()
.expect("Could not create reqwest Client");

let etag_path = PathBuf::from(".schema/etag.id");

let should_update_schema = !(etag_path.exists()) || online::sync::check(None).is_ok();
Expand Down
17 changes: 6 additions & 11 deletions crates/rover-client/src/blocking/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,22 @@ use reqwest::{

use std::collections::HashMap;

pub(crate) fn get_client() -> Result<ReqwestClient, ReqwestError> {
ReqwestClient::builder()
.use_rustls_tls()
.tls_built_in_root_certs(true)
.gzip(true)
.build()
}

/// Represents a generic GraphQL client for making http requests.
pub struct GraphQLClient {
client: ReqwestClient,
graphql_endpoint: String,
client: ReqwestClient,
}

impl GraphQLClient {
/// Construct a new [Client] from a `graphql_endpoint`.
/// This client is used for generic GraphQL requests, such as introspection.
pub fn new(graphql_endpoint: &str) -> Result<GraphQLClient, ReqwestError> {
pub fn new(
graphql_endpoint: &str,
client: ReqwestClient,
) -> Result<GraphQLClient, ReqwestError> {
Ok(GraphQLClient {
client: get_client()?,
graphql_endpoint: graphql_endpoint.to_string(),
client,
})
}

Expand Down
1 change: 0 additions & 1 deletion crates/rover-client/src/blocking/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
mod client;
mod studio_client;

pub(crate) use client::get_client;
pub use client::GraphQLClient;
pub use studio_client::StudioClient;
5 changes: 3 additions & 2 deletions crates/rover-client/src/blocking/studio_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{blocking::GraphQLClient, headers, RoverClientError};
use houston::Credential;

use graphql_client::GraphQLQuery;
use reqwest::Error as ReqwestError;
use reqwest::{blocking::Client as ReqwestClient, Error as ReqwestError};

/// Represents a client for making GraphQL requests to Apollo Studio.
pub struct StudioClient {
Expand All @@ -18,10 +18,11 @@ impl StudioClient {
credential: Credential,
graphql_endpoint: &str,
version: &str,
client: ReqwestClient,
) -> Result<StudioClient, ReqwestError> {
Ok(StudioClient {
credential,
client: GraphQLClient::new(graphql_endpoint)?,
client: GraphQLClient::new(graphql_endpoint, client)?,
version: version.to_string(),
})
}
Expand Down
7 changes: 4 additions & 3 deletions crates/rover-client/src/releases.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use crate::{blocking::get_client, RoverClientError};
use crate::RoverClientError;
use regex::Regex;
use reqwest::blocking::Client;

const LATEST_RELEASE_URL: &str = "https://github.com/apollographql/rover/releases/latest";

/// Looks up the latest release version, and returns it as a string
pub fn get_latest_release() -> Result<String, RoverClientError> {
let res = get_client()?.head(LATEST_RELEASE_URL).send()?;
pub fn get_latest_release(client: Client) -> Result<String, RoverClientError> {
let res = client.head(LATEST_RELEASE_URL).send()?;

let release_url = res.url().to_string();
let release_url_parts: Vec<&str> = release_url.split('/').collect();
Expand Down
17 changes: 15 additions & 2 deletions crates/rover-client/tests/client.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
use reqwest::blocking::Client;
const STUDIO_PROD_API_ENDPOINT: &str = "https://graphql.api.apollographql.com/api/graphql";

pub(crate) fn get_client() -> Client {
Client::builder()
.use_rustls_tls()
.tls_built_in_root_certs(true)
.gzip(true)
.brotli(true)
.build()
.expect("Could not create reqwest Client")
}

#[cfg(test)]
mod tests {
use super::*;
use houston::{Credential, CredentialOrigin};
use rover_client::blocking::{GraphQLClient, StudioClient};

use crate::STUDIO_PROD_API_ENDPOINT;

#[test]
fn it_can_build_client() {
assert!(GraphQLClient::new(STUDIO_PROD_API_ENDPOINT).is_ok());
assert!(GraphQLClient::new(STUDIO_PROD_API_ENDPOINT, get_client()).is_ok(),);
}

#[test]
Expand All @@ -20,7 +32,8 @@ mod tests {
origin: CredentialOrigin::EnvVar,
},
"0.1.0",
STUDIO_PROD_API_ENDPOINT
STUDIO_PROD_API_ENDPOINT,
get_client()
)
.is_ok());
}
Expand Down
2 changes: 1 addition & 1 deletion crates/sputnik/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ edition = "2018"
camino = "1.0"
ci_info = { version = "0.14", features = ["serde-1"] }
git2 = "0.13"
reqwest = { version = "0.11", features = ["blocking", "rustls-tls-native-roots"] }
reqwest = { version = "0.11", default-features = false, features = ["blocking"] }
semver = { version = "1", features = ["serde"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
Expand Down
6 changes: 5 additions & 1 deletion crates/sputnik/src/report.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use camino::{Utf8Path, Utf8PathBuf};
use reqwest::blocking::Client;
use url::Url;
use uuid::Uuid;

Expand Down Expand Up @@ -38,12 +39,15 @@ pub trait Report {

/// returns the globally persistent machine identifier
/// and writes it if it does not exist
/// the default implemenation uses self.machine_id_config()
/// the default implementation uses self.machine_id_config()
/// as the location the machine identifier is written to.
fn machine_id(&self) -> Result<Uuid, SputnikError> {
let config_path = self.machine_id_config()?;
get_or_write_machine_id(&config_path)
}

/// returns the Client to use when sending telemetry data
fn client(&self) -> Client;
}

fn get_or_write_machine_id(path: &Utf8PathBuf) -> Result<Uuid, SputnikError> {
Expand Down
Loading

0 comments on commit f57cdc4

Please sign in to comment.