aboutsummaryrefslogtreecommitdiffstats
path: root/crates/configuration/src/server
diff options
context:
space:
mode:
Diffstat (limited to 'crates/configuration/src/server')
-rw-r--r--crates/configuration/src/server/error.rs26
-rw-r--r--crates/configuration/src/server/http_svc.rs63
-rw-r--r--crates/configuration/src/server/http_svc/routes.rs11
-rw-r--r--crates/configuration/src/server/http_svc/routes/routing.rs4
-rw-r--r--crates/configuration/src/server/http_svc/routes/routing/get_active.rs30
-rw-r--r--crates/configuration/src/server/interceptor.rs23
-rw-r--r--crates/configuration/src/server/version.rs35
7 files changed, 192 insertions, 0 deletions
diff --git a/crates/configuration/src/server/error.rs b/crates/configuration/src/server/error.rs
new file mode 100644
index 0000000..730f99a
--- /dev/null
+++ b/crates/configuration/src/server/error.rs
@@ -0,0 +1,26 @@
+use axum::{
+ http::StatusCode,
+ response::{IntoResponse, Response},
+};
+
+#[derive(Debug)]
+pub struct AppError(anyhow::Error);
+
+impl IntoResponse for AppError {
+ fn into_response(self) -> Response {
+ (
+ StatusCode::INTERNAL_SERVER_ERROR,
+ format!("Something went wrong: {}", self.0),
+ )
+ .into_response()
+ }
+}
+
+impl<E> From<E> for AppError
+where
+ E: Into<anyhow::Error>,
+{
+ fn from(err: E) -> Self {
+ Self(err.into())
+ }
+}
diff --git a/crates/configuration/src/server/http_svc.rs b/crates/configuration/src/server/http_svc.rs
new file mode 100644
index 0000000..7b2a258
--- /dev/null
+++ b/crates/configuration/src/server/http_svc.rs
@@ -0,0 +1,63 @@
+mod routes;
+
+use axum::{Router, response::IntoResponse};
+use utoipa::OpenApi;
+use utoipa_axum::router::OpenApiRouter;
+#[cfg(feature = "redoc")]
+use utoipa_redoc::Servable;
+#[cfg(feature = "scalar")]
+use utoipa_scalar::Servable as _;
+
+use crate::{server::http_svc, state::AppHandle};
+
+const TAG_ROUTING: &str = "Routing";
+
+#[derive(OpenApi)]
+#[openapi(
+ tags(
+ (name = TAG_ROUTING, description = "Operations related to routing configuration"),
+ )
+)]
+pub struct ApiDoc;
+
+/// Get health of the API.
+#[utoipa::path(
+ method(get),
+ path = "/",
+ responses(
+ (status = OK, description = "Success", body = str, content_type = "text/plain")
+ )
+)]
+pub async fn health_check() -> impl IntoResponse {
+ let name = env!("CARGO_PKG_NAME");
+ let ver = env!("CARGO_PKG_VERSION");
+
+ format!("{name} v{ver} is live")
+}
+
+pub fn build_router(state: AppHandle) -> Router {
+ let (router, _api) = OpenApiRouter::with_openapi(ApiDoc::openapi())
+ .routes(utoipa_axum::routes!(health_check))
+ .nest("/api", routes::router(state))
+ .split_for_parts();
+
+ #[cfg(feature = "swagger")]
+ let router = router.merge(
+ utoipa_swagger_ui::SwaggerUi::new("/swagger-ui")
+ .url("/api-docs/swaggerdoc.json", _api.clone()),
+ );
+
+ #[cfg(feature = "redoc")]
+ let router = router.merge(utoipa_redoc::Redoc::with_url("/redoc", _api.clone()));
+
+ #[cfg(feature = "rapidoc")]
+ let router = router.merge(
+ utoipa_rapidoc::RapiDoc::with_openapi("/api-docs/rapidoc.json", _api.clone())
+ .path("/rapidoc"),
+ );
+
+ #[cfg(feature = "scalar")]
+ let router = router.merge(utoipa_scalar::Scalar::with_url("/scalar", _api));
+
+ warden_middleware::apply(router)
+}
diff --git a/crates/configuration/src/server/http_svc/routes.rs b/crates/configuration/src/server/http_svc/routes.rs
new file mode 100644
index 0000000..cc065e8
--- /dev/null
+++ b/crates/configuration/src/server/http_svc/routes.rs
@@ -0,0 +1,11 @@
+mod routing;
+
+use utoipa_axum::{router::OpenApiRouter, routes};
+
+use crate::state::AppHandle;
+
+pub fn router(store: AppHandle) -> OpenApiRouter {
+ OpenApiRouter::new()
+ .routes(routes!(routing::get_active))
+ .with_state(store)
+}
diff --git a/crates/configuration/src/server/http_svc/routes/routing.rs b/crates/configuration/src/server/http_svc/routes/routing.rs
new file mode 100644
index 0000000..7c8affe
--- /dev/null
+++ b/crates/configuration/src/server/http_svc/routes/routing.rs
@@ -0,0 +1,4 @@
+//pub mod delete_routing;
+pub mod get_active;
+//pub mod post_routing;
+//pub mod replace_routing;
diff --git a/crates/configuration/src/server/http_svc/routes/routing/get_active.rs b/crates/configuration/src/server/http_svc/routes/routing/get_active.rs
new file mode 100644
index 0000000..562a1f1
--- /dev/null
+++ b/crates/configuration/src/server/http_svc/routes/routing/get_active.rs
@@ -0,0 +1,30 @@
+use axum::{extract::State, response::IntoResponse};
+use warden_core::configuration::routing::RoutingConfiguration;
+
+use crate::{
+ server::{error::AppError, http_svc::TAG_ROUTING, version::Version},
+ state::AppHandle,
+};
+
+#[utoipa::path(
+ get,
+ responses((
+ status = OK,
+ body = RoutingConfiguration
+ )),
+ operation_id = "get_active_routing", // https://github.com/juhaku/utoipa/issues/1170
+ path = "/{version}/routing",
+ params(
+ ("version" = Version, Path, description = "API version, e.g., v1, v2, v3")
+ ),
+ tag = TAG_ROUTING,
+ )
+]
+#[axum::debug_handler]
+#[tracing::instrument(skip(state), err(Debug), fields(method = "GET"))]
+pub(super) async fn active_routing(
+ version: Version,
+ State(state): State<AppHandle>,
+) -> Result<impl IntoResponse, AppError> {
+ Ok(String::default().into_response())
+}
diff --git a/crates/configuration/src/server/interceptor.rs b/crates/configuration/src/server/interceptor.rs
new file mode 100644
index 0000000..eeb36c2
--- /dev/null
+++ b/crates/configuration/src/server/interceptor.rs
@@ -0,0 +1,23 @@
+use tonic::{Status, service::Interceptor};
+use tracing::Span;
+use warden_stack::{
+ opentelemetry::global, tracing::telemetry::tonic::extractor,
+ tracing_opentelemetry::OpenTelemetrySpanExt,
+};
+
+#[derive(Clone, Copy)]
+pub struct MyInterceptor;
+
+impl Interceptor for MyInterceptor {
+ fn call(&mut self, request: tonic::Request<()>) -> Result<tonic::Request<()>, Status> {
+ let span = Span::current();
+
+ let cx = global::get_text_map_propagator(|propagator| {
+ propagator.extract(&extractor::MetadataMap(request.metadata()))
+ });
+
+ span.set_parent(cx);
+
+ Ok(request)
+ }
+}
diff --git a/crates/configuration/src/server/version.rs b/crates/configuration/src/server/version.rs
new file mode 100644
index 0000000..4eb5677
--- /dev/null
+++ b/crates/configuration/src/server/version.rs
@@ -0,0 +1,35 @@
+use std::collections::HashMap;
+
+use axum::{
+ RequestPartsExt,
+ extract::{FromRequestParts, Path},
+ http::{StatusCode, request::Parts},
+ response::{IntoResponse, Response},
+};
+use utoipa::ToSchema;
+
+#[derive(Debug, ToSchema)]
+pub enum Version {
+ V0,
+}
+
+impl<S> FromRequestParts<S> for Version
+where
+ S: Send + Sync,
+{
+ type Rejection = Response;
+
+ async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> {
+ let params: Path<HashMap<String, String>> =
+ parts.extract().await.map_err(IntoResponse::into_response)?;
+
+ let version = params
+ .get("version")
+ .ok_or_else(|| (StatusCode::NOT_FOUND, "version param missing").into_response())?;
+
+ match version.as_str() {
+ "v0" => Ok(Version::V0),
+ _ => Err((StatusCode::NOT_FOUND, "unknown version").into_response()),
+ }
+ }
+}