Updated directory_client reqwest to 0.10 (#226)
* Updated directory_client reqwest to 0.10 * Using consistent syntax
This commit is contained in:
committed by
GitHub
parent
f47b7cfb13
commit
ff2e24afbc
@@ -8,8 +8,9 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
futures = "0.3"
|
||||
pretty_env_logger = "0.3"
|
||||
reqwest = "0.9.22"
|
||||
reqwest = { version = "0.10", features = ["json"] }
|
||||
serde = { version = "1.0.104", features = ["derive"] }
|
||||
|
||||
## internal
|
||||
@@ -17,3 +18,4 @@ topology = {path = "../../topology"}
|
||||
|
||||
[dev-dependencies]
|
||||
mockito = "0.23.0"
|
||||
tokio = { version = "0.2", features = ["macros"] }
|
||||
@@ -12,24 +12,21 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::requests::health_check_get::{HealthCheckRequester, Request as HealthCheckRequest};
|
||||
use crate::requests::metrics_mixes_get::{MetricsMixRequester, Request as MetricsMixRequest};
|
||||
use crate::requests::metrics_mixes_post::{MetricsMixPoster, Request as MetricsMixPost};
|
||||
use crate::requests::presence_coconodes_post::{
|
||||
PresenceCocoNodesPoster, Request as PresenceCocoNodesPost,
|
||||
};
|
||||
use crate::requests::presence_gateways_post::{
|
||||
PresenceGatewayPoster, Request as PresenceGatewayPost,
|
||||
};
|
||||
use crate::requests::presence_mixnodes_post::{
|
||||
PresenceMixNodesPoster, Request as PresenceMixNodesPost,
|
||||
};
|
||||
use crate::requests::presence_providers_post::{
|
||||
PresenceMixProviderPoster, Request as PresenceProvidersPost,
|
||||
};
|
||||
use crate::requests::presence_topology_get::{
|
||||
PresenceTopologyGetRequester, Request as PresenceTopologyRequest,
|
||||
use crate::requests::health_check_get::Request as HealthCheckRequest;
|
||||
use crate::requests::metrics_mixes_get::Request as MetricsMixRequest;
|
||||
use crate::requests::metrics_mixes_post::Request as MetricsMixPost;
|
||||
use crate::requests::presence_coconodes_post::Request as PresenceCocoNodesPost;
|
||||
use crate::requests::presence_gateways_post::Request as PresenceGatewayPost;
|
||||
use crate::requests::presence_mixnodes_post::Request as PresenceMixNodesPost;
|
||||
use crate::requests::presence_providers_post::Request as PresenceProvidersPost;
|
||||
use crate::requests::presence_topology_get::Request as PresenceTopologyRequest;
|
||||
|
||||
use metrics::{MixMetric, PersistedMixMetric};
|
||||
use presence::{
|
||||
coconodes::CocoPresence, gateways::GatewayPresence, mixnodes::MixNodePresence,
|
||||
providers::MixProviderPresence, Topology,
|
||||
};
|
||||
use requests::{health_check_get::HealthCheckResponse, DirectoryGetRequest, DirectoryPostRequest};
|
||||
|
||||
pub mod metrics;
|
||||
pub mod presence;
|
||||
@@ -50,35 +47,100 @@ pub trait DirectoryClient {
|
||||
}
|
||||
|
||||
pub struct Client {
|
||||
pub health_check: HealthCheckRequest,
|
||||
pub metrics_mixes: MetricsMixRequest,
|
||||
pub metrics_post: MetricsMixPost,
|
||||
pub presence_coconodes_post: PresenceCocoNodesPost,
|
||||
pub presence_gateway_post: PresenceGatewayPost,
|
||||
pub presence_mix_nodes_post: PresenceMixNodesPost,
|
||||
pub presence_providers_post: PresenceProvidersPost,
|
||||
pub presence_topology: PresenceTopologyRequest,
|
||||
base_url: String,
|
||||
reqwest_client: reqwest::Client,
|
||||
}
|
||||
|
||||
impl DirectoryClient for Client {
|
||||
fn new(config: Config) -> Client {
|
||||
let health_check = HealthCheckRequest::new(config.base_url.clone());
|
||||
let metrics_mixes = MetricsMixRequest::new(config.base_url.clone());
|
||||
let metrics_post = MetricsMixPost::new(config.base_url.clone());
|
||||
let presence_topology = PresenceTopologyRequest::new(config.base_url.clone());
|
||||
let presence_coconodes_post = PresenceCocoNodesPost::new(config.base_url.clone());
|
||||
let presence_gateway_post = PresenceGatewayPost::new(config.base_url.clone());
|
||||
let presence_mix_nodes_post = PresenceMixNodesPost::new(config.base_url.clone());
|
||||
let presence_providers_post = PresenceProvidersPost::new(config.base_url);
|
||||
let reqwest_client = reqwest::Client::new();
|
||||
Client {
|
||||
health_check,
|
||||
metrics_mixes,
|
||||
metrics_post,
|
||||
presence_coconodes_post,
|
||||
presence_gateway_post,
|
||||
presence_mix_nodes_post,
|
||||
presence_providers_post,
|
||||
presence_topology,
|
||||
base_url: config.base_url,
|
||||
reqwest_client,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Client {
|
||||
async fn post<R: DirectoryPostRequest>(
|
||||
&self,
|
||||
request: R,
|
||||
) -> reqwest::Result<reqwest::Response> {
|
||||
self.reqwest_client
|
||||
.post(&request.url())
|
||||
.json(request.json_payload())
|
||||
.send()
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get<R: DirectoryGetRequest>(&self, request: R) -> reqwest::Result<R::JSONResponse> {
|
||||
self.reqwest_client
|
||||
.get(&request.url())
|
||||
.send()
|
||||
.await?
|
||||
.json()
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_healthcheck(&self) -> reqwest::Result<HealthCheckResponse> {
|
||||
let req = HealthCheckRequest::new(&self.base_url);
|
||||
self.get(req).await
|
||||
}
|
||||
|
||||
pub async fn post_mix_metrics(&self, metrics: MixMetric) -> reqwest::Result<reqwest::Response> {
|
||||
let req = MetricsMixPost::new(&self.base_url, metrics);
|
||||
self.post(req).await
|
||||
}
|
||||
|
||||
pub async fn get_mix_metrics(&self) -> reqwest::Result<Vec<PersistedMixMetric>> {
|
||||
let req = MetricsMixRequest::new(&self.base_url);
|
||||
self.get(req).await
|
||||
}
|
||||
|
||||
pub async fn post_coconode_presence(
|
||||
&self,
|
||||
presence: CocoPresence,
|
||||
) -> reqwest::Result<reqwest::Response> {
|
||||
let req = PresenceCocoNodesPost::new(&self.base_url, presence);
|
||||
self.post(req).await
|
||||
}
|
||||
|
||||
pub async fn post_gateway_presence(
|
||||
&self,
|
||||
presence: GatewayPresence,
|
||||
) -> reqwest::Result<reqwest::Response> {
|
||||
let req = PresenceGatewayPost::new(&self.base_url, presence);
|
||||
self.post(req).await
|
||||
}
|
||||
|
||||
pub async fn post_mixnode_presence(
|
||||
&self,
|
||||
presence: MixNodePresence,
|
||||
) -> reqwest::Result<reqwest::Response> {
|
||||
let req = PresenceMixNodesPost::new(&self.base_url, presence);
|
||||
self.post(req).await
|
||||
}
|
||||
|
||||
// this should be soft-deprecated as the whole concept of provider will
|
||||
// be removed in the next topology rework
|
||||
pub async fn post_provider_presence(
|
||||
&self,
|
||||
presence: MixProviderPresence,
|
||||
) -> reqwest::Result<reqwest::Response> {
|
||||
let req = PresenceProvidersPost::new(&self.base_url, presence);
|
||||
self.post(req).await
|
||||
}
|
||||
|
||||
pub async fn get_topology(&self) -> reqwest::Result<Topology> {
|
||||
let req = PresenceTopologyRequest::new(&self.base_url);
|
||||
self.get(req).await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn client_test_fixture(base_url: &str) -> Client {
|
||||
Client {
|
||||
base_url: base_url.to_string(),
|
||||
reqwest_client: reqwest::Client::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,122 +12,10 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::requests::presence_topology_get::PresenceTopologyGetRequester;
|
||||
use crate::{Client, Config, DirectoryClient};
|
||||
use log::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::convert::TryInto;
|
||||
use topology::{coco, gateway, mix, provider, NymTopology};
|
||||
|
||||
pub mod coconodes;
|
||||
pub mod gateways;
|
||||
pub mod mixnodes;
|
||||
pub mod providers;
|
||||
pub mod topology;
|
||||
|
||||
// Topology shows us the current state of the overall Nym network
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Topology {
|
||||
pub coco_nodes: Vec<coconodes::CocoPresence>,
|
||||
pub mix_nodes: Vec<mixnodes::MixNodePresence>,
|
||||
pub mix_provider_nodes: Vec<providers::MixProviderPresence>,
|
||||
pub gateway_nodes: Vec<gateways::GatewayPresence>,
|
||||
}
|
||||
|
||||
impl NymTopology for Topology {
|
||||
// TODO: this will need some changes to not imply having to make an HTTP request in constructor
|
||||
fn new(directory_server: String) -> Self {
|
||||
debug!("Using directory server: {:?}", directory_server);
|
||||
let directory_config = Config {
|
||||
base_url: directory_server,
|
||||
};
|
||||
let directory = Client::new(directory_config);
|
||||
|
||||
directory
|
||||
.presence_topology
|
||||
.get()
|
||||
.expect("Failed to retrieve network topology.")
|
||||
}
|
||||
|
||||
fn new_from_nodes(
|
||||
mix_nodes: Vec<mix::Node>,
|
||||
mix_provider_nodes: Vec<provider::Node>,
|
||||
coco_nodes: Vec<coco::Node>,
|
||||
gateway_nodes: Vec<gateway::Node>,
|
||||
) -> Self {
|
||||
Topology {
|
||||
coco_nodes: coco_nodes.into_iter().map(|node| node.into()).collect(),
|
||||
mix_nodes: mix_nodes.into_iter().map(|node| node.into()).collect(),
|
||||
mix_provider_nodes: mix_provider_nodes
|
||||
.into_iter()
|
||||
.map(|node| node.into())
|
||||
.collect(),
|
||||
gateway_nodes: gateway_nodes.into_iter().map(|node| node.into()).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn mix_nodes(&self) -> Vec<mix::Node> {
|
||||
self.mix_nodes
|
||||
.iter()
|
||||
.filter_map(|x| x.clone().try_into().ok())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn providers(&self) -> Vec<provider::Node> {
|
||||
self.mix_provider_nodes
|
||||
.iter()
|
||||
.map(|x| x.clone().into())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn gateways(&self) -> Vec<gateway::Node> {
|
||||
self.gateway_nodes
|
||||
.iter()
|
||||
.map(|x| x.clone().into())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn coco_nodes(&self) -> Vec<topology::coco::Node> {
|
||||
self.coco_nodes.iter().map(|x| x.clone().into()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod converting_mixnode_presence_into_topology_mixnode {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn it_returns_error_on_unresolvable_hostname() {
|
||||
let unresolvable_hostname = "foomp.foomp.foomp:1234";
|
||||
|
||||
let mix_presence = mixnodes::MixNodePresence {
|
||||
location: "".to_string(),
|
||||
host: unresolvable_hostname.to_string(),
|
||||
pub_key: "".to_string(),
|
||||
layer: 0,
|
||||
last_seen: 0,
|
||||
version: "".to_string(),
|
||||
};
|
||||
|
||||
let _result: Result<mix::Node, std::io::Error> = mix_presence.try_into();
|
||||
// assert!(result.is_err()) // This fails only for me. Why?
|
||||
// ¯\_(ツ)_/¯ - works on my machine (and travis)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_returns_resolved_ip_on_resolvable_hostname() {
|
||||
let resolvable_hostname = "nymtech.net:1234";
|
||||
|
||||
let mix_presence = mixnodes::MixNodePresence {
|
||||
location: "".to_string(),
|
||||
host: resolvable_hostname.to_string(),
|
||||
pub_key: "".to_string(),
|
||||
layer: 0,
|
||||
last_seen: 0,
|
||||
version: "".to_string(),
|
||||
};
|
||||
|
||||
let result: Result<topology::mix::Node, std::io::Error> = mix_presence.try_into();
|
||||
assert!(result.is_ok())
|
||||
}
|
||||
}
|
||||
pub use self::topology::Topology;
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use super::{coconodes, gateways, mixnodes, providers};
|
||||
use crate::{Client, Config, DirectoryClient};
|
||||
use futures::future::BoxFuture;
|
||||
use log::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::convert::TryInto;
|
||||
use topology::{coco, gateway, mix, provider, NymTopology};
|
||||
// Topology shows us the current state of the overall Nym network
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Topology {
|
||||
pub coco_nodes: Vec<coconodes::CocoPresence>,
|
||||
pub mix_nodes: Vec<mixnodes::MixNodePresence>,
|
||||
pub mix_provider_nodes: Vec<providers::MixProviderPresence>,
|
||||
pub gateway_nodes: Vec<gateways::GatewayPresence>,
|
||||
}
|
||||
|
||||
impl NymTopology for Topology {
|
||||
// TODO: this will need some changes to not imply having to make an HTTP request in constructor
|
||||
// TODO2: and also be reworked/removed with the topology re-work
|
||||
fn new<'a>(directory_server: String) -> BoxFuture<'a, Self> {
|
||||
debug!("Using directory server: {:?}", directory_server);
|
||||
let directory_config = Config {
|
||||
base_url: directory_server,
|
||||
};
|
||||
let directory = Client::new(directory_config);
|
||||
Box::pin({
|
||||
async move {
|
||||
directory
|
||||
.get_topology()
|
||||
.await
|
||||
.expect("Failed to retrieve network topology.")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn new_from_nodes(
|
||||
mix_nodes: Vec<mix::Node>,
|
||||
mix_provider_nodes: Vec<provider::Node>,
|
||||
coco_nodes: Vec<coco::Node>,
|
||||
gateway_nodes: Vec<gateway::Node>,
|
||||
) -> Self {
|
||||
Topology {
|
||||
coco_nodes: coco_nodes.into_iter().map(|node| node.into()).collect(),
|
||||
mix_nodes: mix_nodes.into_iter().map(|node| node.into()).collect(),
|
||||
mix_provider_nodes: mix_provider_nodes
|
||||
.into_iter()
|
||||
.map(|node| node.into())
|
||||
.collect(),
|
||||
gateway_nodes: gateway_nodes.into_iter().map(|node| node.into()).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn mix_nodes(&self) -> Vec<mix::Node> {
|
||||
self.mix_nodes
|
||||
.iter()
|
||||
.filter_map(|x| x.clone().try_into().ok())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn providers(&self) -> Vec<provider::Node> {
|
||||
self.mix_provider_nodes
|
||||
.iter()
|
||||
.map(|x| x.clone().into())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn gateways(&self) -> Vec<gateway::Node> {
|
||||
self.gateway_nodes
|
||||
.iter()
|
||||
.map(|x| x.clone().into())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn coco_nodes(&self) -> Vec<topology::coco::Node> {
|
||||
self.coco_nodes.iter().map(|x| x.clone().into()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod converting_mixnode_presence_into_topology_mixnode {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn it_returns_error_on_unresolvable_hostname() {
|
||||
let unresolvable_hostname = "foomp.foomp.foomp:1234";
|
||||
|
||||
let mix_presence = mixnodes::MixNodePresence {
|
||||
location: "".to_string(),
|
||||
host: unresolvable_hostname.to_string(),
|
||||
pub_key: "".to_string(),
|
||||
layer: 0,
|
||||
last_seen: 0,
|
||||
version: "".to_string(),
|
||||
};
|
||||
|
||||
let result: Result<mix::Node, std::io::Error> = mix_presence.try_into();
|
||||
assert!(result.is_err()) // This fails only for me. Why?
|
||||
// ¯\_(ツ)_/¯ - works on my machine (and travis)
|
||||
// Is it still broken?
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_returns_resolved_ip_on_resolvable_hostname() {
|
||||
let resolvable_hostname = "nymtech.net:1234";
|
||||
|
||||
let mix_presence = mixnodes::MixNodePresence {
|
||||
location: "".to_string(),
|
||||
host: resolvable_hostname.to_string(),
|
||||
pub_key: "".to_string(),
|
||||
layer: 0,
|
||||
last_seen: 0,
|
||||
version: "".to_string(),
|
||||
};
|
||||
|
||||
let result: Result<topology::mix::Node, std::io::Error> = mix_presence.try_into();
|
||||
assert!(result.is_ok())
|
||||
}
|
||||
}
|
||||
@@ -12,49 +12,53 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use reqwest::Response;
|
||||
use super::{DirectoryGetRequest, DirectoryRequest};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
const PATH: &str = "/api/healthcheck";
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct HealthCheckResponse {
|
||||
pub ok: bool,
|
||||
}
|
||||
|
||||
pub struct Request {
|
||||
base_url: String,
|
||||
path: String,
|
||||
}
|
||||
|
||||
pub trait HealthCheckRequester {
|
||||
fn new(base_url: String) -> Self;
|
||||
fn get(&self) -> Result<Response, reqwest::Error>;
|
||||
impl DirectoryRequest for Request {
|
||||
fn url(&self) -> String {
|
||||
format!("{}{}", self.base_url, self.path)
|
||||
}
|
||||
}
|
||||
|
||||
impl HealthCheckRequester for Request {
|
||||
fn new(base_url: String) -> Self {
|
||||
Request {
|
||||
base_url,
|
||||
path: "/api/healthcheck".to_string(),
|
||||
}
|
||||
}
|
||||
impl DirectoryGetRequest for Request {
|
||||
type JSONResponse = HealthCheckResponse;
|
||||
|
||||
fn get(&self) -> Result<Response, reqwest::Error> {
|
||||
let url = format!("{}{}", self.base_url, self.path);
|
||||
reqwest::get(&url)
|
||||
fn new(base_url: &str) -> Self {
|
||||
Request {
|
||||
base_url: base_url.to_string(),
|
||||
path: PATH.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod healthcheck_requests {
|
||||
use super::*;
|
||||
|
||||
#[cfg(test)]
|
||||
use crate::client_test_fixture;
|
||||
use mockito::mock;
|
||||
|
||||
#[cfg(test)]
|
||||
mod on_a_400_status {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn it_returns_an_error() {
|
||||
#[tokio::test]
|
||||
async fn it_returns_an_error() {
|
||||
let _m = mock("GET", "/api/healthcheck").with_status(400).create();
|
||||
let req = Request::new(mockito::server_url());
|
||||
assert!(req.get().is_err());
|
||||
let client = client_test_fixture(&mockito::server_url());
|
||||
let res = client.get_healthcheck().await;
|
||||
assert!(res.is_err());
|
||||
_m.assert();
|
||||
}
|
||||
}
|
||||
@@ -63,11 +67,18 @@ mod healthcheck_requests {
|
||||
mod on_a_200 {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn it_returns_a_response_with_200_status() {
|
||||
let _m = mock("GET", "/api/healthcheck").with_status(200).create();
|
||||
let req = Request::new(mockito::server_url());
|
||||
assert!(req.get().is_ok());
|
||||
#[tokio::test]
|
||||
async fn it_returns_a_response_with_200_status() {
|
||||
let json = r#"{
|
||||
"ok": true
|
||||
}"#;
|
||||
let _m = mock("GET", "/api/healthcheck")
|
||||
.with_status(200)
|
||||
.with_body(json)
|
||||
.create();
|
||||
let client = client_test_fixture(&mockito::server_url());
|
||||
let res = client.get_healthcheck().await;
|
||||
assert!(res.unwrap().ok);
|
||||
_m.assert();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,50 +12,49 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use super::{DirectoryGetRequest, DirectoryRequest};
|
||||
use crate::metrics::PersistedMixMetric;
|
||||
|
||||
const PATH: &str = "/api/metrics/mixes";
|
||||
|
||||
pub struct Request {
|
||||
base_url: String,
|
||||
path: String,
|
||||
}
|
||||
|
||||
pub trait MetricsMixRequester {
|
||||
fn new(base_url: String) -> Self;
|
||||
fn get(&self) -> Result<Vec<PersistedMixMetric>, reqwest::Error>;
|
||||
impl DirectoryRequest for Request {
|
||||
fn url(&self) -> String {
|
||||
format!("{}{}", self.base_url, self.path)
|
||||
}
|
||||
}
|
||||
|
||||
impl MetricsMixRequester for Request {
|
||||
fn new(base_url: String) -> Self {
|
||||
Request {
|
||||
base_url,
|
||||
path: "/api/metrics/mixes".to_string(),
|
||||
}
|
||||
}
|
||||
impl DirectoryGetRequest for Request {
|
||||
type JSONResponse = Vec<PersistedMixMetric>;
|
||||
|
||||
fn get(&self) -> Result<Vec<PersistedMixMetric>, reqwest::Error> {
|
||||
let url = format!("{}{}", self.base_url, self.path);
|
||||
let mix_metric_vec = reqwest::get(&url)?.json()?;
|
||||
Ok(mix_metric_vec)
|
||||
fn new(base_url: &str) -> Self {
|
||||
Request {
|
||||
base_url: base_url.to_string(),
|
||||
path: PATH.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod metrics_get_request {
|
||||
use super::*;
|
||||
|
||||
#[cfg(test)]
|
||||
use crate::client_test_fixture;
|
||||
use mockito::mock;
|
||||
|
||||
#[cfg(test)]
|
||||
mod on_a_400_status {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn it_returns_an_error() {
|
||||
let _m = mock("GET", "/api/metrics/mixes").with_status(400).create();
|
||||
let req = Request::new(mockito::server_url());
|
||||
req.get().unwrap();
|
||||
#[tokio::test]
|
||||
async fn it_returns_an_error() {
|
||||
let _m = mock("GET", PATH).with_status(400).create();
|
||||
let client = client_test_fixture(&mockito::server_url());
|
||||
let result = client.get_mix_metrics().await;
|
||||
assert!(result.is_err());
|
||||
_m.assert();
|
||||
}
|
||||
}
|
||||
@@ -63,20 +62,15 @@ mod metrics_get_request {
|
||||
#[cfg(test)]
|
||||
mod on_a_200 {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn it_returns_a_response_with_200_status_and_a_correct_topology() {
|
||||
#[tokio::test]
|
||||
async fn it_returns_a_response_with_200_status_and_a_correct_metrics() {
|
||||
let json = fixtures::mix_metrics_response_json();
|
||||
let _m = mock("GET", "/api/metrics/mixes")
|
||||
.with_status(200)
|
||||
.with_body(json)
|
||||
.create();
|
||||
let req = Request::new(mockito::server_url());
|
||||
let result = req.get();
|
||||
assert_eq!(true, result.is_ok());
|
||||
assert_eq!(
|
||||
1576061080635800000,
|
||||
result.unwrap().first().unwrap().timestamp
|
||||
);
|
||||
let _m = mock("GET", PATH).with_status(200).with_body(json).create();
|
||||
let client = client_test_fixture(&mockito::server_url());
|
||||
let result = client.get_mix_metrics().await;
|
||||
let unwrapped = result.unwrap();
|
||||
|
||||
assert_eq!(10, unwrapped.first().unwrap().received);
|
||||
_m.assert();
|
||||
}
|
||||
}
|
||||
@@ -84,7 +78,7 @@ mod metrics_get_request {
|
||||
#[cfg(test)]
|
||||
mod fixtures {
|
||||
#[cfg(test)]
|
||||
pub fn mix_metrics_response_json() -> String {
|
||||
pub fn mix_metrics_response_json() -> &'static str {
|
||||
r#"[
|
||||
{
|
||||
"pubKey": "OwOqwWjh_IlnaWS2PxO6odnhNahOYpRCkju50beQCTA=",
|
||||
@@ -247,7 +241,6 @@ mod metrics_get_request {
|
||||
"timestamp": 1576061080501732900
|
||||
}
|
||||
]"#
|
||||
.to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,52 +12,53 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use super::{DirectoryPostRequest, DirectoryRequest};
|
||||
use crate::metrics::MixMetric;
|
||||
use reqwest::Response;
|
||||
|
||||
const PATH: &str = "/api/metrics/mixes";
|
||||
|
||||
pub struct Request {
|
||||
base_url: String,
|
||||
path: String,
|
||||
payload: MixMetric,
|
||||
}
|
||||
|
||||
pub trait MetricsMixPoster {
|
||||
fn new(base_url: String) -> Self;
|
||||
fn post(&self, metric: &MixMetric) -> Result<Response, reqwest::Error>;
|
||||
impl DirectoryRequest for Request {
|
||||
fn url(&self) -> String {
|
||||
format!("{}{}", self.base_url, self.path)
|
||||
}
|
||||
}
|
||||
|
||||
impl MetricsMixPoster for Request {
|
||||
fn new(base_url: String) -> Self {
|
||||
Request {
|
||||
base_url,
|
||||
path: "/api/metrics/mixes".to_string(),
|
||||
}
|
||||
impl DirectoryPostRequest for Request {
|
||||
type Payload = MixMetric;
|
||||
fn json_payload(&self) -> &MixMetric {
|
||||
&self.payload
|
||||
}
|
||||
|
||||
fn post(&self, metric: &MixMetric) -> Result<Response, reqwest::Error> {
|
||||
let url = format!("{}{}", self.base_url, self.path);
|
||||
let client = reqwest::Client::new();
|
||||
let mix_metric_vec = client.post(&url).json(&metric).send()?;
|
||||
Ok(mix_metric_vec)
|
||||
fn new(base_url: &str, payload: Self::Payload) -> Self {
|
||||
Request {
|
||||
base_url: base_url.to_string(),
|
||||
path: PATH.to_string(),
|
||||
payload,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod metrics_get_request {
|
||||
mod metrics_post_request {
|
||||
use super::*;
|
||||
|
||||
#[cfg(test)]
|
||||
use crate::client_test_fixture;
|
||||
use mockito::mock;
|
||||
|
||||
#[cfg(test)]
|
||||
mod on_a_400_status {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn it_returns_an_error() {
|
||||
let _m = mock("POST", "/api/metrics/mixes").with_status(400).create();
|
||||
let req = Request::new(mockito::server_url());
|
||||
let metric = fixtures::new_metric();
|
||||
let result = req.post(&metric);
|
||||
#[tokio::test]
|
||||
async fn it_returns_an_error() {
|
||||
let _m = mock("POST", PATH).with_status(400).create();
|
||||
let client = client_test_fixture(&mockito::server_url());
|
||||
let result = client.post_mix_metrics(fixtures::new_metric()).await;
|
||||
assert_eq!(400, result.unwrap().status());
|
||||
_m.assert();
|
||||
}
|
||||
@@ -66,17 +67,16 @@ mod metrics_get_request {
|
||||
#[cfg(test)]
|
||||
mod on_a_200 {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn it_returns_a_response_with_200() {
|
||||
#[tokio::test]
|
||||
async fn it_returns_a_response_with_200() {
|
||||
let json = fixtures::mix_metrics_response_json();
|
||||
let _m = mock("POST", "/api/metrics/mixes")
|
||||
.with_status(201)
|
||||
.with_body(json)
|
||||
.create();
|
||||
let req = Request::new(mockito::server_url());
|
||||
let metric = fixtures::new_metric();
|
||||
let result = req.post(&metric);
|
||||
assert_eq!(true, result.is_ok());
|
||||
let client = client_test_fixture(&mockito::server_url());
|
||||
let result = client.post_mix_metrics(fixtures::new_metric()).await;
|
||||
assert!(result.is_ok());
|
||||
_m.assert();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,3 +20,26 @@ pub mod presence_gateways_post;
|
||||
pub mod presence_mixnodes_post;
|
||||
pub mod presence_providers_post;
|
||||
pub mod presence_topology_get;
|
||||
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
|
||||
pub(crate) trait DirectoryRequest {
|
||||
fn url(&self) -> String;
|
||||
}
|
||||
|
||||
pub(crate) trait DirectoryGetRequest: DirectoryRequest {
|
||||
// perhaps the name of this is not the best because it's technically not a JSON,
|
||||
// but something that can be deserialised from JSON.
|
||||
// I'm open to all suggestions on how to rename it
|
||||
type JSONResponse: DeserializeOwned;
|
||||
|
||||
fn new(base_url: &str) -> Self;
|
||||
}
|
||||
|
||||
pub(crate) trait DirectoryPostRequest: DirectoryRequest {
|
||||
// Similarly this, it's something that can be serialized into a JSON
|
||||
type Payload: Serialize + ?Sized;
|
||||
|
||||
fn new(base_url: &str, payload: Self::Payload) -> Self;
|
||||
fn json_payload(&self) -> &Self::Payload;
|
||||
}
|
||||
|
||||
@@ -12,54 +12,54 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use super::{DirectoryPostRequest, DirectoryRequest};
|
||||
use crate::presence::coconodes::CocoPresence;
|
||||
use reqwest::Response;
|
||||
|
||||
const PATH: &str = "/api/presence/coconodes";
|
||||
|
||||
pub struct Request {
|
||||
base_url: String,
|
||||
path: String,
|
||||
payload: CocoPresence,
|
||||
}
|
||||
|
||||
pub trait PresenceCocoNodesPoster {
|
||||
fn new(base_url: String) -> Self;
|
||||
fn post(&self, presence: &CocoPresence) -> Result<Response, reqwest::Error>;
|
||||
impl DirectoryRequest for Request {
|
||||
fn url(&self) -> String {
|
||||
format!("{}{}", self.base_url, self.path)
|
||||
}
|
||||
}
|
||||
|
||||
impl PresenceCocoNodesPoster for Request {
|
||||
fn new(base_url: String) -> Self {
|
||||
Request {
|
||||
base_url,
|
||||
path: "/api/presence/coconodes".to_string(),
|
||||
}
|
||||
impl DirectoryPostRequest for Request {
|
||||
type Payload = CocoPresence;
|
||||
fn json_payload(&self) -> &CocoPresence {
|
||||
&self.payload
|
||||
}
|
||||
|
||||
fn post(&self, presence: &CocoPresence) -> Result<Response, reqwest::Error> {
|
||||
let url = format!("{}{}", self.base_url, self.path);
|
||||
let client = reqwest::Client::new();
|
||||
let p = client.post(&url).json(&presence).send()?;
|
||||
Ok(p)
|
||||
fn new(base_url: &str, payload: Self::Payload) -> Self {
|
||||
Request {
|
||||
base_url: base_url.to_string(),
|
||||
path: PATH.to_string(),
|
||||
payload,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod metrics_get_request {
|
||||
mod presence_coconodes_post_request {
|
||||
use super::*;
|
||||
|
||||
#[cfg(test)]
|
||||
use crate::client_test_fixture;
|
||||
use mockito::mock;
|
||||
|
||||
#[cfg(test)]
|
||||
mod on_a_400_status {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn it_returns_an_error() {
|
||||
let _m = mock("POST", "/api/presence/coconodes")
|
||||
.with_status(400)
|
||||
.create();
|
||||
let req = Request::new(mockito::server_url());
|
||||
#[tokio::test]
|
||||
async fn it_returns_an_error() {
|
||||
let _m = mock("POST", PATH).with_status(400).create();
|
||||
let client = client_test_fixture(&mockito::server_url());
|
||||
let presence = fixtures::new_presence();
|
||||
let result = req.post(&presence);
|
||||
let result = client.post_coconode_presence(presence).await;
|
||||
assert_eq!(400, result.unwrap().status());
|
||||
_m.assert();
|
||||
}
|
||||
@@ -68,19 +68,16 @@ mod metrics_get_request {
|
||||
#[cfg(test)]
|
||||
mod on_a_200 {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn it_returns_a_response_with_201() {
|
||||
#[tokio::test]
|
||||
async fn it_returns_a_response_with_201() {
|
||||
let json = r#"{
|
||||
"ok": true
|
||||
}"#;
|
||||
let _m = mock("POST", "/api/presence/coconodes")
|
||||
.with_status(201)
|
||||
.with_body(json)
|
||||
.create();
|
||||
let req = Request::new(mockito::server_url());
|
||||
let _m = mock("POST", PATH).with_status(201).with_body(json).create();
|
||||
let client = client_test_fixture(&mockito::server_url());
|
||||
let presence = fixtures::new_presence();
|
||||
let result = req.post(&presence);
|
||||
assert_eq!(true, result.is_ok());
|
||||
let result = client.post_coconode_presence(presence).await;
|
||||
assert!(result.is_ok());
|
||||
_m.assert();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,54 +12,54 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use super::{DirectoryPostRequest, DirectoryRequest};
|
||||
use crate::presence::gateways::GatewayPresence;
|
||||
use reqwest::Response;
|
||||
|
||||
const PATH: &str = "/api/presence/gateways";
|
||||
|
||||
pub struct Request {
|
||||
base_url: String,
|
||||
path: String,
|
||||
payload: GatewayPresence,
|
||||
}
|
||||
|
||||
pub trait PresenceGatewayPoster {
|
||||
fn new(base_url: String) -> Self;
|
||||
fn post(&self, presence: &GatewayPresence) -> Result<Response, reqwest::Error>;
|
||||
impl DirectoryRequest for Request {
|
||||
fn url(&self) -> String {
|
||||
format!("{}{}", self.base_url, self.path)
|
||||
}
|
||||
}
|
||||
|
||||
impl PresenceGatewayPoster for Request {
|
||||
fn new(base_url: String) -> Self {
|
||||
Request {
|
||||
base_url,
|
||||
path: "/api/presence/gateways".to_string(),
|
||||
}
|
||||
impl DirectoryPostRequest for Request {
|
||||
type Payload = GatewayPresence;
|
||||
fn json_payload(&self) -> &GatewayPresence {
|
||||
&self.payload
|
||||
}
|
||||
|
||||
fn post(&self, presence: &GatewayPresence) -> Result<Response, reqwest::Error> {
|
||||
let url = format!("{}{}", self.base_url, self.path);
|
||||
let client = reqwest::Client::new();
|
||||
let p = client.post(&url).json(&presence).send()?;
|
||||
Ok(p)
|
||||
fn new(base_url: &str, payload: Self::Payload) -> Self {
|
||||
Request {
|
||||
base_url: base_url.to_string(),
|
||||
path: PATH.to_string(),
|
||||
payload,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod metrics_get_request {
|
||||
mod presence_gateways_post_request {
|
||||
use super::*;
|
||||
|
||||
#[cfg(test)]
|
||||
use crate::client_test_fixture;
|
||||
use mockito::mock;
|
||||
|
||||
#[cfg(test)]
|
||||
mod on_a_400_status {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn it_returns_an_error() {
|
||||
let _m = mock("POST", "/api/presence/gateways")
|
||||
.with_status(400)
|
||||
.create();
|
||||
let req = Request::new(mockito::server_url());
|
||||
#[tokio::test]
|
||||
async fn it_returns_an_error() {
|
||||
let _m = mock("POST", PATH).with_status(400).create();
|
||||
let client = client_test_fixture(&mockito::server_url());
|
||||
let presence = fixtures::new_presence();
|
||||
let result = req.post(&presence);
|
||||
let result = client.post_gateway_presence(presence).await;
|
||||
assert_eq!(400, result.unwrap().status());
|
||||
_m.assert();
|
||||
}
|
||||
@@ -68,19 +68,16 @@ mod metrics_get_request {
|
||||
#[cfg(test)]
|
||||
mod on_a_200 {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn it_returns_a_response_with_201() {
|
||||
#[tokio::test]
|
||||
async fn it_returns_a_response_with_201() {
|
||||
let json = r#"{
|
||||
"ok": true
|
||||
}"#;
|
||||
let _m = mock("POST", "/api/presence/gateways")
|
||||
.with_status(201)
|
||||
.with_body(json)
|
||||
.create();
|
||||
let req = Request::new(mockito::server_url());
|
||||
let _m = mock("POST", PATH).with_status(201).with_body(json).create();
|
||||
let client = client_test_fixture(&mockito::server_url());
|
||||
let presence = fixtures::new_presence();
|
||||
let result = req.post(&presence);
|
||||
assert_eq!(true, result.is_ok());
|
||||
let result = client.post_gateway_presence(presence).await;
|
||||
assert!(result.is_ok());
|
||||
_m.assert();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,54 +12,54 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use super::{DirectoryPostRequest, DirectoryRequest};
|
||||
use crate::presence::mixnodes::MixNodePresence;
|
||||
use reqwest::Response;
|
||||
|
||||
const PATH: &str = "/api/presence/mixnodes";
|
||||
|
||||
pub struct Request {
|
||||
base_url: String,
|
||||
path: String,
|
||||
payload: MixNodePresence,
|
||||
}
|
||||
|
||||
pub trait PresenceMixNodesPoster {
|
||||
fn new(base_url: String) -> Self;
|
||||
fn post(&self, presence: &MixNodePresence) -> Result<Response, reqwest::Error>;
|
||||
impl DirectoryRequest for Request {
|
||||
fn url(&self) -> String {
|
||||
format!("{}{}", self.base_url, self.path)
|
||||
}
|
||||
}
|
||||
|
||||
impl PresenceMixNodesPoster for Request {
|
||||
fn new(base_url: String) -> Self {
|
||||
Request {
|
||||
base_url,
|
||||
path: "/api/presence/mixnodes".to_string(),
|
||||
}
|
||||
impl DirectoryPostRequest for Request {
|
||||
type Payload = MixNodePresence;
|
||||
fn json_payload(&self) -> &MixNodePresence {
|
||||
&self.payload
|
||||
}
|
||||
|
||||
fn post(&self, presence: &MixNodePresence) -> Result<Response, reqwest::Error> {
|
||||
let url = format!("{}{}", self.base_url, self.path);
|
||||
let client = reqwest::Client::new();
|
||||
let p = client.post(&url).json(&presence).send()?;
|
||||
Ok(p)
|
||||
fn new(base_url: &str, payload: Self::Payload) -> Self {
|
||||
Request {
|
||||
base_url: base_url.to_string(),
|
||||
path: PATH.to_string(),
|
||||
payload,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod metrics_get_request {
|
||||
mod presence_mixnodes_post_request {
|
||||
use super::*;
|
||||
|
||||
#[cfg(test)]
|
||||
use crate::client_test_fixture;
|
||||
use mockito::mock;
|
||||
|
||||
#[cfg(test)]
|
||||
mod on_a_400_status {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn it_returns_an_error() {
|
||||
let _m = mock("POST", "/api/presence/mixnodes")
|
||||
.with_status(400)
|
||||
.create();
|
||||
let req = Request::new(mockito::server_url());
|
||||
#[tokio::test]
|
||||
async fn it_returns_an_error() {
|
||||
let _m = mock("POST", PATH).with_status(400).create();
|
||||
let client = client_test_fixture(&mockito::server_url());
|
||||
let presence = fixtures::new_presence();
|
||||
let result = req.post(&presence);
|
||||
let result = client.post_mixnode_presence(presence).await;
|
||||
assert_eq!(400, result.unwrap().status());
|
||||
_m.assert();
|
||||
}
|
||||
@@ -68,19 +68,16 @@ mod metrics_get_request {
|
||||
#[cfg(test)]
|
||||
mod on_a_200 {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn it_returns_a_response_with_201() {
|
||||
#[tokio::test]
|
||||
async fn it_returns_a_response_with_201() {
|
||||
let json = r#"{
|
||||
"ok": true
|
||||
}"#;
|
||||
let _m = mock("POST", "/api/presence/mixnodes")
|
||||
.with_status(201)
|
||||
.with_body(json)
|
||||
.create();
|
||||
let req = Request::new(mockito::server_url());
|
||||
let _m = mock("POST", PATH).with_status(201).with_body(json).create();
|
||||
let client = client_test_fixture(&mockito::server_url());
|
||||
let presence = fixtures::new_presence();
|
||||
let result = req.post(&presence);
|
||||
assert_eq!(true, result.is_ok());
|
||||
let result = client.post_mixnode_presence(presence).await;
|
||||
assert!(result.is_ok());
|
||||
_m.assert();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,54 +12,54 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use super::{DirectoryPostRequest, DirectoryRequest};
|
||||
use crate::presence::providers::MixProviderPresence;
|
||||
use reqwest::Response;
|
||||
|
||||
const PATH: &str = "/api/presence/mixproviders";
|
||||
|
||||
pub struct Request {
|
||||
base_url: String,
|
||||
path: String,
|
||||
payload: MixProviderPresence,
|
||||
}
|
||||
|
||||
pub trait PresenceMixProviderPoster {
|
||||
fn new(base_url: String) -> Self;
|
||||
fn post(&self, presence: &MixProviderPresence) -> Result<Response, reqwest::Error>;
|
||||
impl DirectoryRequest for Request {
|
||||
fn url(&self) -> String {
|
||||
format!("{}{}", self.base_url, self.path)
|
||||
}
|
||||
}
|
||||
|
||||
impl PresenceMixProviderPoster for Request {
|
||||
fn new(base_url: String) -> Self {
|
||||
Request {
|
||||
base_url,
|
||||
path: "/api/presence/mixproviders".to_string(),
|
||||
}
|
||||
impl DirectoryPostRequest for Request {
|
||||
type Payload = MixProviderPresence;
|
||||
fn json_payload(&self) -> &MixProviderPresence {
|
||||
&self.payload
|
||||
}
|
||||
|
||||
fn post(&self, presence: &MixProviderPresence) -> Result<Response, reqwest::Error> {
|
||||
let url = format!("{}{}", self.base_url, self.path);
|
||||
let client = reqwest::Client::new();
|
||||
let p = client.post(&url).json(&presence).send()?;
|
||||
Ok(p)
|
||||
fn new(base_url: &str, payload: Self::Payload) -> Self {
|
||||
Request {
|
||||
base_url: base_url.to_string(),
|
||||
path: PATH.to_string(),
|
||||
payload,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod metrics_get_request {
|
||||
mod presence_providers_post_request {
|
||||
use super::*;
|
||||
|
||||
#[cfg(test)]
|
||||
use crate::client_test_fixture;
|
||||
use mockito::mock;
|
||||
|
||||
#[cfg(test)]
|
||||
mod on_a_400_status {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn it_returns_an_error() {
|
||||
let _m = mock("POST", "/api/presence/mixproviders")
|
||||
.with_status(400)
|
||||
.create();
|
||||
let req = Request::new(mockito::server_url());
|
||||
#[tokio::test]
|
||||
async fn it_returns_an_error() {
|
||||
let _m = mock("POST", PATH).with_status(400).create();
|
||||
let client = client_test_fixture(&mockito::server_url());
|
||||
let presence = fixtures::new_presence();
|
||||
let result = req.post(&presence);
|
||||
let result = client.post_provider_presence(presence).await;
|
||||
assert_eq!(400, result.unwrap().status());
|
||||
_m.assert();
|
||||
}
|
||||
@@ -68,19 +68,16 @@ mod metrics_get_request {
|
||||
#[cfg(test)]
|
||||
mod on_a_200 {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn it_returns_a_response_with_201() {
|
||||
#[tokio::test]
|
||||
async fn it_returns_a_response_with_201() {
|
||||
let json = r#"{
|
||||
"ok": true
|
||||
}"#;
|
||||
let _m = mock("POST", "/api/presence/mixproviders")
|
||||
.with_status(201)
|
||||
.with_body(json)
|
||||
.create();
|
||||
let req = Request::new(mockito::server_url());
|
||||
let _m = mock("POST", PATH).with_status(201).with_body(json).create();
|
||||
let client = client_test_fixture(&mockito::server_url());
|
||||
let presence = fixtures::new_presence();
|
||||
let result = req.post(&presence);
|
||||
assert_eq!(true, result.is_ok());
|
||||
let result = client.post_provider_presence(presence).await;
|
||||
assert!(result.is_ok());
|
||||
_m.assert();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,73 +12,71 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use super::{DirectoryGetRequest, DirectoryRequest};
|
||||
use crate::presence::Topology;
|
||||
|
||||
const PATH: &str = "/api/presence/topology";
|
||||
|
||||
pub struct Request {
|
||||
base_url: String,
|
||||
path: String,
|
||||
}
|
||||
|
||||
pub trait PresenceTopologyGetRequester {
|
||||
fn new(base_url: String) -> Self;
|
||||
fn get(&self) -> Result<Topology, reqwest::Error>;
|
||||
impl DirectoryRequest for Request {
|
||||
fn url(&self) -> String {
|
||||
format!("{}{}", self.base_url, self.path)
|
||||
}
|
||||
}
|
||||
|
||||
impl PresenceTopologyGetRequester for Request {
|
||||
fn new(base_url: String) -> Self {
|
||||
Request {
|
||||
base_url,
|
||||
path: "/api/presence/topology".to_string(),
|
||||
}
|
||||
}
|
||||
impl DirectoryGetRequest for Request {
|
||||
type JSONResponse = Topology;
|
||||
|
||||
fn get(&self) -> Result<Topology, reqwest::Error> {
|
||||
let url = format!("{}{}", self.base_url, self.path);
|
||||
let topology: Topology = reqwest::get(&url)?.json()?;
|
||||
Ok(topology)
|
||||
fn new(base_url: &str) -> Self {
|
||||
Request {
|
||||
base_url: base_url.to_string(),
|
||||
path: PATH.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod topology_requests {
|
||||
use super::*;
|
||||
#[cfg(test)]
|
||||
use crate::client_test_fixture;
|
||||
use mockito::mock;
|
||||
|
||||
#[cfg(test)]
|
||||
mod on_a_400_status {
|
||||
use super::*;
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn it_panics() {
|
||||
let _m = mock("GET", "/api/presence/topology")
|
||||
#[tokio::test]
|
||||
async fn it_returns_an_error() {
|
||||
let _m = mock("GET", PATH)
|
||||
.with_status(400)
|
||||
.with_body("bad body")
|
||||
.create();
|
||||
let req = Request::new(mockito::server_url());
|
||||
req.get().unwrap();
|
||||
let client = client_test_fixture(&mockito::server_url());
|
||||
let result = client.get_topology().await;
|
||||
assert!(result.is_err());
|
||||
_m.assert();
|
||||
}
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod on_a_200 {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn it_returns_a_response_with_200_status_and_a_correct_topology() {
|
||||
#[tokio::test]
|
||||
async fn it_returns_a_response_with_200_status_and_a_correct_topology() {
|
||||
let json = fixtures::topology_response_json();
|
||||
let _m = mock("GET", "/api/presence/topology")
|
||||
.with_status(200)
|
||||
.with_body(json)
|
||||
.create();
|
||||
let req = Request::new(mockito::server_url());
|
||||
let result = req.get();
|
||||
assert!(result.is_ok());
|
||||
let _m = mock("GET", PATH).with_status(200).with_body(json).create();
|
||||
let client = client_test_fixture(&mockito::server_url());
|
||||
let result = client.get_topology().await;
|
||||
assert_eq!(
|
||||
1575915097085539300,
|
||||
1_575_915_097_085_539_300,
|
||||
result.unwrap().coco_nodes.first().unwrap().last_seen
|
||||
);
|
||||
_m.assert();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod fixtures {
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -9,6 +9,7 @@ edition = "2018"
|
||||
[dependencies]
|
||||
bs58 = "0.3.0"
|
||||
itertools = "0.8.2"
|
||||
futures = "0.3"
|
||||
log = "0.4"
|
||||
pretty_env_logger = "0.3"
|
||||
rand = "0.7.2"
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
use crate::filter::VersionFilterable;
|
||||
use futures::future::BoxFuture;
|
||||
use itertools::Itertools;
|
||||
use nymsphinx::Node as SphinxNode;
|
||||
use rand::seq::IteratorRandom;
|
||||
@@ -28,7 +29,10 @@ pub mod provider;
|
||||
// TODO: Figure out why 'Clone' was required to have 'TopologyAccessor<T>' working
|
||||
// even though it only contains an Arc
|
||||
pub trait NymTopology: Sized + std::fmt::Debug + Send + Sync + Clone {
|
||||
fn new(directory_server: String) -> Self;
|
||||
// this is just a temporary work-around to make current code work without having to
|
||||
// do major topology rewrites now.
|
||||
// This will be removed once topology is re-worked
|
||||
fn new<'a>(directory_server: String) -> BoxFuture<'a, Self>;
|
||||
fn new_from_nodes(
|
||||
mix_nodes: Vec<mix::Node>,
|
||||
mix_provider_nodes: Vec<provider::Node>,
|
||||
|
||||
Reference in New Issue
Block a user