refactor: split modules

This commit is contained in:
2025-04-08 02:12:06 +08:00
parent 376d2b28d3
commit 2686fa1d76
94 changed files with 1125 additions and 580 deletions

View File

@@ -7,7 +7,7 @@ use super::core::Controller;
use crate::{
app::AppContextTrait,
auth::{AuthUserInfo, header_www_authenticate_middleware},
errors::app_error::RResult,
errors::RecorderResult,
};
pub const CONTROLLER_PREFIX: &str = "/api/graphql";
@@ -25,7 +25,7 @@ async fn graphql_handler(
graphql_service.schema.execute(req).await.into()
}
pub async fn create(ctx: Arc<dyn AppContextTrait>) -> RResult<Controller> {
pub async fn create(ctx: Arc<dyn AppContextTrait>) -> RecorderResult<Controller> {
let router = Router::<Arc<dyn AppContextTrait>>::new()
.route("/", post(graphql_handler))
.layer(from_fn_with_state(ctx, header_www_authenticate_middleware));

View File

@@ -3,7 +3,7 @@ use std::sync::Arc;
use axum::{Json, Router, extract::State, routing::get};
use serde::Serialize;
use crate::{app::AppContextTrait, errors::app_error::RResult, web::controller::Controller};
use crate::{app::AppContextTrait, errors::RecorderResult, web::controller::Controller};
pub const CONTROLLER_PREFIX: &str = "/api/metadata";
@@ -13,7 +13,9 @@ pub struct StandardResponse {
pub message: String,
}
async fn health(State(ctx): State<Arc<dyn AppContextTrait>>) -> RResult<Json<StandardResponse>> {
async fn health(
State(ctx): State<Arc<dyn AppContextTrait>>,
) -> RecorderResult<Json<StandardResponse>> {
ctx.db().ping().await.inspect_err(
|err| tracing::error!(err.msg = %err, err.detail = ?err, "health check database ping error"),
)?;
@@ -31,7 +33,7 @@ async fn ping() -> Json<StandardResponse> {
})
}
pub async fn create(_context: Arc<dyn AppContextTrait>) -> RResult<Controller> {
pub async fn create(_context: Arc<dyn AppContextTrait>) -> RecorderResult<Controller> {
let router = Router::<Arc<dyn AppContextTrait>>::new()
.route("/health", get(health))
.route("/ping", get(ping));

View File

@@ -2,13 +2,11 @@ use std::sync::Arc;
use axum::{
Json, Router,
extract::{Query, State},
http::request::Parts,
extract::{Query, Request, State},
routing::get,
};
use snafu::prelude::*;
use snafu::ResultExt;
use super::core::Controller;
use crate::{
app::AppContextTrait,
auth::{
@@ -16,9 +14,10 @@ use crate::{
errors::OidcRequestRedirectUriSnafu,
oidc::{OidcAuthCallbackPayload, OidcAuthCallbackQuery, OidcAuthRequest},
},
errors::app_error::RResult,
errors::RecorderResult,
extract::http::ForwardedRelatedInfo,
models::auth::AuthType,
web::controller::core::Controller,
};
pub const CONTROLLER_PREFIX: &str = "/api/oidc";
@@ -43,10 +42,11 @@ async fn oidc_callback(
async fn oidc_auth(
State(ctx): State<Arc<dyn AppContextTrait>>,
parts: Parts,
request: Request,
) -> Result<Json<OidcAuthRequest>, AuthError> {
let auth_service = ctx.auth();
if let AuthService::Oidc(oidc_auth_service) = auth_service {
let (parts, _) = request.into_parts();
let mut redirect_uri = ForwardedRelatedInfo::from_request_parts(&parts)
.resolved_origin()
.ok_or(url::ParseError::EmptyHost)
@@ -73,7 +73,7 @@ async fn oidc_auth(
}
}
pub async fn create(_context: Arc<dyn AppContextTrait>) -> RResult<Controller> {
pub async fn create(_context: Arc<dyn AppContextTrait>) -> RecorderResult<Controller> {
let router = Router::<Arc<dyn AppContextTrait>>::new()
.route("/auth", get(oidc_auth))
.route("/callback", get(oidc_callback));

View File

@@ -12,7 +12,7 @@ use http::StatusCode;
use serde::{Deserialize, Serialize};
use tower_http::catch_panic::CatchPanicLayer;
use crate::{app::AppContextTrait, errors::app_error::RResult, web::middleware::MiddlewareLayer};
use crate::{app::AppContextTrait, errors::RecorderResult, web::middleware::MiddlewareLayer};
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct CatchPanic {
@@ -55,7 +55,7 @@ impl MiddlewareLayer for CatchPanic {
fn apply(
&self,
app: Router<Arc<dyn AppContextTrait>>,
) -> RResult<Router<Arc<dyn AppContextTrait>>> {
) -> RecorderResult<Router<Arc<dyn AppContextTrait>>> {
Ok(app.layer(CatchPanicLayer::custom(handle_panic)))
}
}

View File

@@ -11,7 +11,7 @@ use axum::Router;
use serde::{Deserialize, Serialize};
use tower_http::compression::CompressionLayer;
use crate::{app::AppContextTrait, errors::app_error::RResult, web::middleware::MiddlewareLayer};
use crate::{app::AppContextTrait, errors::RecorderResult, web::middleware::MiddlewareLayer};
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Compression {
@@ -38,7 +38,7 @@ impl MiddlewareLayer for Compression {
fn apply(
&self,
app: Router<Arc<dyn AppContextTrait>>,
) -> RResult<Router<Arc<dyn AppContextTrait>>> {
) -> RecorderResult<Router<Arc<dyn AppContextTrait>>> {
Ok(app.layer(CompressionLayer::new()))
}
}

View File

@@ -12,7 +12,7 @@ use serde::{Deserialize, Serialize};
use serde_json::json;
use tower_http::cors::{self, Any};
use crate::{app::AppContextTrait, errors::app_error::RResult, web::middleware::MiddlewareLayer};
use crate::{app::AppContextTrait, errors::RecorderResult, web::middleware::MiddlewareLayer};
/// CORS middleware configuration
#[derive(Debug, Clone, Deserialize, Serialize)]
@@ -80,7 +80,7 @@ impl Cors {
///
/// In all of these cases, the error returned will be the result of the
/// `parse` method of the corresponding type.
pub fn cors(&self) -> RResult<cors::CorsLayer> {
pub fn cors(&self) -> RecorderResult<cors::CorsLayer> {
let mut cors: cors::CorsLayer = cors::CorsLayer::new();
// testing CORS, assuming https://example.com in the allow list:
@@ -160,7 +160,7 @@ impl MiddlewareLayer for Cors {
fn apply(
&self,
app: Router<Arc<dyn AppContextTrait>>,
) -> RResult<Router<Arc<dyn AppContextTrait>>> {
) -> RecorderResult<Router<Arc<dyn AppContextTrait>>> {
Ok(app.layer(self.cors()?))
}
}

View File

@@ -21,11 +21,11 @@ use axum::{
},
response::Response,
};
use futures_util::future::BoxFuture;
use futures::future::BoxFuture;
use serde::{Deserialize, Serialize};
use tower::{Layer, Service};
use crate::{app::AppContextTrait, errors::app_error::RResult, web::middleware::MiddlewareLayer};
use crate::{app::AppContextTrait, errors::RecorderResult, web::middleware::MiddlewareLayer};
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Etag {
@@ -52,7 +52,7 @@ impl MiddlewareLayer for Etag {
fn apply(
&self,
app: Router<Arc<dyn AppContextTrait>>,
) -> RResult<Router<Arc<dyn AppContextTrait>>> {
) -> RecorderResult<Router<Arc<dyn AppContextTrait>>> {
Ok(app.layer(EtagLayer))
}
}

View File

@@ -1,4 +1,3 @@
//! Detect a content type and format and responds accordingly
use axum::{
extract::FromRequestParts,
http::{
@@ -8,7 +7,7 @@ use axum::{
};
use serde::{Deserialize, Serialize};
use crate::errors::app_error::RError as Error;
use crate::errors::RecorderError as Error;
#[derive(Debug, Deserialize, Serialize)]
pub struct Format(pub RespondTo);

View File

@@ -15,7 +15,7 @@ use tower_http::{add_extension::AddExtensionLayer, trace::TraceLayer};
use crate::{
app::{AppContextTrait, Environment},
errors::app_error::RResult,
errors::RecorderResult,
web::middleware::{MiddlewareLayer, request_id::LocoRequestId},
};
@@ -70,7 +70,7 @@ impl MiddlewareLayer for Middleware {
fn apply(
&self,
app: Router<Arc<dyn AppContextTrait>>,
) -> RResult<Router<Arc<dyn AppContextTrait>>> {
) -> RecorderResult<Router<Arc<dyn AppContextTrait>>> {
Ok(app
.layer(
TraceLayer::new_for_http().make_span_with(|request: &http::Request<_>| {

View File

@@ -14,7 +14,7 @@ use std::sync::Arc;
use axum::Router;
use serde::{Deserialize, Serialize};
use crate::{app::AppContextTrait, errors::app_error::RResult};
use crate::{app::AppContextTrait, errors::RecorderResult};
/// Trait representing the behavior of middleware components in the application.
/// When implementing a new middleware, make sure to go over this checklist:
@@ -55,7 +55,7 @@ pub trait MiddlewareLayer {
fn apply(
&self,
app: Router<Arc<dyn AppContextTrait>>,
) -> RResult<Router<Arc<dyn AppContextTrait>>>;
) -> RecorderResult<Router<Arc<dyn AppContextTrait>>>;
}
#[allow(clippy::unnecessary_lazy_evaluations)]

View File

@@ -24,7 +24,7 @@ use axum::{
http::{header::HeaderMap, request::Parts},
response::Response,
};
use futures_util::future::BoxFuture;
use futures::future::BoxFuture;
use ipnetwork::IpNetwork;
use serde::{Deserialize, Serialize};
use snafu::ResultExt;
@@ -33,7 +33,7 @@ use tracing::error;
use crate::{
app::AppContextTrait,
errors::app_error::{RError, RResult},
errors::app_error::{RecorderError, RecorderResult},
web::middleware::MiddlewareLayer,
};
@@ -127,7 +127,7 @@ impl MiddlewareLayer for RemoteIpMiddleware {
fn apply(
&self,
app: Router<Arc<dyn AppContextTrait>>,
) -> RResult<Router<Arc<dyn AppContextTrait>>> {
) -> RecorderResult<Router<Arc<dyn AppContextTrait>>> {
Ok(app.layer(RemoteIPLayer::new(self)?))
}
}
@@ -225,7 +225,7 @@ impl RemoteIPLayer {
///
/// # Errors
/// Fails if invalid header values found
pub fn new(config: &RemoteIpMiddleware) -> RResult<Self> {
pub fn new(config: &RemoteIpMiddleware) -> RecorderResult<Self> {
Ok(Self {
trusted_proxies: config
.trusted_proxies
@@ -236,14 +236,14 @@ impl RemoteIPLayer {
.map(|proxy| {
IpNetwork::from_str(proxy)
.boxed()
.with_whatever_context::<_, _, RError>(|_| {
.with_whatever_context::<_, _, RecorderError>(|_| {
format!(
"remote ip middleare cannot parse trusted proxy \
configuration: `{proxy}`"
)
})
})
.collect::<RResult<Vec<_>>>()
.collect::<RecorderResult<Vec<_>>>()
})
.transpose()?,
})

View File

@@ -18,7 +18,7 @@ const MAX_LEN: usize = 255;
use std::sync::{Arc, OnceLock};
use crate::errors::app_error::RResult;
use crate::errors::RecorderResult;
static ID_CLEANUP: OnceLock<Regex> = OnceLock::new();
@@ -57,7 +57,7 @@ impl MiddlewareLayer for RequestId {
fn apply(
&self,
app: Router<Arc<dyn AppContextTrait>>,
) -> RResult<Router<Arc<dyn AppContextTrait>>> {
) -> RecorderResult<Router<Arc<dyn AppContextTrait>>> {
Ok(app.layer(axum::middleware::from_fn(request_id_middleware)))
}
}

View File

@@ -15,13 +15,13 @@ use axum::{
http::{HeaderName, HeaderValue, Request},
response::Response,
};
use futures_util::future::BoxFuture;
use futures::future::BoxFuture;
use serde::{Deserialize, Serialize};
use serde_json::{self, json};
use snafu::whatever;
use tower::{Layer, Service};
use crate::{app::AppContextTrait, errors::app_error::RResult, web::middleware::MiddlewareLayer};
use crate::{app::AppContextTrait, errors::RecorderResult, web::middleware::MiddlewareLayer};
static PRESETS: OnceLock<HashMap<String, BTreeMap<String, String>>> = OnceLock::new();
fn get_presets() -> &'static HashMap<String, BTreeMap<String, String>> {
@@ -115,7 +115,7 @@ impl MiddlewareLayer for SecureHeader {
fn apply(
&self,
app: Router<Arc<dyn AppContextTrait>>,
) -> RResult<Router<Arc<dyn AppContextTrait>>> {
) -> RecorderResult<Router<Arc<dyn AppContextTrait>>> {
Ok(app.layer(SecureHeaders::new(self)?))
}
}
@@ -124,7 +124,7 @@ impl SecureHeader {
/// Converts the configuration into a list of headers.
///
/// Applies the preset headers and any custom overrides.
fn as_headers(&self) -> RResult<Vec<(HeaderName, HeaderValue)>> {
fn as_headers(&self) -> RecorderResult<Vec<(HeaderName, HeaderValue)>> {
let mut headers = vec![];
let preset = &self.preset;
@@ -147,7 +147,7 @@ impl SecureHeader {
fn push_headers(
headers: &mut Vec<(HeaderName, HeaderValue)>,
hm: &BTreeMap<String, String>,
) -> RResult<()> {
) -> RecorderResult<()> {
for (k, v) in hm {
headers.push((
HeaderName::from_bytes(k.clone().as_bytes())?,
@@ -171,7 +171,7 @@ impl SecureHeaders {
///
/// # Errors
/// Returns an error if any header values are invalid.
pub fn new(config: &SecureHeader) -> RResult<Self> {
pub fn new(config: &SecureHeader) -> RecorderResult<Self> {
Ok(Self {
headers: config.as_headers()?,
})

View File

@@ -16,7 +16,7 @@ use serde::{Deserialize, Serialize};
use serde_json::json;
use tower_http::timeout::TimeoutLayer;
use crate::{app::AppContextTrait, errors::app_error::RResult, web::middleware::MiddlewareLayer};
use crate::{app::AppContextTrait, errors::RecorderResult, web::middleware::MiddlewareLayer};
/// Timeout middleware configuration
#[derive(Debug, Clone, Deserialize, Serialize)]
@@ -61,7 +61,7 @@ impl MiddlewareLayer for TimeOut {
fn apply(
&self,
app: Router<Arc<dyn AppContextTrait>>,
) -> RResult<Router<Arc<dyn AppContextTrait>>> {
) -> RecorderResult<Router<Arc<dyn AppContextTrait>>> {
Ok(app.layer(TimeoutLayer::new(Duration::from_millis(self.timeout))))
}
}