Network Explorer API improvements:
- upgrade `okapi` for swagger generation across multiple resources - switched `GET mix-node` to `GET mix-nodes` - added error message when no geolocation env var is set and process continues
This commit is contained in:
committed by
Bogdan-Ștefan Neacșu
parent
8f6daf1e03
commit
8bc23434ab
Generated
+9
-6
@@ -3972,10 +3972,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "okapi"
|
||||
version = "0.6.0-alpha-1"
|
||||
version = "0.7.0-rc.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb085e00daf8d75b9dbf0ffdb4738e69503e28898d9641fa8bdc6ad536c7bcf4"
|
||||
checksum = "ce66b6366e049880a35c378123fddb630b1a1a3c37fa1ca70caaf4a09f6e2893"
|
||||
dependencies = [
|
||||
"log",
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -5212,10 +5213,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rocket_okapi"
|
||||
version = "0.7.0-alpha-1"
|
||||
version = "0.8.0-rc.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b2f4f48fb070f9f6c56d5663df5fa8a514406207744f4abd84661bfb24efd7d"
|
||||
checksum = "0025aa04994af8cd8e1fcdd5a73579a395c941ae090ecb0a39b41cca7e237a20"
|
||||
dependencies = [
|
||||
"either",
|
||||
"log",
|
||||
"okapi",
|
||||
"rocket",
|
||||
"rocket_okapi_codegen",
|
||||
@@ -5226,9 +5229,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rocket_okapi_codegen"
|
||||
version = "0.7.0-alpha-1"
|
||||
version = "0.8.0-rc.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88ccf1550e1c806461a6b08e2ab64eb10701d41bf50bde59ab9aa3a57ab14d41"
|
||||
checksum = "dc114779fc27afb78179233e966f469e47fd7a98dc15181cff2574cdddb65612"
|
||||
dependencies = [
|
||||
"darling 0.13.0",
|
||||
"proc-macro2",
|
||||
|
||||
@@ -16,8 +16,8 @@ serde_json = "1.0.66"
|
||||
tokio = {version = "1.9.0", features = ["full"] }
|
||||
chrono = { version = "0.4.19", features = ["serde"] }
|
||||
schemars = { version = "0.8", features = ["preserve_order"] }
|
||||
okapi = { version = "0.6.0-alpha-1", features = ["derive_json_schema"] }
|
||||
rocket_okapi = "0.7.0-alpha-1"
|
||||
okapi = { version = "0.7.0-rc.1", features = ["impl_json_schema"] }
|
||||
rocket_okapi = { version = "0.8.0-rc.1", features = ["swagger"] }
|
||||
log = "0.4.0"
|
||||
pretty_env_logger = "0.4.0"
|
||||
thiserror = "1.0.29"
|
||||
|
||||
@@ -15,6 +15,13 @@ impl GeoLocateTask {
|
||||
}
|
||||
|
||||
pub(crate) fn start(mut self) {
|
||||
if ::std::env::var("GEO_IP_SERVICE_API_KEY").is_err() {
|
||||
error!(
|
||||
"Env var GEO_IP_SERVICE_API_KEY is not set. Geolocation tasks will not be started."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
info!("Spawning mix node locator task runner...");
|
||||
tokio::spawn(async move {
|
||||
let mut interval_timer = tokio::time::interval(std::time::Duration::from_millis(50));
|
||||
|
||||
@@ -2,9 +2,12 @@ use crate::country_statistics::country_nodes_distribution::CountryNodesDistribut
|
||||
use crate::state::ExplorerApiStateContext;
|
||||
use rocket::serde::json::Json;
|
||||
use rocket::{Route, State};
|
||||
use rocket_okapi::okapi::openapi3::OpenApi;
|
||||
use rocket_okapi::openapi_get_routes_spec;
|
||||
use rocket_okapi::settings::OpenApiSettings;
|
||||
|
||||
pub fn country_statistics_make_default_routes() -> Vec<Route> {
|
||||
routes_with_openapi![index]
|
||||
pub fn country_statistics_make_default_routes(settings: &OpenApiSettings) -> (Vec<Route>, OpenApi) {
|
||||
openapi_get_routes_spec![settings: index]
|
||||
}
|
||||
|
||||
// We could either separate stuff by structure (like this, http is separate), or we could just
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
use log::info;
|
||||
use rocket::http::Method;
|
||||
use rocket::Request;
|
||||
use rocket::{Build, Request, Rocket};
|
||||
use rocket_cors::{AllowedHeaders, AllowedOrigins};
|
||||
use rocket_okapi::swagger_ui::make_swagger_ui;
|
||||
|
||||
use crate::country_statistics::http::country_statistics_make_default_routes;
|
||||
use crate::http::swagger::get_docs;
|
||||
use crate::mix_node::http::mix_node_make_default_routes;
|
||||
use crate::mix_nodes::http::mix_nodes_make_default_routes;
|
||||
use crate::ping::http::ping_make_default_routes;
|
||||
use crate::state::ExplorerApiStateContext;
|
||||
|
||||
@@ -15,35 +16,45 @@ mod swagger;
|
||||
pub(crate) fn start(state: ExplorerApiStateContext) {
|
||||
tokio::spawn(async move {
|
||||
info!("Starting up...");
|
||||
|
||||
let allowed_origins = AllowedOrigins::all();
|
||||
|
||||
// You can also deserialize this
|
||||
let cors = rocket_cors::CorsOptions {
|
||||
allowed_origins,
|
||||
allowed_methods: vec![Method::Get].into_iter().map(From::from).collect(),
|
||||
allowed_headers: AllowedHeaders::some(&["*"]),
|
||||
allow_credentials: true,
|
||||
..Default::default()
|
||||
}
|
||||
.to_cors()
|
||||
.unwrap();
|
||||
|
||||
let config = rocket::config::Config::release_default();
|
||||
rocket::build()
|
||||
.configure(config)
|
||||
.mount("/countries", country_statistics_make_default_routes())
|
||||
.mount("/ping", ping_make_default_routes())
|
||||
.mount("/mix-node", mix_node_make_default_routes())
|
||||
.mount("/swagger", make_swagger_ui(&get_docs()))
|
||||
.register("/", catchers![not_found])
|
||||
.manage(state)
|
||||
.attach(cors)
|
||||
.launch()
|
||||
.await
|
||||
configure_rocket(state).launch().await
|
||||
});
|
||||
}
|
||||
|
||||
fn configure_rocket(state: ExplorerApiStateContext) -> Rocket<Build> {
|
||||
let allowed_origins = AllowedOrigins::all();
|
||||
|
||||
// You can also deserialize this
|
||||
let cors = rocket_cors::CorsOptions {
|
||||
allowed_origins,
|
||||
allowed_methods: vec![Method::Get].into_iter().map(From::from).collect(),
|
||||
allowed_headers: AllowedHeaders::some(&["*"]),
|
||||
allow_credentials: true,
|
||||
..Default::default()
|
||||
}
|
||||
.to_cors()
|
||||
.unwrap();
|
||||
|
||||
let openapi_settings = rocket_okapi::settings::OpenApiSettings::default();
|
||||
let config = rocket::config::Config::release_default();
|
||||
let mut building_rocket = rocket::build().configure(config);
|
||||
|
||||
mount_endpoints_and_merged_docs! {
|
||||
building_rocket,
|
||||
"/v1".to_owned(),
|
||||
openapi_settings,
|
||||
"/ping" => ping_make_default_routes(&openapi_settings),
|
||||
"/countries" => country_statistics_make_default_routes(&openapi_settings),
|
||||
"/mix-node" => mix_node_make_default_routes(&openapi_settings),
|
||||
"/mix-nodes" => mix_nodes_make_default_routes(&openapi_settings),
|
||||
};
|
||||
|
||||
building_rocket
|
||||
.mount("/swagger", make_swagger_ui(&get_docs()))
|
||||
.register("/", catchers![not_found])
|
||||
.manage(state)
|
||||
.attach(cors)
|
||||
}
|
||||
|
||||
#[catch(404)]
|
||||
pub(crate) fn not_found(req: &Request) -> String {
|
||||
format!("I couldn't find '{}'. Try something else?", req.uri())
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
use rocket_okapi::swagger_ui::{SwaggerUIConfig, UrlObject};
|
||||
use rocket_okapi::swagger_ui::SwaggerUIConfig;
|
||||
|
||||
pub(crate) fn get_docs() -> SwaggerUIConfig {
|
||||
SwaggerUIConfig {
|
||||
urls: vec![
|
||||
UrlObject::new("Country statistics", "/countries/openapi.json"),
|
||||
UrlObject::new("Node ping", "/ping/openapi.json"),
|
||||
UrlObject::new("Mix node", "/mix-node/openapi.json"),
|
||||
],
|
||||
url: "../v1/openapi.json".to_owned(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,11 @@ impl ExplorerApi {
|
||||
async fn run(&mut self) {
|
||||
info!("Explorer API starting up...");
|
||||
|
||||
info!(
|
||||
"Using validator API - {}",
|
||||
network_defaults::default_api_endpoints()[0].clone()
|
||||
);
|
||||
|
||||
// spawn concurrent tasks
|
||||
mix_nodes::tasks::MixNodesTasks::new(self.state.clone()).start();
|
||||
country_statistics::distribution::CountryStatisticsDistributionTask::new(
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
use reqwest::Error as ReqwestError;
|
||||
use rocket::serde::json::Json;
|
||||
use rocket::{Route, State};
|
||||
use rocket_okapi::okapi::openapi3::OpenApi;
|
||||
use rocket_okapi::openapi_get_routes_spec;
|
||||
use rocket_okapi::settings::OpenApiSettings;
|
||||
use serde::Serialize;
|
||||
|
||||
use mixnet_contract::{Addr, Coin, Delegation, Layer, MixNode};
|
||||
@@ -9,13 +12,12 @@ use crate::mix_node::models::{NodeDescription, NodeStats};
|
||||
use crate::mix_nodes::{get_mixnode_delegations, get_single_mixnode_delegations, Location};
|
||||
use crate::state::ExplorerApiStateContext;
|
||||
|
||||
pub fn mix_node_make_default_routes() -> Vec<Route> {
|
||||
routes_with_openapi![
|
||||
get_delegations,
|
||||
pub fn mix_node_make_default_routes(settings: &OpenApiSettings) -> (Vec<Route>, OpenApi) {
|
||||
openapi_get_routes_spec![
|
||||
settings: get_delegations,
|
||||
get_all_delegations,
|
||||
get_description,
|
||||
get_stats,
|
||||
list
|
||||
]
|
||||
}
|
||||
|
||||
@@ -29,14 +31,6 @@ pub(crate) struct PrettyMixNodeBondWithLocation {
|
||||
pub mix_node: MixNode,
|
||||
}
|
||||
|
||||
#[openapi(tag = "mix_node")]
|
||||
#[get("/")]
|
||||
pub(crate) async fn list(
|
||||
state: &State<ExplorerApiStateContext>,
|
||||
) -> Json<Vec<PrettyMixNodeBondWithLocation>> {
|
||||
Json(state.inner.mix_nodes.get_mixnodes_with_location().await)
|
||||
}
|
||||
|
||||
#[openapi(tag = "mix_node")]
|
||||
#[get("/<pubkey>/delegations")]
|
||||
pub(crate) async fn get_delegations(pubkey: &str) -> Json<Vec<Delegation>> {
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
use rocket::serde::json::Json;
|
||||
use rocket::{Route, State};
|
||||
use rocket_okapi::okapi::openapi3::OpenApi;
|
||||
use rocket_okapi::openapi_get_routes_spec;
|
||||
use rocket_okapi::settings::OpenApiSettings;
|
||||
|
||||
use crate::mix_node::http::PrettyMixNodeBondWithLocation;
|
||||
use crate::state::ExplorerApiStateContext;
|
||||
|
||||
pub fn mix_nodes_make_default_routes(settings: &OpenApiSettings) -> (Vec<Route>, OpenApi) {
|
||||
openapi_get_routes_spec![settings: list]
|
||||
}
|
||||
|
||||
#[openapi(tag = "mix_nodes")]
|
||||
#[get("/")]
|
||||
pub(crate) async fn list(
|
||||
state: &State<ExplorerApiStateContext>,
|
||||
) -> Json<Vec<PrettyMixNodeBondWithLocation>> {
|
||||
Json(state.inner.mix_nodes.get_mixnodes_with_location().await)
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
pub(crate) mod http;
|
||||
pub(crate) mod tasks;
|
||||
mod utils;
|
||||
|
||||
|
||||
@@ -4,6 +4,9 @@ use std::time::Duration;
|
||||
|
||||
use rocket::serde::json::Json;
|
||||
use rocket::{Route, State};
|
||||
use rocket_okapi::okapi::openapi3::OpenApi;
|
||||
use rocket_okapi::openapi_get_routes_spec;
|
||||
use rocket_okapi::settings::OpenApiSettings;
|
||||
|
||||
use mixnet_contract::MixNodeBond;
|
||||
|
||||
@@ -12,8 +15,8 @@ use crate::state::ExplorerApiStateContext;
|
||||
|
||||
const CONNECTION_TIMEOUT_SECONDS: Duration = Duration::from_secs(10);
|
||||
|
||||
pub fn ping_make_default_routes() -> Vec<Route> {
|
||||
routes_with_openapi![index]
|
||||
pub fn ping_make_default_routes(settings: &OpenApiSettings) -> (Vec<Route>, OpenApi) {
|
||||
openapi_get_routes_spec![settings: index]
|
||||
}
|
||||
|
||||
#[openapi(tag = "ping")]
|
||||
|
||||
Reference in New Issue
Block a user