use crate::layer::har::service::HARExportService;
use crate::layer::har::toggle::Toggle;
use rama_core::Layer;
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct HARExportLayer<R, T> {
recorder: R,
toggle: T,
preserve_sensitive: bool,
}
impl<R, T> HARExportLayer<R, T> {
pub fn new(recorder: R, toggle: T) -> Self {
Self {
recorder,
toggle,
preserve_sensitive: false,
}
}
pub fn recorder(&self) -> &R {
&self.recorder
}
pub fn toggle(&self) -> &T {
&self.toggle
}
rama_utils::macros::generate_set_and_with! {
pub fn preserve_sensitive(mut self) -> Self {
self.preserve_sensitive = true;
self
}
}
}
impl<R, S, T> Layer<S> for HARExportLayer<R, T>
where
R: Clone + Send + Sync + 'static,
T: Toggle + Clone + Send + Sync + 'static,
{
type Service = HARExportService<R, S, T>;
fn layer(&self, service: S) -> Self::Service {
HARExportService {
service,
toggle: self.toggle.clone(),
recorder: self.recorder.clone(),
preserve_sensitive: self.preserve_sensitive,
}
}
fn into_layer(self, service: S) -> Self::Service {
HARExportService {
service,
toggle: self.toggle,
recorder: self.recorder,
preserve_sensitive: self.preserve_sensitive,
}
}
}
#[cfg(test)]
mod tests {
use rama_core::extensions::Extensions;
use super::*;
use crate::layer::har::recorder::Recorder;
use crate::layer::har::spec::Log;
use crate::layer::har::toggle::mpsc_unbounded_toggle;
use parking_lot::Mutex;
use std::future::ready;
use std::sync::{Arc, atomic::Ordering};
#[derive(Clone, Default)]
pub struct InMemoryRecorder {
logs: Arc<Mutex<Vec<Log>>>,
}
impl InMemoryRecorder {
#[must_use]
#[inline]
pub fn new() -> Self {
Self::default()
}
}
impl Recorder for InMemoryRecorder {
async fn record(&self, log: Log) -> Option<Extensions> {
let mut lock = self.logs.lock();
lock.push(log);
None
}
fn stop_record(&self) -> impl Future<Output = ()> + Send {
ready(())
}
}
impl<T: Toggle> HARExportLayer<InMemoryRecorder, T> {
pub fn new_test(toggle: T) -> Self {
Self::new(InMemoryRecorder::new(), toggle)
}
}
#[tokio::test]
async fn in_memory_recorder_records_logs() {
let (flag, tx) = mpsc_unbounded_toggle(std::future::pending::<()>());
let layer = HARExportLayer::new_test(flag.clone());
assert!(!flag.load(Ordering::Relaxed));
tx.send(()).unwrap();
tokio::task::yield_now().await;
assert!(flag.load(Ordering::Relaxed));
layer.recorder.record(Log::default()).await;
tx.send(()).unwrap();
tokio::task::yield_now().await;
assert!(!flag.load(Ordering::Relaxed));
let data = layer.recorder.logs.lock();
assert!(
!data.is_empty(),
"Expected recorder to have recorded at least one HAR log"
);
}
}