diff --git a/Cargo.lock b/Cargo.lock index e2f63be..39e0a29 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1271,6 +1271,26 @@ dependencies = [ "subtle", ] +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "doc-comment" version = "0.3.3" @@ -1708,6 +1728,8 @@ dependencies = [ "serde_json", "thiserror", "tracing", + "utoipa", + "utoipa-swagger-ui", ] [[package]] @@ -1816,6 +1838,7 @@ checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", "hashbrown", + "serde", ] [[package]] @@ -2037,6 +2060,16 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +[[package]] +name = "mime_guess" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -2588,6 +2621,30 @@ dependencies = [ "syn", ] +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + [[package]] name = "proc-macro2" version = "1.0.51" @@ -2720,6 +2777,17 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall", + "thiserror", +] + [[package]] name = "regex" version = "1.7.1" @@ -2818,6 +2886,41 @@ dependencies = [ "smallvec", ] +[[package]] +name = "rust-embed" +version = "6.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "283ffe2f866869428c92e0d61c2f35dfb4355293cdfdc48f49e895c15f1333d1" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "6.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31ab23d42d71fb9be1b643fe6765d292c5e14d46912d13f3ae2815ca048ea04d" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "shellexpand", + "syn", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "7.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1669d81dfabd1b5f8e2856b8bbe146c6192b0ba22162edc738ac0a5de18f054" +dependencies = [ + "sha2", + "walkdir", +] + [[package]] name = "rustc_version" version = "0.4.0" @@ -2884,6 +2987,15 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "schannel" version = "0.1.21" @@ -3032,6 +3144,15 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shellexpand" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ccc8076840c4da029af4f87e4e8daeb0fca6b87bbb02e10cb60b791450e11e4" +dependencies = [ + "dirs", +] + [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -3566,6 +3687,15 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +[[package]] +name = "unicase" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +dependencies = [ + "version_check", +] + [[package]] name = "unicode-bidi" version = "0.3.10" @@ -3616,6 +3746,48 @@ version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8db7427f936968176eaa7cdf81b7f98b980b18495ec28f1b5791ac3bfe3eea9" +[[package]] +name = "utoipa" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a15f6da6a2b471134ca44b7d18e8a76d73035cf8b3ed24c4dd5ca6a63aa439c5" +dependencies = [ + "indexmap", + "serde", + "serde_json", + "utoipa-gen", +] + +[[package]] +name = "utoipa-gen" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f2e33027986a4707b3f5c37ed01b33d0e5a53da30204b52ff18f80600f1d0ec" +dependencies = [ + "lazy_static", + "proc-macro-error", + "proc-macro2", + "quote", + "regex", + "syn", +] + +[[package]] +name = "utoipa-swagger-ui" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3d4f4da6408f0f20ff58196ed619c94306ab32635aeca3d3fa0768c0bd0de2" +dependencies = [ + "actix-web", + "mime_guess", + "regex", + "rust-embed", + "serde", + "serde_json", + "utoipa", + "zip", +] + [[package]] name = "uuid" version = "0.8.2" @@ -3655,6 +3827,17 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + [[package]] name = "want" version = "0.3.0" @@ -3916,6 +4099,18 @@ version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" +[[package]] +name = "zip" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0445d0fbc924bb93539b4316c11afb121ea39296f99a3c4c9edad09e3658cdef" +dependencies = [ + "byteorder", + "crc32fast", + "crossbeam-utils", + "flate2", +] + [[package]] name = "zstd" version = "0.12.3+zstd.1.5.2" diff --git a/httpw/Cargo.toml b/httpw/Cargo.toml index 08e2222..f61c350 100644 --- a/httpw/Cargo.toml +++ b/httpw/Cargo.toml @@ -15,3 +15,5 @@ serde_json = { version = "1.0.93" } tracing = { version = "0.1.37" } opentelemetry = { version = "0.18.0" } actix-web-opentelemetry = { version = "0.13.0", features = ["metrics"] } +utoipa = { version = "3.0.2", features = ["actix_extras"] } +utoipa-swagger-ui = { version = "3.0.2", features = ["actix-web"] } diff --git a/httpw/src/server/server.rs b/httpw/src/server/server.rs index 26b0057..36ef41e 100644 --- a/httpw/src/server/server.rs +++ b/httpw/src/server/server.rs @@ -1,6 +1,7 @@ use super::types::RouteConfig; use crate::{errors::HttpServerError, middlewares}; use actix_web::{ + http::KeepAlive, middleware as actix_middleware, web::{self, Data}, App, HttpResponse, HttpServer, Responder, @@ -9,14 +10,16 @@ use actix_web_opentelemetry::{RequestMetricsBuilder, RequestTracing}; use auth::jwt_manager::JwtManager; use env::AppConfig; use opentelemetry::global; -use std::sync::Arc; +use std::{sync::Arc, time::Duration}; use tracing::error; +use utoipa::openapi::OpenApi; +use utoipa_swagger_ui::SwaggerUi; pub struct HttpwServerImpl { services: Vec, jwt_manager: Option>, addr: String, - // openapi_file_path: Option, + openapi: Option, } impl HttpwServerImpl { @@ -25,7 +28,7 @@ impl HttpwServerImpl { services: vec![], addr: cfg.app_addr(), jwt_manager: None, - // openapi_file_path: None, + openapi: None, } } } @@ -41,16 +44,16 @@ impl HttpwServerImpl { self } - // pub fn openapi_file_path(mut self, file_path: String) -> Self { - // self.openapi_file_path = Some(file_path); - // self - // } + pub fn openapi(mut self, openapi: &OpenApi) -> Self { + self.openapi = Some(openapi.to_owned()); + self + } pub async fn start(&self) -> Result<(), HttpServerError> { HttpServer::new({ let services = self.services.to_vec(); let jwt_manager = self.jwt_manager.clone(); - // let openapi_file = self.openapi_file_path.clone(); + let openapi = self.openapi.clone(); move || { let meter = global::meter("actix_web"); @@ -74,22 +77,20 @@ impl HttpwServerImpl { app = app.configure(svc); } - // if let Some(_openapi) = openapi_file.clone() { - // let spec = swagger_ui::swagger_spec_file!("../../swagger-ui/examples/openapi.json"); - // let config = swagger_ui::Config::default(); - // - // let app = app.service( - // scope("/v1/doc") - // .configure(actix_web_swagger_ui::swagger(spec, config)) - // ); - // - // } + if openapi.is_some() { + app = app.service( + SwaggerUi::new("/docs/{_:.*}") + .url("/docs/openapi.json", openapi.clone().unwrap()), + ); + } app.route("/health", web::get().to(health_handler)) .default_service(web::to(middlewares::not_found::not_found)) .wrap(actix_middleware::Logger::default()) } }) + .shutdown_timeout(60) + .keep_alive(KeepAlive::Timeout(Duration::new(2, 0))) .bind(&self.addr) .map_err(|e| { error!( diff --git a/httpw/src/viewmodels/error.rs b/httpw/src/viewmodels/error.rs index 2f61e33..0cd7f9f 100644 --- a/httpw/src/viewmodels/error.rs +++ b/httpw/src/viewmodels/error.rs @@ -1,8 +1,8 @@ -use std::fmt; - use serde::Serialize; +use std::fmt; +use utoipa::ToSchema; -#[derive(Debug, Default, Serialize)] +#[derive(Debug, Default, Serialize, ToSchema)] pub struct HttpErrorViewModel { pub status_code: u16, pub message: String,