summaryrefslogtreecommitdiff
path: root/src/filters/accesslog.rs
blob: 9a33762380650123e3dabce638f9efc8d0603ed0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
use crate::{config::AccessLogConfig, error::ServiceError, FilterRequest, State};
use futures::executor::block_on;
use log::error;
use std::{net::SocketAddr, ops::ControlFlow, time::SystemTime};
use tokio::{
    fs::OpenOptions,
    io::{AsyncWriteExt, BufWriter},
};

pub async fn access_log(
    state: &State,
    host: &str,
    addr: SocketAddr,
    config: &AccessLogConfig,
    req: &FilterRequest,
) -> Result<ControlFlow<()>, ServiceError> {
    let mut g = state.access_logs.write().await;

    let log = g.entry(host.to_owned()).or_insert_with(|| {
        BufWriter::new(
            // TODO aaahh dont block the runtime and dont panic in any case....
            block_on(
                OpenOptions::new()
                    .append(true)
                    .create(true)
                    .open(&config.file),
            )
            .unwrap(),
        )
    });

    let method = req.method().as_str();
    let time = SystemTime::UNIX_EPOCH.elapsed().unwrap().as_micros();
    let mut res = log
        .write_all(format!("{time}\t{addr}\t{method}\t{:?}\n", req.uri()).as_bytes())
        .await;

    if config.flush && res.is_ok() {
        res = log.flush().await;
    }

    if config.reject_on_fail {
        res?
    } else if let Err(e) = res {
        error!("failed to write log: {e:?}")
    }

    Ok(ControlFlow::Continue(()))
}