Rocket icon indicating copy to clipboard operation
Rocket copied to clipboard

Adding support for modifying fairings

Open the10thWiz opened this issue 3 years ago • 0 comments

I believe Rocket should provide support for modifying fairings during the ignite phase. This would enable, for example, an API for fairings to register template functions automatically. I'm working on a rocket-auth crate that provides convenient and secure authentication, and I would like the ability to register a template function that provides a pre-built login template, or the Sign in with Google button. This can't simply be a template macro, since at least the Google button requires some things like the API key in the HTML.

Why this feature can't or shouldn't live outside of Rocket

There are two parts to the feature described above, and only the first needs to live in Rocket's core. To provide a simple and flexible system, Rocket should likely only provide a mutable reference to previously registered fairings. The ability to add functions to the template engine should be implemented in rocket_dyn_templates. In this way, Fairings can define in what ways they can be modified, preventing unexpected interactions.

Ideal Solution

I think the ideal solution should look something like this. Since every other method on Rocket<Build> takes self, I think it's appropriate for modify_fairing to as well. This should also be quite reasonable to call from within an ignite fairing, since the return type works for it.

impl Rocket<Build> {
    pub fn modify_fairing<F: Fairing, E: Error>(self, f: Fn(&mut F) -> Result<(), E>) -> Result<Self, Self>;
}

There are a few issues to consider. First, Fairings are held as Box<dyn Fairing>, however this is actually pretty trivial since Fairings must implement Any. Second, it's possible there are multiple Fairings of a given type. In that case, I think it's best to simply run the function on each instance. If any instance fails (or there are none), modify_fairing should return Err.

Alternatives Considered

At the moment, something like this is kind of possible (at least for template functions), but it requires some somewhat ugly code in the main function. Ideally, the somewhat ugly code should be in the library providing the template, if it cannot be eliminated entirely.

the10thWiz avatar Jul 15 '22 19:07 the10thWiz