tsukuyomi 0.5.3

Asynchronous Web framework for Rust
Documentation
use {
    std::sync::{Arc, Mutex},
    tsukuyomi::{
        config::prelude::*, //
        handler::{AllowedMethods, Handler, ModifyHandler},
        App,
    },
};

#[derive(Clone)]
struct MockModifier {
    marker: Arc<Mutex<Vec<&'static str>>>,
    name: &'static str,
}

impl<H: Handler> ModifyHandler<H> for MockModifier {
    type Output = H::Output;
    type Handler = MockHandler<H>;

    fn modify(&self, inner: H) -> Self::Handler {
        MockHandler {
            inner,
            marker: self.marker.clone(),
            name: self.name,
        }
    }
}

struct MockHandler<H> {
    inner: H,
    marker: Arc<Mutex<Vec<&'static str>>>,
    name: &'static str,
}

impl<H> Handler for MockHandler<H>
where
    H: Handler,
{
    type Output = H::Output;
    type Error = H::Error;
    type Handle = H::Handle;

    fn allowed_methods(&self) -> Option<&AllowedMethods> {
        self.inner.allowed_methods()
    }

    fn handle(&self) -> Self::Handle {
        self.marker.lock().unwrap().push(self.name);
        self.inner.handle()
    }
}

#[test]
fn global_modifier() -> tsukuyomi_server::Result<()> {
    let marker = Arc::new(Mutex::new(vec![]));

    let app = App::create(
        path!("/") //
            .to(endpoint::reply(""))
            .modify(MockModifier {
                marker: marker.clone(),
                name: "M",
            }),
    )?;

    let mut server = tsukuyomi_server::test::server(app)?;

    let _ = server.perform("/")?;
    assert_eq!(*marker.lock().unwrap(), vec!["M"]);

    marker.lock().unwrap().clear();
    let _ = server.perform("/noroute")?;
    assert!(marker.lock().unwrap().is_empty());

    Ok(())
}

#[test]
fn global_modifiers() -> tsukuyomi_server::Result<()> {
    let marker = Arc::new(Mutex::new(vec![]));

    let app = App::create(
        path!("/") //
            .to(endpoint::reply(""))
            .modify(chain![
                MockModifier {
                    marker: marker.clone(),
                    name: "M1",
                },
                MockModifier {
                    marker: marker.clone(),
                    name: "M2",
                }
            ]),
    )?;
    let mut server = tsukuyomi_server::test::server(app)?;

    let _ = server.perform("/")?;
    assert_eq!(*marker.lock().unwrap(), vec!["M2", "M1"]);

    Ok(())
}

#[test]
fn scoped_modifier() -> tsukuyomi_server::Result<()> {
    let marker = Arc::new(Mutex::new(vec![]));

    let app = App::create(
        chain![
            mount("/path1").with({
                path!("/") //
                    .to(endpoint::reply(""))
                    .modify(MockModifier {
                        marker: marker.clone(),
                        name: "M2",
                    })
            }), //
            path!("/path2").to(endpoint::reply("")),
        ]
        .modify(MockModifier {
            marker: marker.clone(),
            name: "M1",
        }),
    )?;
    let mut server = tsukuyomi_server::test::server(app)?;

    let _ = server.perform("/path1")?;
    assert_eq!(*marker.lock().unwrap(), vec!["M2", "M1"]);

    marker.lock().unwrap().clear();
    let _ = server.perform("/path2")?;
    assert_eq!(*marker.lock().unwrap(), vec!["M1"]);

    Ok(())
}

#[test]
fn nested_modifiers() -> tsukuyomi_server::Result<()> {
    let marker = Arc::new(Mutex::new(vec![]));

    let app = App::create({
        mount("/path").with({
            mount("/to")
                .with(
                    chain![
                        path!("/").to(endpoint::reply("")),
                        mount("/a").with({
                            path!("/") //
                                .to(endpoint::reply(""))
                                .modify(MockModifier {
                                    marker: marker.clone(),
                                    name: "M3",
                                })
                        })
                    ]
                    .modify(MockModifier {
                        marker: marker.clone(),
                        name: "M2",
                    }),
                )
                .modify(MockModifier {
                    marker: marker.clone(),
                    name: "M1",
                })
        })
    })?;
    let mut server = tsukuyomi_server::test::server(app)?;

    let _ = server.perform("/path/to")?;
    assert_eq!(*marker.lock().unwrap(), vec!["M2", "M1"]);

    marker.lock().unwrap().clear();
    let _ = server.perform("/path/to/a")?;
    assert_eq!(*marker.lock().unwrap(), vec!["M3", "M2", "M1"]);

    Ok(())
}