Skip to content

Making plugins for Octane

weegee edited this page Nov 1, 2020 · 1 revision

Making plugins for Octane

While Octane allows you access to raw body, headers, etc, you can architect your plugin to integrate seamlessly with octane. For example

let app = Octane::new();
app.get("/", YourPlugin::handle(|req, res| {
 // access to your plugins custom req and res here
 Flow::Next
}))?;

For tutorial purposes, let's make a Cookie handler which will be just a mere wrapper over the cookie crate. We start by making a new lib

cargo new --lib octane-cookies

We will now make a new Request structure, its a cookie middleware, it won't need to do anything to the response so we'll leave it that way.

#[derive(Debug)]
pub struct CookieReq<'a> {
    /// The original octane request we get from the client
    pub request: &'a Request<'a>,
    /// The cookies
    pub data: CookieJar,
}

Note: It is extremely important to keep the original request in there, you can also derive deref to request to make it more seamless but that's not needed.

Now we perform actual cookie parsing using the Cookie crate. We write 2 functions and one method

impl<'a> CookieReq<'a> {
    pub fn parse(req: &'a Request) -> Self {
        let mut jar = CookieJar::new();
        if let Some(key_value) = Self::get_cookies(req) {
            for cookie in key_value.split("; ") {
                if let Ok(x) = Cookie::parse(cookie) {
                    jar.add(x.into_owned())
                }
            }
        }
        Self {
            request: req,
            data: jar,
        }
    }
    pub fn get(&self, name: &str) -> Option<&Cookie> {
        self.data.get(name)
    }
    pub fn handle<T>(closure: T) -> Closure
    where
        T: Fn(CookieReq, &mut Response) -> Flow + Send + Sync + 'static,
    {
        route_next!(|req, res| closure(CookieReq::parse(req), res))
    }
}

Notice the signature of handle there, its similar to what the methods in the Route trait takes in. Now we can

let app = Octane::new();
app.get("/", CookieReq::handle(|req, res| {
 let cookie = req.get("cookie");
 Flow::Next
}))?;

But what if you want to have best of any two of the plugins you are using? That's why the parse method above is pub but unfortunately, we won't get to have that syntax above now.

let app = Octane::new();
app.get("/", CookieReq::handle(|req, res| {
 let cookie = req.get("cookie");
 let second_middleware = YourPlugin::parse(req.request);
 Flow::Next
}))?;
Clone this wiki locally