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:
Edouard Vanbelle
2026-06-08 08:37:16 +02:00
parent 06e4e56ce7
commit 4fc3746754
5 changed files with 438 additions and 78 deletions
+38 -1
View File
@@ -76,7 +76,33 @@ pub fn nextcloud_routes_with_state(state: Arc<AppState>) -> Router<Arc<AppState>
.route(
"/ocs/v2.php/cloud/capabilities",
get(ocs_handler::handle_capabilities_v2),
);
)
// Final NC catch-alls. Any `/ocs/*` or `/remote.php/*` URL
// the routes above don't claim returns 404 here — so it's
// logged under the `http::nextcloud` access-log target the
// surrounding `.layer(access_log!(…))` in main.rs assigns,
// instead of falling through Axum's matcher to ServeDir
// and being mis-attributed to `http::web`.
//
// Concrete example: NC desktop probes
// `/ocs/v2.php/core/navigation/apps` to discover server
// features. We don't implement that endpoint; without these
// catch-alls the 404 was emitted at `http::web`, which is
// misleading for operators triaging Nextcloud client noise.
//
// Mounted on the PUBLIC sub-router (NOT behind basic-auth)
// so unknown-endpoint probes return 404 regardless of
// whether the client sent credentials. Moving them into
// `protected` would turn anonymous probes into 401
// challenges, which breaks some clients' capability-
// detection paths.
//
// Axum routes more-specific paths first, so the specific
// NC routes above (and the protected ones below) still
// claim their requests; only genuinely unmatched paths
// reach these handlers.
.route("/ocs/{*rest}", any(handle_nc_not_found))
.route("/remote.php/{*rest}", any(handle_nc_not_found));
// Protected routes — require Basic Auth via app passwords.
let protected = Router::new()
@@ -297,3 +323,14 @@ async fn handle_dav_discovery() -> Response {
.body(Body::empty())
.unwrap()
}
/// Catch-all 404 for any `/ocs/*` or `/remote.php/*` path the NC
/// router doesn't recognize. Exists purely to anchor the access-log
/// target — see the comment on the routes above for the operator
/// rationale.
async fn handle_nc_not_found() -> Response {
Response::builder()
.status(StatusCode::NOT_FOUND)
.body(Body::empty())
.unwrap()
}