Added minimal sdk, simplified test using the sdk's client
This commit is contained in:
parent
a75c115761
commit
84784599a7
16 changed files with 379 additions and 83 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -3060,6 +3060,7 @@ dependencies = [
|
|||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"ubisync-lib",
|
||||
"ubisync-sdk",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
|
@ -3088,6 +3089,15 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ubisync-sdk"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"ubisync-lib",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ucd-trie"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
[workspace]
|
||||
resolver = "2"
|
||||
|
||||
members = [
|
||||
"ubisync",
|
||||
|
|
|
@ -10,6 +10,7 @@ axum = { version = "0.7.2", features = [ "macros" ] }
|
|||
chrono = "0.4.31"
|
||||
itertools = "0.12.0"
|
||||
jsonwebtoken = "9.2.0"
|
||||
reqwest = "0.11.23"
|
||||
serde = { version = "1.0.166", features = [ "derive" ] }
|
||||
serde_json = "1.0.99"
|
||||
serde_with = "3.3.0"
|
||||
|
|
28
ubisync-lib/src/api/app.rs
Normal file
28
ubisync-lib/src/api/app.rs
Normal file
|
@ -0,0 +1,28 @@
|
|||
use reqwest::Method;
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
use super::UbisyncRequest;
|
||||
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct AppRegisterRequest {
|
||||
pub name: String,
|
||||
pub description: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct AppRegisterResponse {
|
||||
pub token: String,
|
||||
}
|
||||
|
||||
impl UbisyncRequest for AppRegisterRequest {
|
||||
type PathParameters = ();
|
||||
type Response = AppRegisterResponse;
|
||||
|
||||
fn method(&self) -> reqwest::Method {
|
||||
Method::PUT
|
||||
}
|
||||
fn path(&self, _: Self::PathParameters) -> String {
|
||||
"/app/register".to_string()
|
||||
}
|
||||
}
|
88
ubisync-lib/src/api/element.rs
Normal file
88
ubisync-lib/src/api/element.rs
Normal file
|
@ -0,0 +1,88 @@
|
|||
use reqwest::Method;
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
use crate::types::{ElementContent, ElementId, Element};
|
||||
|
||||
use super::UbisyncRequest;
|
||||
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct ElementCreateRequest {
|
||||
pub content: ElementContent,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct ElementCreateResponse {
|
||||
pub id: ElementId,
|
||||
}
|
||||
|
||||
impl UbisyncRequest for ElementCreateRequest {
|
||||
type PathParameters = ();
|
||||
type Response = ElementCreateResponse;
|
||||
|
||||
fn method(&self) -> Method {
|
||||
Method::PUT
|
||||
}
|
||||
fn path(&self, _: Self::PathParameters) -> String {
|
||||
"/element".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct ElementGetRequest;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct ElementGetResponse {
|
||||
pub element: Element,
|
||||
}
|
||||
|
||||
impl UbisyncRequest for ElementGetRequest {
|
||||
type PathParameters = ElementId;
|
||||
type Response = ElementGetResponse;
|
||||
|
||||
fn method(&self) -> Method {
|
||||
Method::GET
|
||||
}
|
||||
fn path(&self, params: Self::PathParameters) -> String {
|
||||
format!("/element/{}", params.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct ElementSetRequest {
|
||||
pub content: ElementContent,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct ElementSetResponse;
|
||||
|
||||
impl UbisyncRequest for ElementSetRequest {
|
||||
type PathParameters = ElementId;
|
||||
type Response = ElementSetResponse;
|
||||
|
||||
fn method(&self) -> Method {
|
||||
Method::POST
|
||||
}
|
||||
fn path(&self, params: Self::PathParameters) -> String {
|
||||
format!("/element/{}", serde_json::to_string(¶ms).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct ElementRemoveRequest;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct ElementRemoveResponse;
|
||||
|
||||
impl UbisyncRequest for ElementRemoveRequest {
|
||||
type PathParameters = ElementId;
|
||||
type Response = ElementRemoveResponse;
|
||||
|
||||
fn method(&self) -> Method {
|
||||
Method::DELETE
|
||||
}
|
||||
fn path(&self, params: Self::PathParameters) -> String {
|
||||
format!("/element/{}", serde_json::to_string(¶ms).unwrap())
|
||||
}
|
||||
}
|
23
ubisync-lib/src/api/mod.rs
Normal file
23
ubisync-lib/src/api/mod.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
use async_trait::async_trait;
|
||||
use reqwest::Method;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub mod app;
|
||||
pub mod element;
|
||||
|
||||
/// Any struct defining a request body for the ubisync API must implement this trait
|
||||
/// It is used both by the client in the SDK and by the API logic in the ubisync node
|
||||
#[async_trait]
|
||||
pub trait UbisyncRequest: for<'de> Deserialize<'de> + Serialize {
|
||||
type PathParameters;
|
||||
type Response: for<'de> Deserialize<'de> + Serialize;
|
||||
|
||||
fn method(&self) -> Method;
|
||||
fn path(&self, params: Self::PathParameters) -> String;
|
||||
async fn parse_response(resp: reqwest::Response) -> Result<Self::Response, reqwest::Error>
|
||||
where
|
||||
for<'de> <Self as UbisyncRequest>::Response: Deserialize<'de>,
|
||||
{
|
||||
resp.json().await
|
||||
}
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
pub mod api;
|
||||
pub mod messages;
|
||||
pub mod types;
|
||||
pub mod peer;
|
||||
pub mod types;
|
||||
|
|
|
@ -6,3 +6,11 @@ edition = "2021"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.79"
|
||||
reqwest = { version = "0.11.23", features = [ "json" ] }
|
||||
serde = { version = "1.0.166", features = [ "derive" ] }
|
||||
serde_json = "1.0.99"
|
||||
tracing = "0.1.37"
|
||||
tracing-subscriber = "0.3.17"
|
||||
|
||||
ubisync-lib = { path = "../ubisync-lib" }
|
20
ubisync-sdk/src/error.rs
Normal file
20
ubisync-sdk/src/error.rs
Normal file
|
@ -0,0 +1,20 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum UbisyncError {
|
||||
InvalidNodeReply(String),
|
||||
AppRegistrationFailed,
|
||||
}
|
||||
|
||||
impl Display for UbisyncError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::InvalidNodeReply(msg) => write!(f, "Invalid reply from ubisync node: {}", msg),
|
||||
Self::AppRegistrationFailed => write!(f, "Registrating this app at the ubisync node failed."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for UbisyncError {}
|
|
@ -0,0 +1,118 @@
|
|||
use anyhow::anyhow;
|
||||
use error::UbisyncError;
|
||||
use reqwest::{Client, StatusCode};
|
||||
use ubisync_lib::api::{
|
||||
app::{AppRegisterRequest, AppRegisterResponse},
|
||||
UbisyncRequest,
|
||||
};
|
||||
pub use ubisync_lib::*;
|
||||
|
||||
pub mod error;
|
||||
|
||||
pub struct UbisyncClient {
|
||||
host: String,
|
||||
port: u16,
|
||||
selected_api_version: String,
|
||||
base_url: String,
|
||||
jwt_token: String,
|
||||
reqwest_client: Client,
|
||||
}
|
||||
|
||||
impl UbisyncClient {
|
||||
pub async fn init(
|
||||
host: &str,
|
||||
port: u16,
|
||||
jwt_token: Option<&str>,
|
||||
application_name: &str,
|
||||
application_description: &str,
|
||||
) -> Result<Self, UbisyncError> {
|
||||
let http_client = Client::new();
|
||||
let mut node_api_versions = http_client
|
||||
.get(&format!("http://{}:{}/versions", host, port))
|
||||
.send()
|
||||
.await
|
||||
.expect("Failed to contact ubisync node, it may be offline.")
|
||||
.json::<Vec<String>>()
|
||||
.await
|
||||
.expect("Failed to read ubisync node's available API versions.");
|
||||
|
||||
node_api_versions.sort();
|
||||
let selected_version = node_api_versions
|
||||
.get(0)
|
||||
.expect("No available API version returned by ubisync node");
|
||||
|
||||
let token = match jwt_token {
|
||||
Some(t) => t.to_string(),
|
||||
None => {
|
||||
let response = http_client
|
||||
.put(Self::build_base_url(host, port, &selected_version) + "/app/register")
|
||||
.json(&AppRegisterRequest {
|
||||
name: application_name.to_string(),
|
||||
description: application_description.to_string(),
|
||||
})
|
||||
.send()
|
||||
.await
|
||||
.expect("App registration request failed.");
|
||||
if response.status() != StatusCode::OK {
|
||||
return Err(UbisyncError::AppRegistrationFailed);
|
||||
}
|
||||
response
|
||||
.json::<AppRegisterResponse>()
|
||||
.await
|
||||
.expect("Failed to extract JWT from app regstration request")
|
||||
.token
|
||||
}
|
||||
};
|
||||
|
||||
Ok(UbisyncClient {
|
||||
host: host.to_string(),
|
||||
port: port,
|
||||
selected_api_version: selected_version.to_string(),
|
||||
base_url: Self::build_base_url(host, port, selected_version),
|
||||
jwt_token: token.to_string(),
|
||||
reqwest_client: http_client,
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn send<R>(
|
||||
&self,
|
||||
request: R,
|
||||
parameters: R::PathParameters,
|
||||
) -> anyhow::Result<R::Response>
|
||||
where
|
||||
R: UbisyncRequest,
|
||||
{
|
||||
self.reqwest_client
|
||||
.request(
|
||||
request.method(),
|
||||
&(self.base_url.to_owned() + &request.path(parameters)),
|
||||
)
|
||||
.bearer_auth(&self.jwt_token)
|
||||
.json(&request)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| anyhow!(e))?
|
||||
.json::<R::Response>()
|
||||
.await
|
||||
.map_err(|e| anyhow!(e))
|
||||
}
|
||||
|
||||
pub async fn set_host(&mut self, host: String) {
|
||||
self.host = host;
|
||||
self.base_url = Self::build_base_url(&self.host, self.port, &self.selected_api_version);
|
||||
}
|
||||
|
||||
pub async fn set_port(&mut self, port: u16) {
|
||||
self.port = port;
|
||||
self.base_url = Self::build_base_url(&self.host, self.port, &self.selected_api_version);
|
||||
}
|
||||
|
||||
pub async fn set_api_version(&mut self, version: String) {
|
||||
self.selected_api_version = version;
|
||||
self.base_url = Self::build_base_url(&self.host, self.port, &self.selected_api_version);
|
||||
}
|
||||
|
||||
fn build_base_url(host: &str, port: u16, api_version: &str) -> String {
|
||||
format!("http://{}:{}/{}", host, port, api_version)
|
||||
}
|
||||
}
|
|
@ -25,4 +25,5 @@ ubisync-lib = { path = "../ubisync-lib" }
|
|||
|
||||
|
||||
[dev-dependencies]
|
||||
reqwest = { version = "0.11.20", features = [ "json" ] }
|
||||
reqwest = { version = "0.11.20", features = [ "json" ] }
|
||||
ubisync-sdk = { path = "../ubisync-sdk" }
|
|
@ -1,4 +1,4 @@
|
|||
use axum::Router;
|
||||
use axum::{Router, routing::get, response::{Response, IntoResponse}, http::StatusCode, Json};
|
||||
use tokio::{net::TcpListener, task::JoinHandle};
|
||||
|
||||
use crate::{config::ApiConfig, state::ApiState};
|
||||
|
@ -44,6 +44,8 @@ impl From<ApiConfig> for ApiBuilder {
|
|||
impl ApiBuilder {
|
||||
pub async fn build(&self, state: ApiState) -> Api {
|
||||
let mut app: Router = Router::new();
|
||||
app = app.route("/versions", get(list_available_versions));
|
||||
|
||||
match &self.version {
|
||||
Some(v) if v == "v0" => app = app.nest(&format!("/{}", v), v0::get_router(state)),
|
||||
_ => app = app.nest("/v0", v0::get_router(state)),
|
||||
|
@ -72,3 +74,8 @@ impl ApiBuilder {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async fn list_available_versions() -> Response {
|
||||
(StatusCode::OK, Json {0: vec!["v0"]}).into_response()
|
||||
}
|
|
@ -11,11 +11,11 @@ use axum::{
|
|||
use jsonwebtoken::{decode, Header};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tracing::{debug, error, warn};
|
||||
use ubisync_lib::api::app::{AppRegisterRequest, AppRegisterResponse};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::state::ApiState;
|
||||
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct AppId(Uuid);
|
||||
|
||||
|
@ -30,15 +30,6 @@ struct JWTClaims {
|
|||
sub: AppId,
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct AppDescription {
|
||||
pub name: String,
|
||||
pub desc_text: String,
|
||||
}
|
||||
|
||||
|
||||
pub(super) async fn auth(
|
||||
s: Extension<Arc<ApiState>>,
|
||||
mut request: Request<Body>,
|
||||
|
@ -67,12 +58,12 @@ pub(super) async fn auth(
|
|||
|
||||
pub(super) async fn register(
|
||||
s: Extension<Arc<ApiState>>,
|
||||
Json(data): Json<AppDescription>,
|
||||
Json(body): Json<AppRegisterRequest>,
|
||||
) -> Response {
|
||||
// Maybe ask for consent by user
|
||||
|
||||
// If user wants registration, proceed
|
||||
let result = s.add_app(&data);
|
||||
let result = s.add_app(&body.name, &body.description);
|
||||
|
||||
match result {
|
||||
Ok(id) => {
|
||||
|
@ -83,7 +74,13 @@ pub(super) async fn register(
|
|||
&s.jwt_encoding_key(),
|
||||
);
|
||||
match jwt {
|
||||
Ok(token) => (StatusCode::OK, token).into_response(),
|
||||
Ok(token) => (
|
||||
StatusCode::OK,
|
||||
Json {
|
||||
0: AppRegisterResponse { token: token },
|
||||
},
|
||||
)
|
||||
.into_response(),
|
||||
Err(e) => {
|
||||
warn!("Failed to encode token: {:?}", e);
|
||||
StatusCode::INTERNAL_SERVER_ERROR.into_response()
|
||||
|
|
|
@ -6,17 +6,28 @@ use axum::{
|
|||
response::{IntoResponse, Response},
|
||||
Extension,
|
||||
};
|
||||
use tracing::{debug, warn};
|
||||
use tracing::debug;
|
||||
|
||||
use crate::state::ApiState;
|
||||
use ubisync_lib::types::{ElementContent, ElementId};
|
||||
use ubisync_lib::{
|
||||
api::element::{
|
||||
ElementCreateRequest, ElementCreateResponse, ElementGetResponse, ElementSetRequest,
|
||||
ElementSetResponse, ElementRemoveResponse,
|
||||
},
|
||||
types::ElementId,
|
||||
};
|
||||
|
||||
pub(super) async fn get(Path(id): Path<ElementId>, s: Extension<Arc<ApiState>>) -> Response {
|
||||
let element = s.get_element(&id);
|
||||
match element {
|
||||
Ok(el) => (StatusCode::OK, Json { 0: el }).into_response(),
|
||||
Err(e) => {
|
||||
warn!("Element not found:\n{:?}", e);
|
||||
Ok(el) => (
|
||||
StatusCode::OK,
|
||||
Json {
|
||||
0: ElementGetResponse { element: el },
|
||||
},
|
||||
)
|
||||
.into_response(),
|
||||
Err(_) => {
|
||||
StatusCode::NOT_FOUND.into_response()
|
||||
}
|
||||
}
|
||||
|
@ -24,15 +35,15 @@ pub(super) async fn get(Path(id): Path<ElementId>, s: Extension<Arc<ApiState>>)
|
|||
|
||||
pub(super) async fn create(
|
||||
s: Extension<Arc<ApiState>>,
|
||||
Json(content): Json<ElementContent>,
|
||||
Json(req): Json<ElementCreateRequest>,
|
||||
) -> Response {
|
||||
let element_id = s.create_element(&content);
|
||||
let element_id = s.create_element(&req.content);
|
||||
debug!("{:?}", element_id);
|
||||
match element_id {
|
||||
Ok(id) => (
|
||||
StatusCode::OK,
|
||||
Json {
|
||||
0: &Into::<String>::into(&id),
|
||||
0: ElementCreateResponse { id },
|
||||
},
|
||||
)
|
||||
.into_response(),
|
||||
|
@ -43,11 +54,17 @@ pub(super) async fn create(
|
|||
pub(super) async fn set(
|
||||
Path(id): Path<ElementId>,
|
||||
s: Extension<Arc<ApiState>>,
|
||||
Json(content): Json<ElementContent>,
|
||||
Json(req): Json<ElementSetRequest>,
|
||||
) -> Response {
|
||||
let res = s.write_element_content(&id, &content);
|
||||
let res = s.write_element_content(&id, &req.content);
|
||||
match res {
|
||||
Ok(_) => StatusCode::OK.into_response(),
|
||||
Ok(_) => (
|
||||
StatusCode::OK,
|
||||
Json {
|
||||
0: ElementSetResponse,
|
||||
},
|
||||
)
|
||||
.into_response(),
|
||||
Err(_) => StatusCode::INTERNAL_SERVER_ERROR.into_response(),
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +72,7 @@ pub(super) async fn set(
|
|||
pub(super) async fn remove(Path(id): Path<ElementId>, s: Extension<Arc<ApiState>>) -> Response {
|
||||
let res = s.remove_element(&id);
|
||||
match res {
|
||||
Ok(_) => StatusCode::OK.into_response(),
|
||||
Ok(_) => (StatusCode::OK, Json { 0: ElementRemoveResponse }).into_response(),
|
||||
Err(_) => StatusCode::INTERNAL_SERVER_ERROR.into_response(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use jsonwebtoken::{DecodingKey, EncodingKey, Validation};
|
|||
use tracing::debug;
|
||||
use ubisync_lib::{types::{ElementContent, ElementId, Element}, messages::MessageContent};
|
||||
|
||||
use crate::{api::v0::app::{AppDescription, AppId}, state::queries};
|
||||
use crate::{api::v0::app::AppId, state::queries};
|
||||
|
||||
use super::State;
|
||||
|
||||
|
@ -29,15 +29,15 @@ impl ApiState {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn add_app(&self, description: &AppDescription) -> anyhow::Result<AppId> {
|
||||
pub fn add_app(&self, name: &str, description: &str) -> anyhow::Result<AppId> {
|
||||
let id = AppId::new();
|
||||
let last_access = Utc::now();
|
||||
queries::apps::add(
|
||||
self.db(),
|
||||
&id,
|
||||
&last_access,
|
||||
&description.name,
|
||||
&description.desc_text,
|
||||
name,
|
||||
description,
|
||||
)?;
|
||||
debug!("Successfully added app");
|
||||
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
use std::time::Duration;
|
||||
|
||||
use tracing::{debug, Level};
|
||||
use ubisync::{config::Config, Ubisync, api::v0::app::AppDescription};
|
||||
use ubisync_lib::types::{ElementContent, ElementId, Element};
|
||||
|
||||
use tracing::{debug, warn, Level};
|
||||
use ubisync::{config::Config, Ubisync};
|
||||
use ubisync_lib::{
|
||||
api::element::{ElementCreateRequest, ElementGetRequest},
|
||||
types::{Element, ElementContent},
|
||||
};
|
||||
use ubisync_sdk::UbisyncClient;
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn two_nodes_element_creation() {
|
||||
|
@ -11,6 +14,7 @@ async fn two_nodes_element_creation() {
|
|||
.pretty()
|
||||
.with_max_level(Level::DEBUG)
|
||||
.init();
|
||||
|
||||
// Two nodes need to bind to different ports
|
||||
let mut c2 = Config::default();
|
||||
c2.api_config.port = Some(9982);
|
||||
|
@ -19,63 +23,35 @@ async fn two_nodes_element_creation() {
|
|||
ubi1.add_peer_from_id(ubi2.get_destination().unwrap().into())
|
||||
.unwrap();
|
||||
|
||||
let http_client = reqwest::Client::new();
|
||||
let register_response = http_client
|
||||
.put("http://localhost:9981/v0/app/register")
|
||||
.json(&AppDescription {
|
||||
name: "Test".to_string(),
|
||||
desc_text: "desc".to_string(),
|
||||
})
|
||||
.send()
|
||||
let api_client1 = UbisyncClient::init("localhost", 9981, None, "App", "Long desc")
|
||||
.await
|
||||
.unwrap();
|
||||
let jwt1 = register_response
|
||||
.text()
|
||||
.await
|
||||
.expect("Couldn't fetch token from response");
|
||||
let register_response = http_client
|
||||
.put("http://localhost:9982/v0/app/register")
|
||||
.json(&AppDescription {
|
||||
name: "Test".to_string(),
|
||||
desc_text: "desc".to_string(),
|
||||
})
|
||||
.send()
|
||||
let api_client2 = UbisyncClient::init("localhost", 9982, None, "App", "Long desc")
|
||||
.await
|
||||
.unwrap();
|
||||
let jwt2 = register_response
|
||||
.text()
|
||||
.await
|
||||
.expect("Couldn't fetch token from response");
|
||||
|
||||
let test_element_content = ElementContent::Text("Text".to_string());
|
||||
let put_resp = http_client
|
||||
.put(&format!("http://localhost:9981/v0/element"))
|
||||
.json(&test_element_content)
|
||||
.header("Authorization", &format!("Bearer {}", &jwt1))
|
||||
.send()
|
||||
let create_resp = api_client1
|
||||
.send(
|
||||
ElementCreateRequest {
|
||||
content: test_element_content.clone(),
|
||||
},
|
||||
(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
debug!("{:?}", &put_resp);
|
||||
let put_resp_text = put_resp.text().await.expect("No put response body");
|
||||
debug!("{}", put_resp_text);
|
||||
let id =
|
||||
serde_json::from_str::<ElementId>(&put_resp_text).expect("Could not deserialize ElementId");
|
||||
let id = create_resp.id;
|
||||
|
||||
tokio::time::sleep(Duration::from_millis(3000)).await;
|
||||
tokio::time::sleep(Duration::from_millis(1000)).await;
|
||||
|
||||
let get_resp = http_client
|
||||
.get(&format!(
|
||||
"http://localhost:9982/v0/element/{}",
|
||||
Into::<String>::into(&id)
|
||||
))
|
||||
.header("Authorization", &format!("Bearer {}", &jwt2))
|
||||
.send()
|
||||
.await
|
||||
.expect("Get request failed");
|
||||
let get_resp_text = get_resp.text().await.expect("No get request body");
|
||||
debug!("{}", get_resp_text);
|
||||
let received_element =
|
||||
serde_json::from_str::<Element>(&get_resp_text).expect("Could not deserialize Element");
|
||||
let mut get_resp = api_client2.send(ElementGetRequest {}, id.clone()).await;
|
||||
while let Err(_) = get_resp {
|
||||
warn!("Sleeping for another second, element has not arrived yet");
|
||||
tokio::time::sleep(Duration::from_millis(1000)).await;
|
||||
get_resp = api_client2.send(ElementGetRequest {}, id.clone()).await;
|
||||
}
|
||||
|
||||
let received_element: Element = get_resp.unwrap().element;
|
||||
debug!("Other node received this element: {:?}", received_element);
|
||||
|
||||
assert_eq!(&test_element_content, received_element.content());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue