prax 0.1.1

a web penetration proxy hosted in neovim
Documentation
use std::sync::Arc;

use prax::Filter;

use super::{view::ViewOp, NVim};

use prax::{Req, Res};
use tokio::sync::{Mutex, Notify};

use prax::lines::{LinesImprint, ToLines};

#[derive(Clone)]
pub struct Intercept(Arc<Mutex<NVim>>);

impl From<NVim> for Intercept {
    fn from(value: NVim) -> Self {
        Intercept(Arc::new(Mutex::new(value)))
    }
}

impl Filter for Intercept {
    async fn modify_request(&self, hostname: &str, req: &mut Req<Vec<u8>>) -> prax::Result<()> {
        let nvim = self.0.lock().await;
        nvim.modify_request(hostname, req).await
    }

    async fn modify_response(&self, hostname: &str, req: &mut Res<Vec<u8>>) -> prax::Result<()> {
        let nvim = self.0.lock().await;
        nvim.modify_response(hostname, req).await
    }
}

impl Filter for NVim {
    async fn modify_request(&self, _: &str, req: &mut Req<Vec<u8>>) -> prax::Result<()> {
        let content = req.to_lines()?;

        let notify = {
            let mut backlog = self.backlog.lock().await;

            if self
                .action
                .send(ViewOp::Intercept {
                    title: "Intercept Request".into(),
                    content,
                })
                .await
                .is_err()
            {
                return Ok(());
            };

            let notify = Arc::new(Notify::new());
            backlog.push_back(notify.clone());
            notify
        };

        notify.notified().await;

        let view = self.view.lock().await;
        let content = view.intercept_buffer().await?;

        req.imprint(content)?;

        Ok(())
    }

    async fn modify_response(&self, _: &str, res: &mut Res<Vec<u8>>) -> prax::Result<()> {
        let content = res.to_lines()?;

        let notify = {
            let mut backlog = self.backlog.lock().await;

            if self
                .action
                .send(ViewOp::Intercept {
                    title: "Intercept Response".into(),
                    content,
                })
                .await
                .is_err()
            {
                return Ok(());
            }

            let notify = Arc::new(Notify::new());
            backlog.push_back(notify.clone());
            notify
        };

        notify.notified().await;

        let view = self.view.lock().await;
        let content = view.intercept_buffer().await?;

        res.imprint(content)?;

        Ok(())
    }
}