populated build-info endpoint
This commit is contained in:
@@ -171,6 +171,7 @@ tokio-tungstenite = "0.20.1"
|
||||
tracing = "0.1.37"
|
||||
tungstenite = { version = "0.20.1", default-features = false }
|
||||
ts-rs = "7.0.0"
|
||||
utoipa = "3.5.0"
|
||||
url = "2.4"
|
||||
zeroize = "1.6.0"
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ opentelemetry-jaeger = { version = "0.18.0", optional = true, features = [
|
||||
"isahc_collector_client",
|
||||
] }
|
||||
tracing-opentelemetry = { version = "0.19.0", optional = true }
|
||||
utoipa = { workspace = true, optional = true }
|
||||
opentelemetry = { version = "0.19.0", optional = true, features = ["rt-tokio"] }
|
||||
|
||||
|
||||
@@ -42,6 +43,7 @@ vergen = { version = "=7.4.3", default-features = false, features = [
|
||||
|
||||
[features]
|
||||
default = []
|
||||
openapi = ["utoipa"]
|
||||
output_format = ["serde_json"]
|
||||
tracing = [
|
||||
"tracing-subscriber",
|
||||
|
||||
@@ -81,6 +81,7 @@ impl BinaryBuildInformation {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
|
||||
pub struct BinaryBuildInformationOwned {
|
||||
/// Provides the name of the binary, i.e. the content of `CARGO_PKG_NAME` environmental variable.
|
||||
pub binary_name: String,
|
||||
|
||||
+6
-2
@@ -15,16 +15,20 @@ anyhow = { workspace = true }
|
||||
bytes = "1.5.0"
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_yaml = "0.9.25"
|
||||
serde_json = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
||||
# HTTP API:
|
||||
axum = { workspace = true }
|
||||
|
||||
# useful for `#[axum_macros::debug_handler]`
|
||||
#axum-macros = "0.3.8"
|
||||
mime = "0.3.17"
|
||||
hyper = { workspace = true }
|
||||
tower = { version = "0.4.13" }
|
||||
tower-http = { version = "0.4.4", features = ["fs"] }
|
||||
utoipa = { version = "3.5.0", features = ["axum_extras"] }
|
||||
utoipa = { workspace = true, features = ["axum_extras"] }
|
||||
utoipa-swagger-ui = { version = "3.1.5", features = ["axum"] }
|
||||
|
||||
# if we ever wanted redoc/rapidoc bridges:
|
||||
@@ -32,4 +36,4 @@ utoipa-swagger-ui = { version = "3.1.5", features = ["axum"] }
|
||||
#utoipa-rapidoc = { version = "0.1.0", features = ["axum"] }
|
||||
|
||||
|
||||
nym-bin-common = { path = "../common/bin-common" }
|
||||
nym-bin-common = { path = "../common/bin-common", features = ["openapi"] }
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::http::state::AppState;
|
||||
use axum::http::{header, HeaderValue, StatusCode};
|
||||
use axum::response::{IntoResponse, Response};
|
||||
use axum::{Json, Router};
|
||||
use bytes::{BufMut, BytesMut};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use utoipa::{IntoParams, ToSchema};
|
||||
|
||||
pub mod v1;
|
||||
|
||||
@@ -19,13 +21,31 @@ pub struct Config {
|
||||
pub v1_config: v1::Config,
|
||||
}
|
||||
|
||||
pub(super) fn routes(config: Config) -> Router {
|
||||
Router::new().nest_service(routes::V1, v1::routes(config.v1_config))
|
||||
pub(super) fn routes(config: Config) -> Router<AppState> {
|
||||
Router::new().nest(routes::V1, v1::routes(config.v1_config))
|
||||
// .nest(routes::SWAGGER, openapi::route())
|
||||
// .nest(routes::SWAGGER, openapi::route())
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Serialize, Deserialize, Copy, Clone)]
|
||||
#[derive(Debug, Clone, ToSchema)]
|
||||
pub enum FormattedResponse<T> {
|
||||
Json(Json<T>),
|
||||
Yaml(Yaml<T>),
|
||||
}
|
||||
|
||||
impl<T> IntoResponse for FormattedResponse<T>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
fn into_response(self) -> Response {
|
||||
match self {
|
||||
FormattedResponse::Json(json_response) => json_response.into_response(),
|
||||
FormattedResponse::Yaml(yaml_response) => yaml_response.into_response(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Serialize, Deserialize, Copy, Clone, ToSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum Output {
|
||||
#[default]
|
||||
@@ -33,11 +53,17 @@ pub enum Output {
|
||||
Yaml,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Serialize, Deserialize, Copy, Clone, IntoParams, ToSchema)]
|
||||
#[serde(default)]
|
||||
pub struct OutputParams {
|
||||
pub output: Option<Output>,
|
||||
}
|
||||
|
||||
impl Output {
|
||||
pub fn to_response<T: Serialize + 'static>(self, data: T) -> Box<dyn IntoResponse> {
|
||||
pub fn to_response<T: Serialize>(self, data: T) -> FormattedResponse<T> {
|
||||
match self {
|
||||
Output::Json => Box::new(Json(data)),
|
||||
Output::Yaml => Box::new(Yaml(data)),
|
||||
Output::Json => FormattedResponse::Json(Json(data)),
|
||||
Output::Yaml => FormattedResponse::Yaml(Yaml(data)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,33 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::http::router::api::Output;
|
||||
use axum::extract::Query;
|
||||
use crate::http::router::api::{FormattedResponse, OutputParams};
|
||||
use crate::http::state::AppState;
|
||||
use axum::extract::{Query, State};
|
||||
use axum::response::IntoResponse;
|
||||
use nym_bin_common::build_information::BinaryBuildInformationOwned;
|
||||
|
||||
/// Description of the path
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/",
|
||||
path = "/build-info",
|
||||
context_path = "/api/v1",
|
||||
responses(
|
||||
(status=200, description ="", body = ())
|
||||
(status=200, content(
|
||||
("application/json" = BinaryBuildInformationOwned),
|
||||
("application/yaml" = BinaryBuildInformationOwned)
|
||||
))
|
||||
),
|
||||
params(
|
||||
("output" = Option<Output>, Query, description = "")
|
||||
)
|
||||
params(OutputParams)
|
||||
)]
|
||||
pub async fn build_info(Query(output): Query<Option<Output>>) -> impl IntoResponse {
|
||||
let output = output.unwrap_or_default();
|
||||
|
||||
todo!()
|
||||
pub async fn build_info(
|
||||
State(state): State<AppState>,
|
||||
Query(output): Query<OutputParams>,
|
||||
) -> FormattedResponse<BinaryBuildInformationOwned> {
|
||||
let output = output.output.unwrap_or_default();
|
||||
// todo!()
|
||||
// TODO: get rid of the clone since it's getting serialized anyway
|
||||
output.to_response(state.build_information.clone())
|
||||
}
|
||||
|
||||
pub struct BuildInfoResponse(BinaryBuildInformationOwned);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::http::state::AppState;
|
||||
use axum::http::StatusCode;
|
||||
use axum::routing::get;
|
||||
use axum::Router;
|
||||
@@ -8,6 +9,6 @@ use axum::Router;
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct Config {}
|
||||
|
||||
pub(crate) fn routes(_config: Config) -> Router {
|
||||
pub(crate) fn routes(_config: Config) -> Router<AppState> {
|
||||
Router::new().route("/", get(|| async { StatusCode::NOT_IMPLEMENTED }))
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::http::state::AppState;
|
||||
use axum::http::StatusCode;
|
||||
use axum::routing::get;
|
||||
use axum::Router;
|
||||
@@ -8,6 +9,6 @@ use axum::Router;
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct Config {}
|
||||
|
||||
pub(crate) fn routes(_config: Config) -> Router {
|
||||
pub(crate) fn routes(_config: Config) -> Router<AppState> {
|
||||
Router::new().route("/", get(|| async { StatusCode::NOT_IMPLEMENTED }))
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
use crate::http::router::api::v1::build_info::build_info;
|
||||
use crate::http::router::api::v1::roles::roles;
|
||||
use crate::http::state::AppState;
|
||||
use axum::routing::get;
|
||||
use axum::Router;
|
||||
use nym_bin_common::build_information::BinaryBuildInformationOwned;
|
||||
@@ -30,7 +31,7 @@ pub struct Config {
|
||||
pub network_requester: network_requester::Config,
|
||||
}
|
||||
|
||||
pub(super) fn routes(config: Config) -> Router {
|
||||
pub(super) fn routes(config: Config) -> Router<AppState> {
|
||||
Router::new()
|
||||
.nest(routes::GATEWAY, gateway::routes(config.gateway))
|
||||
.nest(routes::MIXNODE, mixnode::routes(config.mixnide))
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::http::state::AppState;
|
||||
use axum::http::StatusCode;
|
||||
use axum::routing::get;
|
||||
use axum::Router;
|
||||
@@ -8,6 +9,6 @@ use axum::Router;
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct Config {}
|
||||
|
||||
pub(crate) fn routes(_config: Config) -> Router {
|
||||
pub(crate) fn routes(_config: Config) -> Router<AppState> {
|
||||
Router::new().route("/", get(|| async { StatusCode::NOT_IMPLEMENTED }))
|
||||
}
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::http::router::api;
|
||||
use crate::http::state::AppState;
|
||||
use axum::Router;
|
||||
use nym_bin_common::build_information::BinaryBuildInformationOwned;
|
||||
use utoipa::OpenApi;
|
||||
use utoipa_swagger_ui::SwaggerUi;
|
||||
|
||||
#[derive(OpenApi)]
|
||||
#[openapi(info(title = "NymNode API"))]
|
||||
#[openapi(
|
||||
info(title = "NymNode API"),
|
||||
paths(api::v1::build_info::build_info,),
|
||||
components(schemas(api::Output, api::OutputParams, BinaryBuildInformationOwned))
|
||||
)]
|
||||
pub(crate) struct ApiDoc;
|
||||
|
||||
pub(crate) fn route() -> Router {
|
||||
pub(crate) fn route() -> Router<AppState> {
|
||||
// provide absolute path to the openapi.json
|
||||
let config = utoipa_swagger_ui::Config::from("/api/v1/api-docs/openapi.json");
|
||||
SwaggerUi::new("/swagger")
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::http::state::AppState;
|
||||
use axum::routing::get;
|
||||
use axum::Router;
|
||||
use std::path::PathBuf;
|
||||
@@ -11,7 +12,7 @@ pub struct Config {
|
||||
pub assets_path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
pub(super) fn routes(config: Config) -> Router {
|
||||
pub(super) fn routes(config: Config) -> Router<AppState> {
|
||||
if let Some(assets) = config.assets_path {
|
||||
Router::new().nest_service("/", ServeDir::new(assets))
|
||||
} else {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
use crate::error::NymNodeError;
|
||||
use crate::http::middleware::logging;
|
||||
use crate::http::state::AppState;
|
||||
use axum::routing::IntoMakeService;
|
||||
use axum::Router;
|
||||
use hyper::server::conn::AddrIncoming;
|
||||
@@ -47,7 +48,8 @@ impl NymNodeRouter {
|
||||
.nest(routes::LANDING_PAGE, landing_page::routes(config.landing))
|
||||
.nest(routes::POLICY, policy::routes(config.policy))
|
||||
.nest(routes::API, api::routes(config.api))
|
||||
.layer(axum::middleware::from_fn(logging::logger)),
|
||||
.layer(axum::middleware::from_fn(logging::logger))
|
||||
.with_state(AppState::new_dummy()),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::http::state::AppState;
|
||||
use axum::routing::get;
|
||||
use axum::Router;
|
||||
use std::path::PathBuf;
|
||||
@@ -11,7 +12,7 @@ pub struct Config {
|
||||
pub assets_path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
pub(super) fn routes(config: Config) -> Router {
|
||||
pub(super) fn routes(config: Config) -> Router<AppState> {
|
||||
if let Some(assets) = config.assets_path {
|
||||
Router::new().nest_service("/", ServeDir::new(assets))
|
||||
} else {
|
||||
|
||||
@@ -1,16 +1,36 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_bin_common::bin_info_owned;
|
||||
use nym_bin_common::build_information::BinaryBuildInformationOwned;
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct AppState {
|
||||
pub struct AppState {
|
||||
inner: Arc<AppStateInner>,
|
||||
}
|
||||
|
||||
impl AppState {
|
||||
pub fn new_dummy() -> Self {
|
||||
AppState {
|
||||
inner: Arc::new(AppStateInner {
|
||||
build_information: bin_info_owned!(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for AppState {
|
||||
type Target = AppStateInner;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AppStateInner {
|
||||
pub struct AppStateInner {
|
||||
// TODO: split it based on routes?
|
||||
pub(crate) build_information: BinaryBuildInformationOwned,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user