11 ms·
Migrating from Warp to Axum
- jph 4y agoWarp/Rocket/Actix to Axum is a good improvement IMHO, especially because you get Hyper and Tower as well. I wrote an intro to these at https://github.com/joelparkerhenderson/demo-rust-axum https://github.com/joelparkerhenderson/demo-rust-axum
- newaccount2021 4y agoI'm using Axum now...its nice but still could use much more "batteries included" For example, I would like something like Go's Context for passing temporary per-request data through middlewares...maybe this is possible with Axum but I'm not seeing a straightforward approach Extensions also seem to be kinda magical and not straightforward Immature ergonomics are still a hallmark of many Rust libs
- jamincan 4y agoMaybe tower-request-id is an example of how to implement something like that? https://github.com/imbolc/tower-request-id https://github.com/imbolc/tower-request-id
- newaccount2021 4y agoThis is exactly what I am doing, but you shouldn't have to modify the request itself to pass temporary state
- fasterthanlime 4y agoEh, that's definitely a matter of taste. You definitely shouldn't have to pass an additional parameter everywhere you want context there's no absolutes here, just preferences.
- masklinn 4y agoWhy not? Given Rust's semantics it's really no different than how Go's Context seems to be used, just more efficient.
- fasterthanlime 4y agoRequest extensions (a feature of the `http` crate, not specifically hyper/warp/axum) are "just" a typemap, which is "just" a HashMap where keys are TypeIDs rather than strings. It's slightly less footgunny than something like Go's Context, although I still dislike it because checking for the presence of something happens at runtime only, so if you're messing with middleware composition, it's still too easy to accidentally get it wrong.
- masklinn 4y ago> For example, I would like something like Go's Context for passing temporary per-request data through middlewares...maybe this is possible with Axum but I'm not seeing a straightforward approach That's probably more of a Tower(-http) thing. It's the bit which handles all the middleware, Tower is layered over that. > Extensions also seem to be kinda magical and not straightforward Yeah, the problem is that they come directly from the http crates so everything that's built on top assumes you know what it is. The reality is that Extensions are just a typemap, meaning it's a k:v where keys are types. So you can define your own state type, shove it in the Extension, and know that you'll be able to retrieve that and there will be no collision (because it's your state type). For a more complete introduction, see https://blog.adamchalmers.com/what-are-extensions/ https://blog.adamchalmers.com/what-are-extensions/ It's one of those topic which is so obvious afterwards that it's easy to forget it's completely opaque and obscure beforewards.
- OtomotO 4y agoYup, working on that one too. I liked the API of warp a lot, it somehow reminded me of Akka http a bit. But all the points mentioned in the blog post resonate with me, which is why I've begun to migrate to axum.rs as well :)
- zemo 4y agoI have a handful of services, some in Warp and some in Rocket, and I dislike both of those frameworks. I've been looking into axum so this is a nice read. Honestly I don't think that Axum is right either. So for example, this: async fn create_user( Json(payload): Json<CreateUser>, ) -> impl IntoResponse { let user = User { id: 1337, username: payload.username, }; (StatusCode::CREATED, Json(user)) } For context, if you haven't checked out Axum, this is from the Axum docs. Rocket has a similar thing with its request guards, it has a similar json type that you put into the signature of a handler function and it automatically plucks the value from the body and parses it as json. What's weird to me is that it's coupling the request and response format to the logic. What if a client wants to post this as a form body? Write a separate endpoint? What if some old clients put the arguments in the query string? When I see this snippet as one of the intro examples for Axum, it feels like a red flag to me.
- Kinrany 4y agoA perfect API would consist of a few parts: 1. A request type and an associated response type 2. Impls for converting an HTTP request into the request type, and the reverse for response 3. A server type with an impl for handling the request 4. A client type with an impl for sending the request The remaining challenge is making all this ergonomic for the simple cases.
- xena 4y agoFun fact: you just described Go's net/http package.
- metadaemon 4y agoIt's also pretty much Express.js
- zemo 4y agonot really, point 2 isn't in the standard library.
- mdtusz 4y agoI've gone through the process of auditioning a bunch of rust webservers as well and came away with the opinion that of them all, Axum and Tide have the best interfaces and features. We went with tide, and I still believe that it is the _easiest_ to use in most cases - just with a few quirks that need to be changed and features added (or in some cases just be made public). Sadly however it is not very actively maintained and I fear for its future as that compounds with less and less people choosing it over time. Axum by comparison has a very active community, but I found it's request handling and middleware concepts much less ergonomic. If you're debating between rust webservers it's worth taking a look and giving tide a chance. The async-std choice hasn't been an issue for us at all either.
- metadaemon 4y agoYeah I think it's mostly a choice between Tokio and async-std. FWIW I chose Axum in a recent migration from Node. It's not perfect, but I found it to be pretty simple, even with controller/service/data abstractions.
- Serow225 4y agoI came to similar conclusions. Tide is IMO the most ergonomic, but its future is unclear in terms of community/maintenance. Its choice to use async-std ended up kind of biting it, since projects have by and large chosen tokio. I have hope for the eventual “swappable async runtimes” initiative, but it’s probably going to be too late to help in these regards.
- ibz 4y agoVery similar conclusions to what I got to. Just a couple of days ago I watched this video on YT - Designing Tide by Yoshua Wuyrts [1] and I really loved everything about tide. On the other hand, it seems that this guy was (is) sponsored by Microsoft for working on these things, which is a red flag. Not that I am against something sponsored by them, but having a framework maintained by pretty much a one person-team at Microsoft seems like it could end any time if some manager decides there is no budget for "Rust web research" anymore. But I have also asked myself - how mature is tide now, and how much development does it really need? I can't answer, since I have used it only very little, over the last days. I am curious if somebody else, more in the know, would explain. So the question really is - Could tide, as it is now, be considered mature enough such that it does not matter who maintains it (if even)? If so, then it might be the perfect framework. Anything extra could be developed as additional packages on top of it. Plus, it could always go through a revival (somebody else forking it and continuing to add features)? [1] - https://www.youtube.com/watch?v=laJA4QCjmxk https://www.youtube.com/watch?v=laJA4QCjmxk
- tipsytoad 4y agoNoob to rust, is there a reason to use if / if let over match statements or is it just a style preference?
- khuey 4y agoUsing "if let" is generally preferred style when there's only a single case that needs to be handled. (And I suspect that now that "if let ... else" is available that that will become the preferred style for handling two cases.)
- fasterthanlime 4y agoYeah, clippy will yell at you if you use a match with a single arm - I personally don't hate matches with a single arm, but I'd rather not fight clippy (ie. come up with my own clippy config, enforce it onto every project I maintain etc.)
- ratmice 4y agoI've hit this warning a few times where I expect to add additional match arms to be added in the future, always bugs me that clippy in that case steers you towards some change you know you'll end up undoing.
- pitaj 4y ago> And I suspect that now that "if let ... else" is available that that will become the preferred style for handling two cases. if let Pattern(binding) = thing { ... } else { ... } has been available for a long time. What was recently stabilized is let Pattern(binding) = thing else { ... }; which is syntax sugar for let binding = if let Pattern(binding) { binding } else { ... }; And facilitates easier unwrapping in early exit or default scenarios, without an extra level of indentation.
- kibwen 4y agoI respect the people behind Warp, but it always struck me as a design that actively worked against the grain of the language rather than a design that worked gracefully with the language. A bit too "functional" for what Rust really supports.
- sivakon 4y agoi really like elixir plug style API for http. trillium.rs comes very close but it’s not as popular.
- jgbyrne 4y agoI did the exact same thing with my imageboard, plainchant [1]. I had the same experience that you did with Warp: the routing model was extremely clever, but never came to feel intuitive or ergonomic to me. [1] https://github.com/jgbyrne/plainchant https://github.com/jgbyrne/plainchant
- masklinn 4y ago> Oh and that type never "gets bigger" in a way that would cause compile-time explosions. FWIW Axum did get hit by last year's "huge types" regression, the maintainer opted to bypass the issue by boxing routes internally: https://github.com/tokio-rs/axum/pull/404 https://github.com/tokio-rs/axum/pull/404 Which is not really surprising, as it's built on tower, which at the time Lime noted was affected: https://fasterthanli.me/articles/why-is-my-rust-build-so-slow#warp-i-trusted-you https://fasterthanli.me/articles/why-is-my-rust-build-so-slo... > ...I didn't actually trust warp that much. It's perfectly fine! It just.. has a tendency to make for very very long types, like the one we see above. Just like tower.
- fasterthanlime 4y agoFair, but if you were writing a web application on top of hyper directly, you probably wouldn't use one tower layer per route, which is somewhat equivalent to what warp does. When I wrote this I worked at a company where the main Rust codebase had, uh, perhaps too many tower layers.
- losvedir 4y ago> The axum::debug_handler macro is invaluable to debug type errors (there's some with axum too), like for example, accidentally having a non-Send type slip in. Heh, yeah. For my recent project where I explored implementing the same little app in a few different languages[0], I chose Axum for the rust version. The whole "extractor" system was pretty magical, and when I had this exact issue (non-Send argument), the compiler error was totally useless. I did see the docs about adding this extra macro crate for error messages but it seemed like a bit of a red flag that the framework was going against the grain of the language. Still, on the whole, I did enjoy working with Axum. [0] https://github.com/losvedir/transit-lang-cmp https://github.com/losvedir/transit-lang-cmp
- masklinn 4y ago> I did see the docs about adding this extra macro crate for error messages but it seemed like a bit of a red flag that the framework was going against the grain of the language. Is it really going against the grain of the language? Or really that Rust still has issues with error messages on complex / deep types and that should be reported / fixed? Because leveraging the type system seems to be pretty in-line with normal Rust ideals, and Send issues is a load-bearing type error of the concurrency system.
- rwaksmunski 4y agoI'm writing a toy image sharing webapp with Axum, $40/m server is able to process 200,000 dynamic requests per second. A bit more than nginx and a bit less than varnish serving static files on the same hardware. This whole Rust thing has some potential.
- java_expert_123 4y agoI'd like a single-threaded async pull-based http library
- fasterthanlime 4y agoI'm not sure what you mean by "pull-based", but you can make the whole thing single-threaded with `#[tokio::main(flavor = "current_thread")]` See https://docs.rs/tokio/latest/tokio/attr.main.html https://docs.rs/tokio/latest/tokio/attr.main.html
- rychco 4y agoCoincidentally, last night I started porting an actix-web project to Axum. In my very brief experience, I have found Axum (0.6.0-rc5) to be more ergonomic compared to actix-web. However, I haven't rewritten all the existing features yet so my opinion could change in a few days.
- deleted 4y ago[deleted]
- chromatin 4y agoReally glad to see this! More eyes on axum will make it better and better. We recently decided to move from Rocket to axum for non-user-facing service to support our platform. Haven't made the decision yet to move the main API, but strongly considering it. Rocket is really nice, and it's recent stall at 0.5-rc has been jump-started, but I feel that axum has much more momentum. Sergio (Benitez, of Rocket) is fantastic, but only one guy. OTOH, Axum is mostly the pet project of one person as well. If I had to pick analogies, I'd say Rocket is aiming to be more like Django and Axum more like Flask. The latter scope seems much more sustainable by a single person.
- jonathan_s 4y agoI've gone very recently through a rewrite from Rocket to Axum and very much love it so far. The initial motivation was the need for web socket support, which Rocket doesn't have (yet). But I love how simple it is, and also that it does not want to be the entry point of the application. (I like an http server that's a library that can be embedded at any place in the application.) Another great thing is the examples/ directory in the Axum repository. I had to use the latest version from GitHub though to get some of the features I needed, but maybe that's not the case anymore.
- ptx 4y agoNot about OS/2 Warp, apparently. I was imagining an OS/2 diehard user either migrating to some new version of ArcaOS or finally finding another worthy successor to the system.
- fasterthanlime 4y agoI'm afraid I'm a bit too young for OS/2 Warp, but I can write about Haiku OS in the future if that'd help?
- rob74 4y agoJudging by these comments, everyone is writing web apps in Rust these days. While I can understand the fascination that many HNers seem to have with Rust (been wanting to give it a try myself for some time now, but work and life always get in the way), I'm still not sure web apps are really a good fit for a language that has a reputation for being high performance, but more difficult than other languages commonly used for web development. I mean, you wouldn't build a web app in C/C++, and not only because of the potential security issues?
- satvikpendem 4y agoThere was a post just yesterday about this topic, for which I gave my (general) rebuttal: https://news.ycombinator.com/context?id=33714300 https://news.ycombinator.com/context?id=33714300
- chromatin 4y agoI previously wrote web applications in Python. My primary reason for moving was to capture the advantages of a strongly-typed language. I suppose Go would have been another reasonable choice in this regard.
- LAC-Tech 4y agoI always thought Actix-Web was the tried & true rust web framework. I'd vaguely heard of Warp and never heard of Axum. What's behind this sudden explosion of them? Are they all skins over the same core libs or what?
- dralley 4y ago>I always thought Actix-Web was the tried & true rust web framework. That is mostly still true, but Axum is developed under the same organization as Tokio and integrates very well with that ecosystem, including Tower middleware. So in that sense it has a feeling of being "official" insofar as such a thing exists. The community is big enough for it to not die if the maintainer were to disappear tomorrow. It's also a pretty nice framework and has better compile times than Actix-web. It is less an explosion of frameworks so much as a consolidation, if anything. Axum and Actix are the de-facto frontrunners.
- LAC-Tech 4y agoThanks - that gives me a nice overview of what's going on. Will check out Axum the thing i was excited about actix-web (Actors) is apparently not part of it anymore anyway.
- satvikpendem 4y agoAs someone that uses actix-web, what are the pros and cons of moving to Axum? I hear about it a lot these day. I know it integrates into the Tokio ecosystem well, including Tower, but I'm not sure what that concretely means for someone already using actix-web. When would I use Tower?
- telios 4y agoI created my own web framework (<https://docs.rs/under/latest/under/ https://docs.rs/under/latest/under/>) to address some of my own perceived issues with a lot of current rust web frameworks - typing issues being one of them. Personally, I don't like the idea of endpoints requiring `#[handler]` or other "magic" derives, or guards - I wanted something with an endpoint that takes a request, and returns a result with a response. I'm still working on it, though.