added base for openapi & swaggerui

This commit is contained in:
2025-02-18 18:42:04 +01:00
parent 466f8dd992
commit c29aae3207
6 changed files with 766 additions and 23 deletions

View File

@@ -1,9 +1,9 @@
use crate::base::{entity::BaseEntity, i_service::IBaseService};
use anyhow::Result;
use axum::{http::StatusCode, response::IntoResponse, Json};
use axum::{extract::State, http::StatusCode, response::IntoResponse, routing::get, Json, Router};
use diesel::Identifiable;
use serde::Serialize;
use std::marker::PhantomData;
use crate::base::{entity::BaseEntity, i_service::IBaseService};
use std::{marker::PhantomData, ops::Deref, sync::Arc};
pub struct BaseController<T, S>
where
@@ -27,7 +27,28 @@ where
}
pub async fn get_all(&self) -> Result<impl IntoResponse, String> {
let entities = self.service.get_all().await.map_err(|err| err.to_string())?;
let entities = self
.service
.get_all()
.await
.map_err(|err| err.to_string())?;
Ok((StatusCode::OK, Json(entities)))
}
pub fn default_routes<C>(controller: Arc<C>, base_path: &str) -> Router
where
C: Deref<Target = Self> + Send + Sync + 'static,
{
Router::new()
.route(
&format!("{}", base_path),
get(|State(controller): State<Arc<C>>| async move {
controller
.get_all()
.await
.map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, Json(err)))
}),
)
.with_state(controller)
}
}

View File

@@ -1,11 +1,16 @@
use std::sync::Arc;
use crate::routes::user::controller::UserController;
use crate::routes::user::model::{User, UserResponse};
use crate::routes::user::service::UserService;
use axum::http::StatusCode;
use axum::routing::get;
use axum::{serve, Router};
use config::db::init_db;
use dotenvy::dotenv;
use tokio::net::TcpListener;
use crate::routes::user::controller::UserController;
use crate::routes::user::service::UserService;
use utoipa::OpenApi;
use utoipa_swagger_ui::SwaggerUi;
mod base;
mod config;
@@ -16,12 +21,31 @@ async fn main() {
dotenv().ok();
let pool = init_db();
let hc_router = Router::new().route("/", get(health_check));
let user_service = UserService::new(pool);
let user_controller = Arc::new(UserController::new(user_service));
let app = Router::new()
.merge(UserController::routes(user_controller.clone()));
.merge(UserController::routes(user_controller.clone()))
.merge(SwaggerUi::new("/swagger-ui").url("/api-docs/openapi.json", ApiDoc::openapi()))
.nest("/hc", hc_router);
let listener = TcpListener::bind("0.0.0.0:3000").await.unwrap();
serve(listener, app).await.unwrap();
async fn health_check() -> StatusCode {
StatusCode::OK
}
#[derive(OpenApi)]
#[openapi(
components(
schemas(User, UserResponse)
),
tags(
(name = "users", description = "User management endpoints")
)
)]
struct ApiDoc;
}

View File

@@ -1,11 +1,8 @@
use std::ops::Deref;
use std::sync::Arc;
use axum::extract::State;
use axum::http::StatusCode;
use axum::response::IntoResponse;
use axum::{Json, Router};
use axum::routing::get;
use crate::base::controller::BaseController;
use axum::Router;
use super::model::User;
use super::service::UserService;
@@ -14,6 +11,14 @@ pub struct UserController {
base_controller: BaseController<User, UserService>,
}
impl Deref for UserController {
type Target = BaseController<User, UserService>;
fn deref(&self) -> &Self::Target {
&self.base_controller
}
}
impl UserController {
pub fn new(service: UserService) -> Self {
Self {
@@ -21,17 +26,19 @@ impl UserController {
}
}
pub fn routes(state: Arc<UserController>) -> Router {
Router::new()
.route("/users", get(Self::get_users))
.with_state(state)
pub fn routes(controller: Arc<Self>) -> Router {
BaseController::default_routes(controller, "/users")
}
/*
async fn get_users(
State(controller): State<Arc<UserController>>,
) -> Result<impl IntoResponse, (StatusCode, Json<String>)> {
controller.base_controller.get_all().await.map_err(|err| {
(StatusCode::INTERNAL_SERVER_ERROR, Json(err))
})
controller
.base_controller
.get_all()
.await
.map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, Json(err)))
}
*/
}

View File

@@ -1,9 +1,10 @@
use super::schema::users;
use crate::base::entity::BaseEntity;
use diesel::prelude::*;
use serde::{Deserialize, Serialize};
use crate::base::entity::BaseEntity;
use super::schema::users;
use utoipa::ToSchema;
#[derive(Debug, Clone, Serialize, Deserialize, Queryable, Identifiable)]
#[derive(Debug, Clone, Serialize, Deserialize, Queryable, Identifiable, ToSchema)]
#[diesel(table_name = users, primary_key(id))]
pub struct User {
pub id: i32,
@@ -11,6 +12,13 @@ pub struct User {
pub email: String,
}
#[derive(Debug, Serialize, ToSchema)]
pub struct UserResponse {
pub id: i32,
pub name: String,
pub email: String,
}
impl BaseEntity for User {
fn id(&self) -> i32 {
self.id
@@ -23,4 +31,5 @@ impl Identifiable for User {
fn id(self) -> Self::Id {
self.id
}
}
}