Remove error generics, address PR comments
This commit is contained in:
Generated
+11
@@ -5895,6 +5895,8 @@ dependencies = [
|
||||
"reqwest 0.12.22",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_plain",
|
||||
"serde_yaml",
|
||||
"thiserror 2.0.12",
|
||||
"tokio",
|
||||
"tracing",
|
||||
@@ -9295,6 +9297,15 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_plain"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ce1fc6db65a611022b23a0dec6975d63fb80a302cb3388835ff02c097258d50"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_repr"
|
||||
version = "0.1.20"
|
||||
|
||||
@@ -756,23 +756,24 @@ where
|
||||
let mut nym_api_urls = config.get_nym_api_endpoints();
|
||||
nym_api_urls.shuffle(&mut thread_rng());
|
||||
|
||||
let mut builder = nym_http_api_client::Client::builder::<
|
||||
_,
|
||||
nym_validator_client::models::RequestError,
|
||||
>(nym_api_urls[0].clone())
|
||||
.map_err(|e| ClientCoreError::NymApiQueryFailure {
|
||||
source: nym_validator_client::nym_api::error::NymAPIError::GenericRequestFailure(
|
||||
e.to_string(),
|
||||
),
|
||||
})?;
|
||||
let mut builder =
|
||||
nym_http_api_client::Client::builder(nym_api_urls[0].clone()).map_err(|e| {
|
||||
ClientCoreError::NymApiQueryFailure {
|
||||
source:
|
||||
nym_validator_client::nym_api::error::NymAPIError::GenericRequestFailure(
|
||||
e.to_string(),
|
||||
),
|
||||
}
|
||||
})?;
|
||||
|
||||
if let Some(user_agent) = user_agent {
|
||||
builder = builder.with_user_agent(user_agent);
|
||||
}
|
||||
|
||||
builder = builder.with_bincode();
|
||||
|
||||
builder
|
||||
.with_bincode()
|
||||
.build::<nym_validator_client::models::RequestError>()
|
||||
.build()
|
||||
.map_err(|e| ClientCoreError::NymApiQueryFailure {
|
||||
source: nym_validator_client::nym_api::error::NymAPIError::GenericRequestFailure(
|
||||
e.to_string(),
|
||||
|
||||
@@ -156,13 +156,11 @@ pub async fn gateways_for_init<R: Rng>(
|
||||
builder = builder.with_user_agent(user_agent);
|
||||
}
|
||||
|
||||
let client = builder
|
||||
.build::<nym_validator_client::models::RequestError>()
|
||||
.map_err(|e| {
|
||||
ClientCoreError::ValidatorClientError(
|
||||
nym_validator_client::ValidatorClientError::NymAPIError { source: e },
|
||||
)
|
||||
})?;
|
||||
let client = builder.build().map_err(|e| {
|
||||
ClientCoreError::ValidatorClientError(
|
||||
nym_validator_client::ValidatorClientError::NymAPIError { source: e },
|
||||
)
|
||||
})?;
|
||||
|
||||
tracing::debug!("Fetching list of gateways from: {nym_api}");
|
||||
|
||||
|
||||
@@ -418,10 +418,10 @@ impl NymApiClient {
|
||||
}
|
||||
|
||||
pub fn new_with_user_agent(api_url: Url, user_agent: impl Into<UserAgent>) -> Self {
|
||||
let nym_api = nym_http_api_client::Client::builder::<_, ValidatorClientError>(api_url)
|
||||
let nym_api = nym_http_api_client::Client::builder(api_url)
|
||||
.expect("invalid api url")
|
||||
.with_user_agent(user_agent.into())
|
||||
.build::<ValidatorClientError>()
|
||||
.build()
|
||||
.expect("failed to build nym api client");
|
||||
|
||||
NymApiClient {
|
||||
|
||||
@@ -91,13 +91,10 @@ impl TryFrom<ContractVKShare> for EcashApiClient {
|
||||
// In non-client applications this resolver can cause warning logs about H2 connection
|
||||
// failure. This indicates that the long lived https connection was closed by the remote
|
||||
// peer and the resolver will have to reconnect. It should not impact actual functionality
|
||||
let api_client = nym_http_api_client::Client::builder::<
|
||||
_,
|
||||
nym_api_requests::models::RequestError,
|
||||
>(url_address)
|
||||
.map_err(|e| EcashApiError::ClientError(e.to_string()))?
|
||||
.build::<nym_api_requests::models::RequestError>()
|
||||
.map_err(|e| EcashApiError::ClientError(e.to_string()))?;
|
||||
let api_client = nym_http_api_client::Client::builder(url_address)
|
||||
.map_err(|e| EcashApiError::ClientError(e.to_string()))?
|
||||
.build()
|
||||
.map_err(|e| EcashApiError::ClientError(e.to_string()))?;
|
||||
|
||||
Ok(EcashApiClient {
|
||||
api_client,
|
||||
|
||||
@@ -89,9 +89,7 @@ fn setup_connection_tests<H: BuildHasher + 'static>(
|
||||
});
|
||||
|
||||
let api_connection_test_clients = api_urls.filter_map(|(network, url)| {
|
||||
match nym_http_api_client::Client::builder(url.clone())
|
||||
.and_then(|b| b.build::<nym_api_requests::models::RequestError>())
|
||||
{
|
||||
match nym_http_api_client::Client::builder(url.clone()).and_then(|b| b.build()) {
|
||||
Ok(client) => Some(ClientForConnectionTest::Api(network, url, client)),
|
||||
Err(err) => {
|
||||
eprintln!(
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_api_requests::models::RequestError;
|
||||
use nym_http_api_client::HttpClientError;
|
||||
|
||||
pub type NymAPIError = HttpClientError<RequestError>;
|
||||
pub type NymAPIError = HttpClientError;
|
||||
|
||||
@@ -275,9 +275,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
// Create a custom error for inconsistent metadata
|
||||
return Err(NymAPIError::EndpointFailure {
|
||||
status: reqwest::StatusCode::INTERNAL_SERVER_ERROR,
|
||||
error: nym_api_requests::models::RequestError::new(
|
||||
"Inconsistent paged metadata",
|
||||
),
|
||||
error: "Inconsistent paged metadata".to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -318,9 +316,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
if !metadata.consistency_check(&res.metadata) {
|
||||
return Err(NymAPIError::EndpointFailure {
|
||||
status: reqwest::StatusCode::INTERNAL_SERVER_ERROR,
|
||||
error: nym_api_requests::models::RequestError::new(
|
||||
"Inconsistent paged metadata",
|
||||
),
|
||||
error: "Inconsistent paged metadata".to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -363,9 +359,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
if !metadata.consistency_check(&res.metadata) {
|
||||
return Err(NymAPIError::EndpointFailure {
|
||||
status: reqwest::StatusCode::INTERNAL_SERVER_ERROR,
|
||||
error: nym_api_requests::models::RequestError::new(
|
||||
"Inconsistent paged metadata",
|
||||
),
|
||||
error: "Inconsistent paged metadata".to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@ url = { workspace = true }
|
||||
once_cell = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
serde_yaml = "0.9.34-deprecated"
|
||||
serde_plain = "1.0.2"
|
||||
thiserror = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
itertools = { workspace = true }
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
//! # use url::Url;
|
||||
//! # use nym_http_api_client::{ApiClient, NO_PARAMS, HttpClientError};
|
||||
//!
|
||||
//! # type Err = HttpClientError<String>;
|
||||
//! # type Err = HttpClientError;
|
||||
//! # async fn run() -> Result<(), Err> {
|
||||
//! let url: Url = "https://nymvpn.com".parse()?;
|
||||
//! let client = nym_http_api_client::Client::new(url, None);
|
||||
@@ -114,7 +114,7 @@
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! pub type SpecificAPIError = HttpClientError<error::RequestError>;
|
||||
//! pub type SpecificAPIError = HttpClientError;
|
||||
//!
|
||||
//! #[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
//! #[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
@@ -142,7 +142,7 @@ pub use reqwest::StatusCode;
|
||||
use crate::path::RequestPath;
|
||||
use async_trait::async_trait;
|
||||
use bytes::Bytes;
|
||||
use http::header::CONTENT_TYPE;
|
||||
use http::header::{ACCEPT, CONTENT_TYPE};
|
||||
use http::HeaderMap;
|
||||
use itertools::Itertools;
|
||||
use mime::Mime;
|
||||
@@ -201,12 +201,39 @@ pub enum SerializationFormat {
|
||||
Json,
|
||||
/// Use bincode serialization (must be explicitly opted into)
|
||||
Bincode,
|
||||
/// Use YAML serialization
|
||||
Yaml,
|
||||
/// Use Text serialization
|
||||
Text,
|
||||
}
|
||||
|
||||
impl Display for SerializationFormat {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
SerializationFormat::Json => write!(f, "json"),
|
||||
SerializationFormat::Bincode => write!(f, "bincode"),
|
||||
SerializationFormat::Yaml => write!(f, "yaml"),
|
||||
SerializationFormat::Text => write!(f, "text"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SerializationFormat {
|
||||
#[allow(missing_docs)]
|
||||
pub fn content_type(&self) -> String {
|
||||
match self {
|
||||
SerializationFormat::Json => "application/json".to_string(),
|
||||
SerializationFormat::Bincode => "application/bincode".to_string(),
|
||||
SerializationFormat::Yaml => "application/yaml".to_string(),
|
||||
SerializationFormat::Text => "text/plain".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The Errors that may occur when creating or using an HTTP client.
|
||||
#[derive(Debug, Error)]
|
||||
#[allow(missing_docs)]
|
||||
pub enum HttpClientError<E: Display = String> {
|
||||
pub enum HttpClientError {
|
||||
#[error("there was an issue with the REST request: {source}")]
|
||||
ReqwestClientError {
|
||||
#[from]
|
||||
@@ -235,11 +262,23 @@ pub enum HttpClientError<E: Display = String> {
|
||||
EmptyResponse { status: StatusCode },
|
||||
|
||||
#[error("failed to resolve request. status: '{status}', additional error message: {error}")]
|
||||
EndpointFailure { status: StatusCode, error: E },
|
||||
EndpointFailure { status: StatusCode, error: String },
|
||||
|
||||
#[error("failed to decode response body: {message} from {content}")]
|
||||
ResponseDecodeFailure { message: String, content: String },
|
||||
|
||||
#[error("Failed to encode bincode: {0}")]
|
||||
Bincode(#[from] bincode::Error),
|
||||
|
||||
#[error("Failed to json: {0}")]
|
||||
Json(#[from] serde_json::Error),
|
||||
|
||||
#[error("Failed to yaml: {0}")]
|
||||
Yaml(#[from] serde_yaml::Error),
|
||||
|
||||
#[error("Failed to plain: {0}")]
|
||||
Plain(#[from] serde_plain::Error),
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[error("the request has timed out")]
|
||||
RequestTimeout,
|
||||
@@ -281,8 +320,8 @@ pub trait ApiClientCore {
|
||||
method: reqwest::Method,
|
||||
path: P,
|
||||
params: Params<'_, K, V>,
|
||||
json_body: Option<&B>,
|
||||
) -> RequestBuilder
|
||||
body: Option<&B>,
|
||||
) -> Result<RequestBuilder, HttpClientError>
|
||||
where
|
||||
P: RequestPath,
|
||||
B: Serialize + ?Sized,
|
||||
@@ -308,8 +347,8 @@ pub trait ApiClientCore {
|
||||
&self,
|
||||
method: reqwest::Method,
|
||||
endpoint: S,
|
||||
json_body: Option<&B>,
|
||||
) -> RequestBuilder
|
||||
body: Option<&B>,
|
||||
) -> Result<RequestBuilder, HttpClientError>
|
||||
where
|
||||
B: Serialize + ?Sized,
|
||||
S: AsRef<str>,
|
||||
@@ -335,7 +374,7 @@ pub trait ApiClientCore {
|
||||
};
|
||||
let params: Vec<(String, String)> = standin_url.query_pairs().into_owned().collect();
|
||||
|
||||
self.create_request(method, path.as_slice(), ¶ms, json_body)
|
||||
self.create_request(method, path.as_slice(), ¶ms, body)
|
||||
}
|
||||
|
||||
/// Send a created HTTP request.
|
||||
@@ -343,26 +382,23 @@ pub trait ApiClientCore {
|
||||
/// A [`RequestBuilder`] can be created with [`ApiClientCore::create_request`] or
|
||||
/// [`ApiClientCore::create_request_endpoint`] or if absolutely necessary, using reqwest
|
||||
/// tooling directly.
|
||||
async fn send<E>(&self, request: RequestBuilder) -> Result<Response, HttpClientError<E>>
|
||||
where
|
||||
E: Display;
|
||||
async fn send(&self, request: RequestBuilder) -> Result<Response, HttpClientError>;
|
||||
|
||||
/// Create and send a created HTTP request.
|
||||
async fn send_request<P, B, K, V, E>(
|
||||
async fn send_request<P, B, K, V>(
|
||||
&self,
|
||||
method: reqwest::Method,
|
||||
path: P,
|
||||
params: Params<'_, K, V>,
|
||||
json_body: Option<&B>,
|
||||
) -> Result<Response, HttpClientError<E>>
|
||||
) -> Result<Response, HttpClientError>
|
||||
where
|
||||
P: RequestPath + Send + Sync,
|
||||
B: Serialize + ?Sized + Sync,
|
||||
K: AsRef<str> + Sync,
|
||||
V: AsRef<str> + Sync,
|
||||
E: Display,
|
||||
{
|
||||
let req = self.create_request(method, path, params, json_body);
|
||||
let req = self.create_request(method, path, params, json_body)?;
|
||||
self.send(req).await
|
||||
}
|
||||
}
|
||||
@@ -389,10 +425,9 @@ impl ClientBuilder {
|
||||
/// Constructs a new `ClientBuilder`.
|
||||
///
|
||||
/// This is the same as `Client::builder()`.
|
||||
pub fn new<U, E>(url: U) -> Result<Self, HttpClientError<E>>
|
||||
pub fn new<U>(url: U) -> Result<Self, HttpClientError>
|
||||
where
|
||||
U: IntoUrl,
|
||||
E: Display,
|
||||
{
|
||||
let str_url = url.as_str();
|
||||
|
||||
@@ -570,10 +605,7 @@ impl ClientBuilder {
|
||||
}
|
||||
|
||||
/// Returns a Client that uses this ClientBuilder configuration.
|
||||
pub fn build<E>(self) -> Result<Client, HttpClientError<E>>
|
||||
where
|
||||
E: Display,
|
||||
{
|
||||
pub fn build(self) -> Result<Client, HttpClientError> {
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
let reqwest_client = self.reqwest_client_builder.build()?;
|
||||
|
||||
@@ -641,16 +673,15 @@ impl Client {
|
||||
// In order to prevent interference in API requests at the DNS phase we default to a resolver
|
||||
// that uses DoT and DoH.
|
||||
pub fn new(base_url: ::url::Url, timeout: Option<Duration>) -> Self {
|
||||
Self::new_url::<_, String>(base_url, timeout).expect(
|
||||
Self::new_url(base_url, timeout).expect(
|
||||
"we provided valid url and we were unwrapping previous construction errors anyway",
|
||||
)
|
||||
}
|
||||
|
||||
/// Attempt to create a new http client from a something that can be converted to a URL
|
||||
pub fn new_url<U, E>(url: U, timeout: Option<Duration>) -> Result<Self, HttpClientError<E>>
|
||||
pub fn new_url<U>(url: U, timeout: Option<Duration>) -> Result<Self, HttpClientError>
|
||||
where
|
||||
U: IntoUrl,
|
||||
E: Display,
|
||||
{
|
||||
let builder = Self::builder(url)?;
|
||||
match timeout {
|
||||
@@ -662,10 +693,9 @@ impl Client {
|
||||
/// Creates a [`ClientBuilder`] to configure a [`Client`].
|
||||
///
|
||||
/// This is the same as [`ClientBuilder::new()`].
|
||||
pub fn builder<U, E>(url: U) -> Result<ClientBuilder, HttpClientError<E>>
|
||||
pub fn builder<U>(url: U) -> Result<ClientBuilder, HttpClientError>
|
||||
where
|
||||
U: IntoUrl,
|
||||
E: Display,
|
||||
{
|
||||
ClientBuilder::new(url)
|
||||
}
|
||||
@@ -808,8 +838,8 @@ impl ApiClientCore for Client {
|
||||
method: reqwest::Method,
|
||||
path: P,
|
||||
params: Params<'_, K, V>,
|
||||
json_body: Option<&B>,
|
||||
) -> RequestBuilder
|
||||
body: Option<&B>,
|
||||
) -> Result<RequestBuilder, HttpClientError>
|
||||
where
|
||||
P: RequestPath,
|
||||
B: Serialize + ?Sized,
|
||||
@@ -825,24 +855,35 @@ impl ApiClientCore for Client {
|
||||
|
||||
let mut rb = RequestBuilder::from_parts(self.reqwest_client.clone(), req);
|
||||
|
||||
// Set Accept header based on serialization preference
|
||||
let accept_header = match self.serialization {
|
||||
SerializationFormat::Json => "application/json",
|
||||
SerializationFormat::Bincode => "application/bincode",
|
||||
};
|
||||
rb = rb.header(reqwest::header::ACCEPT, accept_header);
|
||||
rb = rb
|
||||
.header(ACCEPT, self.serialization.content_type())
|
||||
.header(CONTENT_TYPE, self.serialization.content_type());
|
||||
|
||||
if let Some(body) = json_body {
|
||||
rb = rb.json(body);
|
||||
if let Some(body) = body {
|
||||
match self.serialization {
|
||||
SerializationFormat::Json => {
|
||||
rb = rb.json(body);
|
||||
}
|
||||
SerializationFormat::Bincode => {
|
||||
let body = bincode::serialize(body)?;
|
||||
rb = rb.body(body);
|
||||
}
|
||||
SerializationFormat::Yaml => {
|
||||
let mut body_bytes = Vec::new();
|
||||
serde_yaml::to_writer(&mut body_bytes, &body)?;
|
||||
rb = rb.body(body_bytes);
|
||||
}
|
||||
SerializationFormat::Text => {
|
||||
let body = serde_plain::to_string(&body)?.as_bytes().to_vec();
|
||||
rb = rb.body(body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rb
|
||||
Ok(rb)
|
||||
}
|
||||
|
||||
async fn send<E>(&self, request: RequestBuilder) -> Result<Response, HttpClientError<E>>
|
||||
where
|
||||
E: Display,
|
||||
{
|
||||
async fn send(&self, request: RequestBuilder) -> Result<Response, HttpClientError> {
|
||||
let mut attempts = 0;
|
||||
loop {
|
||||
// try_clone may fail if the body is a stream in which case using retries is not advised.
|
||||
@@ -858,7 +899,7 @@ impl ApiClientCore for Client {
|
||||
self.apply_hosts_to_req(&mut req);
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
let response: Result<Response, HttpClientError<E>> = {
|
||||
let response: Result<Response, HttpClientError> = {
|
||||
Ok(wasmtimer::tokio::timeout(
|
||||
self.request_timeout,
|
||||
self.reqwest_client.execute(req),
|
||||
@@ -912,7 +953,11 @@ impl ApiClientCore for Client {
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
pub trait ApiClient: ApiClientCore {
|
||||
/// Create an HTTP GET Request with the provided path and parameters
|
||||
fn create_get_request<P, K, V>(&self, path: P, params: Params<'_, K, V>) -> RequestBuilder
|
||||
fn create_get_request<P, K, V>(
|
||||
&self,
|
||||
path: P,
|
||||
params: Params<'_, K, V>,
|
||||
) -> Result<RequestBuilder, HttpClientError>
|
||||
where
|
||||
P: RequestPath,
|
||||
K: AsRef<str>,
|
||||
@@ -927,7 +972,7 @@ pub trait ApiClient: ApiClientCore {
|
||||
path: P,
|
||||
params: Params<'_, K, V>,
|
||||
json_body: &B,
|
||||
) -> RequestBuilder
|
||||
) -> Result<RequestBuilder, HttpClientError>
|
||||
where
|
||||
P: RequestPath,
|
||||
B: Serialize + ?Sized,
|
||||
@@ -938,7 +983,11 @@ pub trait ApiClient: ApiClientCore {
|
||||
}
|
||||
|
||||
/// Create an HTTP DELETE Request with the provided path and parameters
|
||||
fn create_delete_request<P, K, V>(&self, path: P, params: Params<'_, K, V>) -> RequestBuilder
|
||||
fn create_delete_request<P, K, V>(
|
||||
&self,
|
||||
path: P,
|
||||
params: Params<'_, K, V>,
|
||||
) -> Result<RequestBuilder, HttpClientError>
|
||||
where
|
||||
P: RequestPath,
|
||||
K: AsRef<str>,
|
||||
@@ -953,7 +1002,7 @@ pub trait ApiClient: ApiClientCore {
|
||||
path: P,
|
||||
params: Params<'_, K, V>,
|
||||
json_body: &B,
|
||||
) -> RequestBuilder
|
||||
) -> Result<RequestBuilder, HttpClientError>
|
||||
where
|
||||
P: RequestPath,
|
||||
B: Serialize + ?Sized,
|
||||
@@ -965,68 +1014,64 @@ pub trait ApiClient: ApiClientCore {
|
||||
|
||||
/// Create and send an HTTP GET Request with the provided path and parameters
|
||||
#[instrument(level = "debug", skip_all, fields(path=?path))]
|
||||
async fn send_get_request<P, K, V, E>(
|
||||
async fn send_get_request<P, K, V>(
|
||||
&self,
|
||||
path: P,
|
||||
params: Params<'_, K, V>,
|
||||
) -> Result<Response, HttpClientError<E>>
|
||||
) -> Result<Response, HttpClientError>
|
||||
where
|
||||
P: RequestPath + Send + Sync,
|
||||
K: AsRef<str> + Sync,
|
||||
V: AsRef<str> + Sync,
|
||||
E: Display,
|
||||
{
|
||||
self.send_request(reqwest::Method::GET, path, params, None::<&()>)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Create and send an HTTP POST Request with the provided path, parameters, and json data
|
||||
async fn send_post_request<P, B, K, V, E>(
|
||||
async fn send_post_request<P, B, K, V>(
|
||||
&self,
|
||||
path: P,
|
||||
params: Params<'_, K, V>,
|
||||
json_body: &B,
|
||||
) -> Result<Response, HttpClientError<E>>
|
||||
) -> Result<Response, HttpClientError>
|
||||
where
|
||||
P: RequestPath + Send + Sync,
|
||||
B: Serialize + ?Sized + Sync,
|
||||
K: AsRef<str> + Sync,
|
||||
V: AsRef<str> + Sync,
|
||||
E: Display,
|
||||
{
|
||||
self.send_request(reqwest::Method::POST, path, params, Some(json_body))
|
||||
.await
|
||||
}
|
||||
|
||||
/// Create and send an HTTP DELETE Request with the provided path and parameters
|
||||
async fn send_delete_request<P, K, V, E>(
|
||||
async fn send_delete_request<P, K, V>(
|
||||
&self,
|
||||
path: P,
|
||||
params: Params<'_, K, V>,
|
||||
) -> Result<Response, HttpClientError<E>>
|
||||
) -> Result<Response, HttpClientError>
|
||||
where
|
||||
P: RequestPath + Send + Sync,
|
||||
K: AsRef<str> + Sync,
|
||||
V: AsRef<str> + Sync,
|
||||
E: Display,
|
||||
{
|
||||
self.send_request(reqwest::Method::DELETE, path, params, None::<&()>)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Create and send an HTTP PATCH Request with the provided path, parameters, and json data
|
||||
async fn send_patch_request<P, B, K, V, E>(
|
||||
async fn send_patch_request<P, B, K, V>(
|
||||
&self,
|
||||
path: P,
|
||||
params: Params<'_, K, V>,
|
||||
json_body: &B,
|
||||
) -> Result<Response, HttpClientError<E>>
|
||||
) -> Result<Response, HttpClientError>
|
||||
where
|
||||
P: RequestPath + Send + Sync,
|
||||
B: Serialize + ?Sized + Sync,
|
||||
K: AsRef<str> + Sync,
|
||||
V: AsRef<str> + Sync,
|
||||
E: Display,
|
||||
{
|
||||
self.send_request(reqwest::Method::PATCH, path, params, Some(json_body))
|
||||
.await
|
||||
@@ -1037,17 +1082,16 @@ pub trait ApiClient: ApiClientCore {
|
||||
/// into the provided type `T`.
|
||||
#[instrument(level = "debug", skip_all, fields(path=?path))]
|
||||
// TODO: deprecate in favour of get_response that works based on mime type in the response
|
||||
async fn get_json<P, T, K, V, E>(
|
||||
async fn get_json<P, T, K, V>(
|
||||
&self,
|
||||
path: P,
|
||||
params: Params<'_, K, V>,
|
||||
) -> Result<T, HttpClientError<E>>
|
||||
) -> Result<T, HttpClientError>
|
||||
where
|
||||
P: RequestPath + Send + Sync,
|
||||
for<'a> T: Deserialize<'a>,
|
||||
K: AsRef<str> + Sync,
|
||||
V: AsRef<str> + Sync,
|
||||
E: Display + DeserializeOwned,
|
||||
{
|
||||
self.get_response(path, params).await
|
||||
}
|
||||
@@ -1055,17 +1099,16 @@ pub trait ApiClient: ApiClientCore {
|
||||
/// 'get' data from the segment-defined path, e.g. `["api", "v1", "mixnodes"]`, with tuple
|
||||
/// defined key-value parameters, e.g. `[("since", "12345")]`. Attempt to parse the response
|
||||
/// into the provided type `T` based on the content type header
|
||||
async fn get_response<P, T, K, V, E>(
|
||||
async fn get_response<P, T, K, V>(
|
||||
&self,
|
||||
path: P,
|
||||
params: Params<'_, K, V>,
|
||||
) -> Result<T, HttpClientError<E>>
|
||||
) -> Result<T, HttpClientError>
|
||||
where
|
||||
P: RequestPath + Send + Sync,
|
||||
for<'a> T: Deserialize<'a>,
|
||||
K: AsRef<str> + Sync,
|
||||
V: AsRef<str> + Sync,
|
||||
E: Display + DeserializeOwned,
|
||||
{
|
||||
let res = self
|
||||
.send_request(reqwest::Method::GET, path, params, None::<&()>)
|
||||
@@ -1076,19 +1119,18 @@ pub trait ApiClient: ApiClientCore {
|
||||
/// 'post' json data to the segment-defined path, e.g. `["api", "v1", "mixnodes"]`, with tuple
|
||||
/// defined key-value parameters, e.g. `[("since", "12345")]`. Attempt to parse the response
|
||||
/// into the provided type `T`.
|
||||
async fn post_json<P, B, T, K, V, E>(
|
||||
async fn post_json<P, B, T, K, V>(
|
||||
&self,
|
||||
path: P,
|
||||
params: Params<'_, K, V>,
|
||||
json_body: &B,
|
||||
) -> Result<T, HttpClientError<E>>
|
||||
) -> Result<T, HttpClientError>
|
||||
where
|
||||
P: RequestPath + Send + Sync,
|
||||
B: Serialize + ?Sized + Sync,
|
||||
for<'a> T: Deserialize<'a>,
|
||||
K: AsRef<str> + Sync,
|
||||
V: AsRef<str> + Sync,
|
||||
E: Display + DeserializeOwned,
|
||||
{
|
||||
let res = self
|
||||
.send_request(reqwest::Method::POST, path, params, Some(json_body))
|
||||
@@ -1099,17 +1141,16 @@ pub trait ApiClient: ApiClientCore {
|
||||
/// 'delete' json data from the segment-defined path, e.g. `["api", "v1", "mixnodes"]`, with
|
||||
/// tuple defined key-value parameters, e.g. `[("since", "12345")]`. Attempt to parse the
|
||||
/// response into the provided type `T`.
|
||||
async fn delete_json<P, T, K, V, E>(
|
||||
async fn delete_json<P, T, K, V>(
|
||||
&self,
|
||||
path: P,
|
||||
params: Params<'_, K, V>,
|
||||
) -> Result<T, HttpClientError<E>>
|
||||
) -> Result<T, HttpClientError>
|
||||
where
|
||||
P: RequestPath + Send + Sync,
|
||||
for<'a> T: Deserialize<'a>,
|
||||
K: AsRef<str> + Sync,
|
||||
V: AsRef<str> + Sync,
|
||||
E: Display + DeserializeOwned,
|
||||
{
|
||||
let res = self
|
||||
.send_request(reqwest::Method::DELETE, path, params, None::<&()>)
|
||||
@@ -1120,19 +1161,18 @@ pub trait ApiClient: ApiClientCore {
|
||||
/// 'patch' json data at the segment-defined path, e.g. `["api", "v1", "mixnodes"]`, with tuple
|
||||
/// defined key-value parameters, e.g. `[("since", "12345")]`. Attempt to parse the response
|
||||
/// into the provided type `T`.
|
||||
async fn patch_json<P, B, T, K, V, E>(
|
||||
async fn patch_json<P, B, T, K, V>(
|
||||
&self,
|
||||
path: P,
|
||||
params: Params<'_, K, V>,
|
||||
json_body: &B,
|
||||
) -> Result<T, HttpClientError<E>>
|
||||
) -> Result<T, HttpClientError>
|
||||
where
|
||||
P: RequestPath + Send + Sync,
|
||||
B: Serialize + ?Sized + Sync,
|
||||
for<'a> T: Deserialize<'a>,
|
||||
K: AsRef<str> + Sync,
|
||||
V: AsRef<str> + Sync,
|
||||
E: Display + DeserializeOwned,
|
||||
{
|
||||
let res = self
|
||||
.send_request(reqwest::Method::PATCH, path, params, Some(json_body))
|
||||
@@ -1142,62 +1182,59 @@ pub trait ApiClient: ApiClientCore {
|
||||
|
||||
/// `get` json data from the provided absolute endpoint, e.g. `"/api/v1/mixnodes?since=12345"`.
|
||||
/// Attempt to parse the response into the provided type `T`.
|
||||
async fn get_json_from<T, S, E>(&self, endpoint: S) -> Result<T, HttpClientError<E>>
|
||||
async fn get_json_from<T, S>(&self, endpoint: S) -> Result<T, HttpClientError>
|
||||
where
|
||||
for<'a> T: Deserialize<'a>,
|
||||
E: Display + DeserializeOwned,
|
||||
S: AsRef<str> + Sync + Send,
|
||||
{
|
||||
let req = self.create_request_endpoint(reqwest::Method::GET, endpoint, None::<&()>);
|
||||
let req = self.create_request_endpoint(reqwest::Method::GET, endpoint, None::<&()>)?;
|
||||
let res = self.send(req).await?;
|
||||
parse_response(res, false).await
|
||||
}
|
||||
|
||||
/// `post` json data to the provided absolute endpoint, e.g. `"/api/v1/mixnodes?since=12345"`.
|
||||
/// Attempt to parse the response into the provided type `T`.
|
||||
async fn post_json_data_to<B, T, S, E>(
|
||||
async fn post_json_data_to<B, T, S>(
|
||||
&self,
|
||||
endpoint: S,
|
||||
json_body: &B,
|
||||
) -> Result<T, HttpClientError<E>>
|
||||
) -> Result<T, HttpClientError>
|
||||
where
|
||||
B: Serialize + ?Sized + Sync,
|
||||
for<'a> T: Deserialize<'a>,
|
||||
E: Display + DeserializeOwned,
|
||||
S: AsRef<str> + Sync + Send,
|
||||
{
|
||||
let req = self.create_request_endpoint(reqwest::Method::POST, endpoint, Some(json_body));
|
||||
let req = self.create_request_endpoint(reqwest::Method::POST, endpoint, Some(json_body))?;
|
||||
let res = self.send(req).await?;
|
||||
parse_response(res, false).await
|
||||
}
|
||||
|
||||
/// `delete` json data from the provided absolute endpoint, e.g.
|
||||
/// `"/api/v1/mixnodes?since=12345"`. Attempt to parse the response into the provided type `T`.
|
||||
async fn delete_json_from<T, S, E>(&self, endpoint: S) -> Result<T, HttpClientError<E>>
|
||||
async fn delete_json_from<T, S>(&self, endpoint: S) -> Result<T, HttpClientError>
|
||||
where
|
||||
for<'a> T: Deserialize<'a>,
|
||||
E: Display + DeserializeOwned,
|
||||
S: AsRef<str> + Sync + Send,
|
||||
{
|
||||
let req = self.create_request_endpoint(reqwest::Method::DELETE, endpoint, None::<&()>);
|
||||
let req = self.create_request_endpoint(reqwest::Method::DELETE, endpoint, None::<&()>)?;
|
||||
let res = self.send(req).await?;
|
||||
parse_response(res, false).await
|
||||
}
|
||||
|
||||
/// `patch` json data at the provided absolute endpoint, e.g. `"/api/v1/mixnodes?since=12345"`.
|
||||
/// Attempt to parse the response into the provided type `T`.
|
||||
async fn patch_json_data_at<B, T, S, E>(
|
||||
async fn patch_json_data_at<B, T, S>(
|
||||
&self,
|
||||
endpoint: S,
|
||||
json_body: &B,
|
||||
) -> Result<T, HttpClientError<E>>
|
||||
) -> Result<T, HttpClientError>
|
||||
where
|
||||
B: Serialize + ?Sized + Sync,
|
||||
for<'a> T: Deserialize<'a>,
|
||||
E: Display + DeserializeOwned,
|
||||
S: AsRef<str> + Sync + Send,
|
||||
{
|
||||
let req = self.create_request_endpoint(reqwest::Method::PATCH, endpoint, Some(json_body));
|
||||
let req =
|
||||
self.create_request_endpoint(reqwest::Method::PATCH, endpoint, Some(json_body))?;
|
||||
let res = self.send(req).await?;
|
||||
parse_response(res, false).await
|
||||
}
|
||||
@@ -1253,10 +1290,9 @@ fn decode_as_text(bytes: &bytes::Bytes, headers: &HeaderMap) -> String {
|
||||
|
||||
/// Attempt to parse a response object from an HTTP response
|
||||
#[instrument(level = "debug", skip_all)]
|
||||
pub async fn parse_response<T, E>(res: Response, allow_empty: bool) -> Result<T, HttpClientError<E>>
|
||||
pub async fn parse_response<T>(res: Response, allow_empty: bool) -> Result<T, HttpClientError>
|
||||
where
|
||||
T: DeserializeOwned,
|
||||
E: DeserializeOwned + Display,
|
||||
{
|
||||
let status = res.status();
|
||||
tracing::trace!("Status: {} (success: {})", &status, status.is_success());
|
||||
@@ -1292,10 +1328,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn decode_as_json<T, E>(headers: &HeaderMap, content: Bytes) -> Result<T, HttpClientError<E>>
|
||||
fn decode_as_json<T>(headers: &HeaderMap, content: Bytes) -> Result<T, HttpClientError>
|
||||
where
|
||||
T: DeserializeOwned,
|
||||
E: DeserializeOwned + Display,
|
||||
{
|
||||
match serde_json::from_slice(&content) {
|
||||
Ok(data) => Ok(data),
|
||||
@@ -1309,10 +1344,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn decode_as_bincode<T, E>(headers: &HeaderMap, content: Bytes) -> Result<T, HttpClientError<E>>
|
||||
fn decode_as_bincode<T>(headers: &HeaderMap, content: Bytes) -> Result<T, HttpClientError>
|
||||
where
|
||||
T: DeserializeOwned,
|
||||
E: DeserializeOwned + Display,
|
||||
{
|
||||
use bincode::Options;
|
||||
|
||||
@@ -1329,10 +1363,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn decode_raw_response<T, E>(headers: &HeaderMap, content: Bytes) -> Result<T, HttpClientError<E>>
|
||||
fn decode_raw_response<T>(headers: &HeaderMap, content: Bytes) -> Result<T, HttpClientError>
|
||||
where
|
||||
T: DeserializeOwned,
|
||||
E: DeserializeOwned + Display,
|
||||
{
|
||||
// if content type header is missing, fallback to our old default, json
|
||||
let mime = try_get_mime_type(headers).unwrap_or(mime::APPLICATION_JSON);
|
||||
|
||||
@@ -97,7 +97,7 @@ async fn api_client_retry() -> Result<(), Box<dyn std::error::Error>> {
|
||||
.with_retries(3)
|
||||
.build::<HttpClientError>()?;
|
||||
|
||||
let req = client.create_get_request(&["/"], NO_PARAMS);
|
||||
let req = client.create_get_request(&["/"], NO_PARAMS).unwrap();
|
||||
let resp = client.send::<HttpClientError>(req).await?;
|
||||
|
||||
assert_eq!(resp.status(), 200);
|
||||
|
||||
@@ -135,17 +135,15 @@ impl VerlocMeasurer {
|
||||
let mut api_endpoints = self.config.nym_api_urls.clone();
|
||||
api_endpoints.shuffle(&mut thread_rng());
|
||||
for api_endpoint in api_endpoints {
|
||||
let client =
|
||||
match nym_http_api_client::Client::builder(api_endpoint.clone()).and_then(|b| {
|
||||
b.with_user_agent(self.config.user_agent.clone())
|
||||
.build::<nym_api_requests::models::RequestError>()
|
||||
}) {
|
||||
Ok(c) => c,
|
||||
Err(err) => {
|
||||
warn!("failed to create client for {api_endpoint}: {err}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let client = match nym_http_api_client::Client::builder(api_endpoint.clone())
|
||||
.and_then(|b| b.with_user_agent(self.config.user_agent.clone()).build())
|
||||
{
|
||||
Ok(c) => c,
|
||||
Err(err) => {
|
||||
warn!("failed to create client for {api_endpoint}: {err}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
match client.get_all_described_nodes().await {
|
||||
Ok(res) => return Some(res),
|
||||
Err(err) => {
|
||||
|
||||
@@ -97,7 +97,7 @@ impl NymVpnApiClient for VpnApiClient {
|
||||
{
|
||||
let req = self
|
||||
.inner
|
||||
.create_get_request(path, NO_PARAMS)
|
||||
.create_get_request(path, NO_PARAMS)?
|
||||
.bearer_auth(&self.bearer_token)
|
||||
.send();
|
||||
|
||||
@@ -129,7 +129,7 @@ impl NymVpnApiClient for VpnApiClient {
|
||||
{
|
||||
let req = self
|
||||
.inner
|
||||
.create_post_request(path, params, json_body)
|
||||
.create_post_request(path, params, json_body)?
|
||||
.bearer_auth(&self.bearer_token)
|
||||
.send();
|
||||
|
||||
|
||||
@@ -12,9 +12,7 @@ use nym_credential_proxy_requests::api::v1::ticketbook::models::{
|
||||
};
|
||||
use nym_credentials_interface::Base58;
|
||||
use nym_validator_client::ecash::BlindSignRequestBody;
|
||||
use nym_validator_client::nyxd::Coin;
|
||||
use nym_validator_client::nym_api::NymApiClientExt;
|
||||
use rand::rngs::OsRng;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
@@ -60,7 +60,7 @@ async fn run(
|
||||
let nym_api = nym_http_api_client::ClientBuilder::new_with_urls(vec![default_api_url.into()])
|
||||
.no_hickory_dns()
|
||||
.with_timeout(nym_api_client_timeout)
|
||||
.build::<&str>()?;
|
||||
.build()?;
|
||||
|
||||
//SW TBC what nodes exactly need to be scraped, the skimmed node endpoint seems to return more nodes
|
||||
let bonded_nodes = nym_api.get_all_bonded_nym_nodes().await?;
|
||||
|
||||
@@ -109,7 +109,7 @@ impl Monitor {
|
||||
nym_http_api_client::ClientBuilder::new_with_urls(vec![default_api_url.into()])
|
||||
.no_hickory_dns()
|
||||
.with_timeout(self.nym_api_client_timeout)
|
||||
.build::<&str>()?;
|
||||
.build()?;
|
||||
|
||||
let described_nodes = nym_api
|
||||
.get_all_described_nodes()
|
||||
|
||||
@@ -5,7 +5,6 @@ use crate::api::v1::gateway::models::WebSockets;
|
||||
use crate::api::v1::node::models::{
|
||||
AuxiliaryDetails, NodeDescription, NodeRoles, SignedHostInformation,
|
||||
};
|
||||
use crate::api::ErrorResponse;
|
||||
use crate::routes;
|
||||
use async_trait::async_trait;
|
||||
use nym_bin_common::build_information::BinaryBuildInformationOwned;
|
||||
@@ -21,7 +20,7 @@ use crate::api::v1::network_requester::models::NetworkRequester;
|
||||
use crate::api::v1::node_load::models::NodeLoad;
|
||||
pub use nym_http_api_client::Client;
|
||||
|
||||
pub type NymNodeApiClientError = HttpClientError<ErrorResponse>;
|
||||
pub type NymNodeApiClientError = HttpClientError;
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
|
||||
@@ -101,10 +101,10 @@ impl NetworkRefresher {
|
||||
}
|
||||
|
||||
fn build_http_api_client(url: Url) -> Result<Client> {
|
||||
Ok(Client::builder::<_, anyhow::Error>(url)?
|
||||
Ok(Client::builder(url)?
|
||||
.no_hickory_dns()
|
||||
.with_user_agent("node-statistics-api")
|
||||
.build::<anyhow::Error>()?)
|
||||
.build()?)
|
||||
}
|
||||
|
||||
async fn refresh_network_nodes(&mut self) -> Result<()> {
|
||||
|
||||
@@ -140,7 +140,7 @@ impl NyxdClient {
|
||||
};
|
||||
|
||||
let api_client = match nym_http_api_client::Client::builder(api_address)
|
||||
.and_then(|b| b.build::<nym_validator_client::models::RequestError>())
|
||||
.and_then(|b| b.build())
|
||||
{
|
||||
Ok(client) => client,
|
||||
Err(err) => {
|
||||
|
||||
Reference in New Issue
Block a user