From 98a8855a0e653692becbf5ba3d9453c43ee81e42 Mon Sep 17 00:00:00 2001 From: Al Liu Date: Fri, 20 Oct 2023 14:10:05 +0800 Subject: [PATCH] axum backend for new http api (#465) * axum backend --- nomos-http-api/Cargo.toml | 17 +++++---- nomos-http-api/src/http/backend/axum.rs | 46 +++++++++++++++++++++++++ nomos-http-api/src/http/backend/mod.rs | 2 ++ nomos-http-api/src/http/mod.rs | 1 + nomos-http-api/src/lib.rs | 2 ++ nomos-http-api/tests/todo.rs | 12 +++---- 6 files changed, 68 insertions(+), 12 deletions(-) create mode 100644 nomos-http-api/src/http/backend/axum.rs create mode 100644 nomos-http-api/src/http/backend/mod.rs create mode 100644 nomos-http-api/src/http/mod.rs diff --git a/nomos-http-api/Cargo.toml b/nomos-http-api/Cargo.toml index 7106f1cb..88ef6ab7 100644 --- a/nomos-http-api/Cargo.toml +++ b/nomos-http-api/Cargo.toml @@ -3,20 +3,25 @@ name = "nomos-http-api" version = "0.1.0" edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +axum = ["dep:axum", "dep:hyper", "utoipa-swagger-ui/axum"] [dependencies] async-trait = "0.1" overwatch-rs = { git = "https://github.com/logos-co/Overwatch", rev = "6e6678b" } overwatch-derive = { git = "https://github.com/logos-co/Overwatch", rev = "6e6678b" } tracing = "0.1" +utoipa = "4.0" +utoipa-swagger-ui = { version = "4.0" } + +# axum related dependencies +axum = { version = "0.6", optional = true } +hyper = { version = "0.14", features = ["full"], optional = true } [dev-dependencies] -axum = "0.6.20" -tokio = { version = "1.32", features = ["full"] } -hyper = { version = "*", features = ["full"] } -utoipa = "3.5" +axum = "0.6" +hyper = { version = "0.14", features = ["full"] } +utoipa-swagger-ui = { version = "4.0", features = ["axum"] } reqwest = { version = "0.11", features = ["blocking", "json"] } serde = { version = "1", features = ["derive"] } serde_json = "1" -utoipa-swagger-ui = { version = "3.1", features = ["axum"] } diff --git a/nomos-http-api/src/http/backend/axum.rs b/nomos-http-api/src/http/backend/axum.rs new file mode 100644 index 00000000..efdd26e9 --- /dev/null +++ b/nomos-http-api/src/http/backend/axum.rs @@ -0,0 +1,46 @@ +use std::{net::SocketAddr, sync::Arc}; + +use axum::{Router, Server}; +use utoipa::OpenApi; +use utoipa_swagger_ui::SwaggerUi; + +use crate::Backend; + +#[derive(Clone)] +pub struct AxumBackendSettings { + pub addr: SocketAddr, +} + +pub struct AxumBackend { + settings: Arc, +} + +#[derive(OpenApi)] +#[openapi(paths(), components(), tags())] +struct ApiDoc; + +#[async_trait::async_trait] +impl Backend for AxumBackend { + type Error = hyper::Error; + type Settings = AxumBackendSettings; + + async fn new(settings: Self::Settings) -> Result + where + Self: Sized, + { + Ok(Self { + settings: Arc::new(settings), + }) + } + + async fn serve(self) -> Result<(), Self::Error> { + let store = self.settings.clone(); + let app = Router::new() + .merge(SwaggerUi::new("/swagger-ui").url("/api-docs/openapi.json", ApiDoc::openapi())) + .with_state(store); + + Server::bind(&self.settings.addr) + .serve(app.into_make_service()) + .await + } +} diff --git a/nomos-http-api/src/http/backend/mod.rs b/nomos-http-api/src/http/backend/mod.rs new file mode 100644 index 00000000..8545ecd7 --- /dev/null +++ b/nomos-http-api/src/http/backend/mod.rs @@ -0,0 +1,2 @@ +#[cfg(feature = "axum")] +pub mod axum; diff --git a/nomos-http-api/src/http/mod.rs b/nomos-http-api/src/http/mod.rs new file mode 100644 index 00000000..fceb1419 --- /dev/null +++ b/nomos-http-api/src/http/mod.rs @@ -0,0 +1 @@ +pub mod backend; diff --git a/nomos-http-api/src/lib.rs b/nomos-http-api/src/lib.rs index 5aa6a8c3..7f78baad 100644 --- a/nomos-http-api/src/lib.rs +++ b/nomos-http-api/src/lib.rs @@ -8,6 +8,8 @@ use overwatch_rs::{ DynError, }; +pub mod http; + /// A simple abstraction so that we can easily /// change the underlying http server #[async_trait::async_trait] diff --git a/nomos-http-api/tests/todo.rs b/nomos-http-api/tests/todo.rs index aae85c24..73b95026 100644 --- a/nomos-http-api/tests/todo.rs +++ b/nomos-http-api/tests/todo.rs @@ -133,7 +133,7 @@ mod todo { }; use hyper::{HeaderMap, StatusCode}; use serde::{Deserialize, Serialize}; - use tokio::sync::Mutex; + use std::sync::Mutex; use utoipa::{IntoParams, ToSchema}; /// In-memory todo store @@ -173,7 +173,7 @@ mod todo { ) )] pub(super) async fn list_todos(State(store): State>) -> Json> { - let todos = store.lock().await.clone(); + let todos = store.lock().unwrap().clone(); Json(todos) } @@ -207,7 +207,7 @@ mod todo { Json( store .lock() - .await + .unwrap() .iter() .filter(|todo| { todo.value.to_lowercase() == query.value.to_lowercase() @@ -234,7 +234,7 @@ mod todo { State(store): State>, Json(todo): Json, ) -> impl IntoResponse { - let mut todos = store.lock().await; + let mut todos = store.lock().unwrap(); todos .iter_mut() @@ -284,7 +284,7 @@ mod todo { Err(_) => return StatusCode::UNAUTHORIZED, } - let mut todos = store.lock().await; + let mut todos = store.lock().unwrap(); todos .iter_mut() @@ -324,7 +324,7 @@ mod todo { Err(error) => return error.into_response(), } - let mut todos = store.lock().await; + let mut todos = store.lock().unwrap(); let len = todos.len();