Skip to main content

http_request_derive_logging/
logging.rs

1// SPDX-FileCopyrightText: OpenTalk GmbH <mail@opentalk.eu>
2//
3// SPDX-License-Identifier: MIT OR Apache-2.0
4
5use std::sync::Arc;
6
7use bytes::Bytes;
8use tokio::sync::RwLock;
9
10/// A middleware for logging HTTP requests.
11#[derive(Clone)]
12pub struct HttpLogger {
13    backend: Arc<RwLock<dyn HttpLoggerBackend>>,
14}
15
16impl HttpLogger {
17    /// Create a new HTTP logger from a backend
18    pub fn new<T: HttpLoggerBackend + 'static>(backend: T) -> Self {
19        Self {
20            backend: Arc::new(RwLock::new(backend)),
21        }
22    }
23
24    /// Create a new HTTP logger from a backend that is encapsulated in an `Arc<Rwlock<_>>`.
25    ///
26    /// This can be used in order to maintain access to the backend inside the `RwLock`
27    /// even after passing it into the `HttpLogger`.
28    pub fn new_with_locked<T: HttpLoggerBackend + 'static>(backend: Arc<RwLock<T>>) -> Self {
29        Self { backend }
30    }
31
32    /// Log a HTTP request.
33    pub async fn log_request(
34        &self,
35        start_time: std::time::SystemTime,
36        request: &http::Request<Vec<u8>>,
37        response: Option<&http::Response<Bytes>>,
38    ) {
39        let mut lock = self.backend.write().await;
40        lock.log_request(start_time, request, response).await;
41    }
42}
43
44impl std::fmt::Debug for HttpLogger {
45    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46        f.debug_struct("ExampleLogger").field("inner", &()).finish()
47    }
48}
49
50/// Implement this trait for middlewares that can log HTTP traffic.
51#[async_trait::async_trait(?Send)]
52pub trait HttpLoggerBackend {
53    /// Log a HTTP request.
54    async fn log_request(
55        &mut self,
56        start_time: std::time::SystemTime,
57        request: &http::Request<Vec<u8>>,
58        response: Option<&http::Response<Bytes>>,
59    );
60}