#![allow(clippy::too_long_first_doc_paragraph)]
use url::Url;
mod clients;
mod errors;
pub mod types;
pub use clients::*;
pub use errors::*;
pub struct ClientBuilder {
api_key: String,
api_url: Option<Url>,
reqwest_client: Option<reqwest::Client>,
}
impl ClientBuilder {
pub fn new(api_key: String) -> ClientBuilder {
ClientBuilder {
api_key,
api_url: None,
reqwest_client: None,
}
}
pub fn api_url(&mut self, api_url: Url) -> &mut Self {
self.api_url = Some(api_url);
self
}
pub fn reqwest_client(&mut self, client: reqwest::Client) -> &mut Self {
self.reqwest_client = Some(client);
self
}
pub fn build(self) -> Client {
Client {
api_key: self.api_key,
api_url: self
.api_url
.unwrap_or_else(|| Url::parse("https://api.ngrok.com").unwrap()),
c: self.reqwest_client.unwrap_or_default(),
}
}
}
#[derive(Clone, Debug)]
pub struct Client {
api_key: String,
api_url: Url,
c: reqwest::Client,
}
impl Client {
pub fn new(api_key: String) -> Self {
ClientBuilder::new(api_key).build()
}
pub(crate) async fn make_request<T, R>(
&self,
path: &str,
method: reqwest::Method,
req: Option<T>,
) -> Result<R, Error>
where
T: serde::Serialize,
R: serde::de::DeserializeOwned + Default,
{
let api_url = &self.api_url;
let mut builder = self
.c
.request(method.clone(), api_url.join(path).unwrap())
.bearer_auth(&self.api_key)
.header("Ngrok-Version", "2");
if let Some(r) = req {
builder = match method {
reqwest::Method::GET => builder.query(&r),
_ => builder.json(&r),
};
}
let resp = builder.send().await?;
match resp.status() {
reqwest::StatusCode::NO_CONTENT => return Ok(Default::default()),
s if s.is_success() => {
return resp.json().await.map_err(|e| e.into());
}
_ => {}
}
let resp_bytes = resp.bytes().await?;
if let Ok(e) = serde_json::from_slice(&resp_bytes) {
return Err(Error::Ngrok(e));
}
Err(Error::UnknownError(
String::from_utf8_lossy(&resp_bytes).into(),
))
}
pub(crate) async fn get_by_uri<R>(&self, uri: &str) -> Result<R, Error>
where
R: serde::de::DeserializeOwned,
{
let builder = self
.c
.request(reqwest::Method::GET, uri)
.bearer_auth(&self.api_key)
.header("Ngrok-Version", "2");
let resp = builder.send().await?;
if resp.status().is_success() {
return resp.json().await.map_err(|e| e.into());
}
let resp_bytes = resp.bytes().await?;
if let Ok(e) = serde_json::from_slice(&resp_bytes) {
return Err(Error::Ngrok(e));
}
Err(Error::UnknownError(
String::from_utf8_lossy(&resp_bytes).into(),
))
}
}