xesite/blog/site-update-axum-2022-03-21...

82 lines
5.2 KiB
Markdown

---
title: "Site Update: Axum"
date: 2022-03-21
---
I have made a bunch of huge changes to my website that hopefully you won't
notice unless you read this post that points them out to you. I have redone how
the website's URL routing works to use
[axum](https://tokio.rs/blog/2021-07-announcing-axum) instead of
[warp](https://docs.rs/warp/latest/warp/).
I chose warp fairly arbitrarily when I was getting into the swing of Rust. This
choice turned out to be a bit of a mistake. Don't get me wrong, warp is a
fantastic framework, but overall I've not been happy with how it impacts compile
times. Warp works by pushing a lot of the complexities with HTTP routing into
the type system. This can lead to undebuggable inscruitable types that make it
really hard to understand what is wrong. Here is the autogenerated type for the
`/blog/:name` route:
```
warp::filter::and::And<warp::filter::and::And<impl warp::filter::FilterBase<Extract = (), Error = Infallible> + warp::Filter + std::marker::Copy, Exact<warp::path::internal::Opaque<main::{closure#0}::__StaticPath>>>, warp::filter::and_then::AndThen<warp::filter::and::And<warp::filter::and::And<warp::filter::and::And<warp::filter::and::And<impl warp::filter::FilterBase<Extract = (), Error = Infallible> + warp::Filter + std::marker::Copy, impl warp::filter::FilterBase<Extract = (std::string::String,), Error = Rejection> + warp::Filter + std::marker::Copy>, impl warp::filter::FilterBase<Extract = (), Error = Rejection> + warp::Filter + std::marker::Copy>, impl warp::filter::FilterBase<Extract = (Arc<app::State>,), Error = Infallible> + warp::Filter + Clone>, impl warp::filter::FilterBase<Extract = (), Error = Rejection> + warp::Filter + std::marker::Copy>, fn(std::string::String, Arc<app::State>) -> impl warp::Future<Output = Result<Opaque(DefId(0:1249 ~ xesite[3495]::handlers::blog::post_view::{opaque#0}::{opaque#0}), []), Rejection>> {blog::post_view}>>
```
[What the heck is that? Is that a binary tree?](conversation://Numa/delet)
[Yep. It's insufferable to try and debug too.](conversation://Cadey/coffee)
Yeah, it's really hard to understand what's going on in error messages because
of this. This also means that the routes are put into a binary tree in the type
system, which means if your tree is unbalanced then you get slower compile times
and a slight hit at runtime as the framework traverses your binary tree to
figure out what to do. This has also made it difficult for me to add features
such as [historical views of my RSS feed](https://github.com/Xe/site/issues/419)
or other things I want to add like the April Fools day feature I've been working
on.
When I went out framework shopping, I tried a few things and got reccomendations
from a trusted friend before I finally settled on axum as the heart of this
website. Axum has a few major advantages that brought me "in the door":
- It's maintained by the tokio team
- It leverages the type system of Rust to make writing handlers easier
- It uses extractors (think lenses) to help you pick out the subset of data you
need, not blindly giving you everything and hoping you figure it out
- It has sub-routers which can have different middleware stacks than the main
one (useful for things like API authentication)
And it has these disadvantages:
- Writing middleware is kinda weird (though this may be because I'm not used to
working with tower), but easy once you get the general flow of things
- I can't find a way to have the template data get continuously piped to client
connections instead of rendering it to a buffer and then writing that buffer
to the client
- It doesn't have the biggest mindshare and one of the best ways to get unstuck
at the time of writing this article is to ask on their Discord server
Overall, I've been happy with the experience of porting over my site to using
Axum. I did [a stream on Twitch](https://www.twitch.tv/videos/1429533858) where
I ported it all over if you want to watch the process and hear my thought
processes as I was figuring things out.
As users, nothing should have changed about this site. However I'm almost
certain that I did forget to port _something_ over, so if I missed something you
rely on, [get in contact](/contact). I have not gotten the Patreon API
interoperability code fixed yet, so that is the next major issue. I am going to
figure out how refresh tokens work the hard way and make the patrons page
auto-updating instead of having to [manually get a new API key every
month](https://github.com/Xe/site/blob/main/docs/patron-page.org). I am also
looking into having that patrons page be updated by a cronjob that emits json to
the disk and have my site load from that instead of just hoping that the patreon
API credentials are up to date. We'll see how that goes, but you can track that
[here](https://github.com/Xe/site/issues/442). I will likely do a livestream for
this.
I have also contacted a copyeditor for my blog. I am so happy with the results
so far. [My Devops post](/blog/social-quandry-devops-2022-03-17) was the first
thing that the editor reviewed and they absolutely tore my first draft in half
and helped me put the parts back together into something more palateable. I am
beyond satisfied with this and will continue to use this editor in the future. I
wish I had gotten a copyeditor sooner.