chore(logs): add explicit http logs
Default is now RUST_LOG=info,http=warn. Effect of each level on the access log: ┌────────────────────┬────────────────────────┐ │ Level on http │ Status classes emitted │ ├────────────────────┼────────────────────────┤ │ info │ 2xx/3xx + 4xx + 5xx │ ├────────────────────┼────────────────────────┤ │ warn (default) │ 4xx + 5xx │ ├────────────────────┼────────────────────────┤ │ error │ 5xx only │ ├────────────────────┼────────────────────────┤ │ off │ nothing │ └────────────────────┴────────────────────────┘ Target mapping: ┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬─────────────────┐ │ Routes │ Target │ ├────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼─────────────────┤ │ health_routes │ http::probe │ ├────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼─────────────────┤ │ magic_link_router │ http::web │ ├────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼─────────────────┤ │ All /api/auth/* sub-routers (login, register, refresh, public, protected, app_pw, device_public, device_protected) │ http::api::auth │ ├────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼─────────────────┤ │ setup_router, public_api_routes, protected_api, wopi_api_protected │ http::api │ ├────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼─────────────────┤ │ well_known_router, caldav_protected, carddav_protected, webdav_protected │ http::dav │ ├────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼─────────────────┤ │ nc_router │ http::nextcloud │ ├────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼─────────────────┤ │ wopi_protocol │ http::wopi │ ├────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼─────────────────┤ │ web_routes (+ ServeDir fallback) │ http::web │ └────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴─────────────────┘ # Default value: - **http=warn** if target http not specified - **http::web=error** if target http::web not specified Common operator overrides: # Server-error-only access logs (the new default) unset RUST_LOG # See login failures and other client errors on auth RUST_LOG=info,http=warn,http::api::auth=info # which is similar to RUST_LOG=info,http::api::auth=info # Full access log everywhere (heavy) RUST_LOG=info,http=info # Silence everything except errors RUST_LOG=warn
This commit is contained in:
@@ -2,10 +2,11 @@ use crate::application::services::batch_operations::BatchOperationService;
|
||||
use crate::common::di::AppState;
|
||||
use axum::{
|
||||
Router,
|
||||
body::Body,
|
||||
extract::{DefaultBodyLimit, State},
|
||||
http::StatusCode,
|
||||
response::{IntoResponse, Json as AxumJson},
|
||||
routing::{delete, get, post, put},
|
||||
response::{IntoResponse, Json as AxumJson, Response},
|
||||
routing::{any, delete, get, post, put},
|
||||
};
|
||||
use serde_json::json;
|
||||
use std::sync::Arc;
|
||||
@@ -588,6 +589,19 @@ pub fn create_api_routes(app_state: &Arc<AppState>) -> Router<Arc<AppState>> {
|
||||
.with_state(app_state.clone());
|
||||
router = router.nest("/users", users_router);
|
||||
|
||||
// Collector for any unknown `/api/*` path. Without this, an
|
||||
// unmatched API URL falls through Axum's matcher to the
|
||||
// ServeDir fallback and is logged under `http::web` — wrong
|
||||
// surface for operator triage. Adding the catch-all here
|
||||
// anchors the 404 on whichever access-log layer the parent
|
||||
// mount applies (i.e. `http::api`).
|
||||
//
|
||||
// The bare `/api/auth/*`, `/api/wopi/*`, and other more-
|
||||
// specific nests are registered at higher specificity and
|
||||
// still win over this catch-all — Axum's matcher prefers
|
||||
// them on every overlapping request.
|
||||
router = router.route("/{*rest}", any(api_not_found));
|
||||
|
||||
// Compression is applied once, globally, in `main.rs` with a content-type
|
||||
// aware predicate that skips already-compressed media. Re-applying it here
|
||||
// would double-wrap `/api`: this inner layer (no predicate) would compress
|
||||
@@ -595,3 +609,12 @@ pub fn create_api_routes(app_state: &Arc<AppState>) -> Router<Arc<AppState>> {
|
||||
// So this router only adds tracing; compression is the global layer's job.
|
||||
router.layer(TraceLayer::new_for_http())
|
||||
}
|
||||
|
||||
/// Catch-all 404 for unknown `/api/*` paths. Pure log-anchoring
|
||||
/// shim — see the comment in `create_api_routes`.
|
||||
async fn api_not_found() -> Response {
|
||||
Response::builder()
|
||||
.status(StatusCode::NOT_FOUND)
|
||||
.body(Body::empty())
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user