#axum — Public Fediverse posts
Live and recent posts from across the Fediverse tagged #axum, aggregated by home.social.
-
So I have read some more about the whole #dioxus vs #tauri plus #leptos plus #axum for a #rust #rustlang #desktop app.
From what I read by now, I would say that I will try the tauri route next. I would still prefer if Dioxus would just work, but what makes me wary about whether Dioxus would be a sustainable choice is that there's a lot of issues in the Dioxus repository that do not even have a reply by a maintainer. My own issues (which are relatively young!) have only little interaction. I get that this is an open source project and maintainer overload and so on, sure. But there's also something about Dioxus being funded? So there are full-time devs (plural!) working on it? What can I say? This makes me wary.
Going down that tauri route would mean that I would need to build the whole thing myself. That could work, but is more than I would have liked to do. I want to develop my app functionality, not set up a GUI development environment.
I could also go for a TUI first, but tbh, I would rather like to have a GUI first, with a clean API that I can then reuse to build a TUI on top of it. Not sure why, the other way around would probably work as well 🤔.
Either way, I would then try leptos as framework for the app, because it looks rather good from what I can read from its documentation, and I can use axum in the backend, which I think fits my needs as well. (Btw developing this with ratatui with a axum backend would also be possible, but that's not the "native way" for a ratatui app, but much more for a leptos app as I understand it, so I expect less headaches here).
I hope I can get a MVP fast, so I can get back to developing my core application stuff, because there's sooo much missing still.
-
It looks like #axum is finally going to get proper route matching with prefixes and suffixes support (e.g. `/images/{foo}.jpg`, while before only `/images/{foo}` was supported).
https://github.com/tokio-rs/axum/pull/3702 -
@pointlessone @rayk @tomekw I'm afraid you have biased view. There are two angles to the "web frameworks".
1. #Axum and #Rails don't even play the same sport, the former's performace comes at cost of orders of magnitude more complex implementation; it was never intended to be #Django in #Rust
2. The fact we have web frameworks in Rust is "an accident", the language was never intended to specifically write ones. Rust is a proper system programming language, the same class as C (not #Go w/GC).
-
Built a full-stack Rust web app entirely with Claude Code. Claude wrote all the code, I just directed the features, architecture and tech.
Stack:
- Axum with async-graphql API
- Dioxus WASM frontend
- ReDB databaseIt's an artillery calculator for the game Foxhole — place markers on maps, get firing solutions with wind compensation.
Feel free to check it out: https://arty.dp42.dev
Source code on my github#Rust #WASM #Dioxus #Axum #AI #ClaudeCode #OpenSource #GameDev
-
* looks at the repo of a rust template
* clicks at the maintainers name
* clicks a link on his profilesHuh? "Coaching for your Daddy Phase"?
-
[Перевод] Гексагональная архитектура в Rust: отвязываем бизнес-логику от Solana
Представьте: вы строите сервис выдачи дипломов на Solana. Всё отлично, пока дело не доходит до тестов. Внезапно оказывается, что для проверки бизнес-логики нужно поднимать валидатор, искать тестовые токены и молиться на стабильность сети. Знакомая боль? В этой статье я покажу, как мы решили проблему, используя async-trait и dyn Trait. Мы превратили интеграционные тесты длиной в минуты в юнит-тесты, которые проходят за миллисекунды. Узнать решение
https://habr.com/ru/articles/983874/
#rust #solana #гексагональная_архитектура #блокчейн #unittesting #dependency_injection #axum #web3 #mocking #refactoring
-
A bonus entry: error handling.
This is more of a Rust thing, not specific to Axum. So Rust has no exceptions. Instead rust has a Result type that can be either a "good" return value or an "error”.
My fellow Rubyists probably know of this concept from other languages or maybe you’ve encountered Railway-Oriented Programming pattern (it resurfaces once in a while, here's a recent one: https://www.alchemists.io/articles/railway_pattern ).
Anyway, one quirk is that since it's just a normal value, it doesn't have a backtrace attached to it. It can bubble up all the way to the
mainfunction and you wouldn't be any wiser where it came from.Another “inconvenience” is that
Result<T, E>is generic but it also means that every concrete variant of both parameter types yields a completely separate type. There's no inheritance, you have to specifically address every instance of the Result type. Where in Ruby you can handle all exceptions by catching StandardError, you can't do that in Rust.The idiomatic solution is to have your own error type that wraps other error types and implement conversion from those error types to your own error type.
There are a few crates (packages, like gems) that try to address various aspects of this. I settled on rootcause which sorts out the backtrace deficiency. It allows for even more reach contexts attached to the errors. This is even better than in Ruby. It's always obvious in Rust where you can potentially get an error so it’s easy to provide relevant context.
However it only partially addresses the multitude of errors issue. I still had to implement my own error type to wrap around rootcause's Report because Rust doesn't allow to implement external traits (like Axum's IntoResponse) for external types (like, rootcause's Report). So in order for my handlers to be able to return proper Results that Axum could turn into responses I have to have this intermediate glue type.
But it let me have error pages with backtraces like in Rails, which is neat. But again, it's not a built-in feature, it's something I had to build myself.
I suspect there's nothing like errbit/sentry/rollbar. What do people use to catch failures in production? Anything for monitoring, metrics?
-
OK, that's a wrap for now.
My current impression is that Rust is decades behind Ruby in terms of developer experience. There are some neat ideas, some features that are only possible because of Rust's type system, performance is definitely incomparable. But the things that are called a framework in Rust would never be called that in Ruby. Rust can not be compared to Ruby in terms of development speed.
I can not stress that enough. What's done in Rails with a scaffold and a few lines of code took me like a solid week and I'm still nowhere near the end of it. Yes, I have to learn a lot. But I have to learn a lot precisely because basics are not covered in the docs and I can't copy-paste pieces to have the same (or analogous) thing as in Rails.
It's rather the basics are different. In Rails basics are CRUD. In Rust basics are how to run a router on top of a socket. A form to update a record in the db is an advanced topic in Rust web development. Unfortunately.
-
Oh, right, almost forgot. Axum provides router but doesn't provide anything to generate URLs. And as far as I can tell, it's on purpose.
In rails you get named routes and helpers to generate URLs for them. It a little thing but it helps a lot when you change the URL but keep the name. You don't have to go through the whole app and change it everywhere but you still get the new URLs.
In Axum it’s all just strings. You have to make sure you remember every place you have that URL and you’ll have to fix it manually.
TBH, I'm baffled by this. Everywhere else everything has to be its own type and types have to be coherent. But here it's completely detached and suddenly stringly typed.
-
At this point I’m nearly at my wits end trying to build a form for a record that has multiple associated records.
I haven't yet touched assets. I've seen solutions to embed assets into the compiled binary, which is neat. I like that the whole app can be deployed in a single file. I suspect the build for those assets has to be external.
I also haven't touched background jobs. As far as I can tell there's nothing like Sidekiq for Rust. Though maybe there's something decent. I haven’t looked yet
-
BTW, remember forms? Those have to be separate structs, too.
Where in Rails you’d have
Post.find(id).update(params)you'd have three different structs in Rust: one for the form, one for the partial update, and one for the returned post.So in addition to those multiple “query” structs, you also may get multiple input structs (for each different form, for each schema in the API, etc.). And you have to com up with conversions between those for everything to work.
-
Axum also doesn't provide any DB layer. You’ll have to bring your own. (Notice the theme?)
I’ve chosen Diesel.
At the surface it's kinda similar to ActiveRecord. You see familiar terms like migrations and associations. But in reality it's very far from AR.
Again, I'm not exactly a fan of ActiveRecord but in comparison experience working with it is all sparkly unicorns and rainbows.
Let's take migrations, for example. Migrations in Diesel are raw SQL. Which is fine is you're forking on an app that will only use a single db (like your typical startup or something will settle on, say, Postgres for the main db). It’s much more awkward when you're working on an app that people might want to deploy in different environments. Like a self-hosted app that can have 1-2 users might want to use SQLite for simplicity, and same app can be used for a company of 300 and might be better served by pg (for reliability, concurrency, backups, etc.). With Diesel you’d have to write migrations for every supported db backend. In Rails you use a simple API that abstracts that away for the most part. You still can use very specific db-dependent feature, in the same migration.
Diesel provides an option to generate migrations from a schema definition. I think it's neat. You write the schema you need and Diesel would figure out what needs to be changed and puts that in a migration. The issue is that the DSL is extremely limited. You can't even define indexes with it.
Relations in Diesel are very limited as well. It's very basic “get associated records”. Transitive associations are very awkward compared to AR.
Anther snag is in Rust everything is a type. On one hand Diesel ensures that db is in the right state to work with the types in your code. So you can be sure there won't be some weird miscommunication between the app and the db that will lose your data. On the other, you can't be loose with your requests. In Rails you can requests partial rows and you still get the same models. So you can optimise your queries much easier (but you have to be careful). In Diesel every shape of the returned row has to be a specific type. You can't randomly add or remove columns from the query.
So what’s conceptually a single model in AR can be a whole bunch of structs in Diesel. And you have to pay attention where you use which.
-
BTW, there's no form builder in Axum.
I’m not very fond of Rails form builder. It's bloated. It hides a lot of HTML features. But if you need a basic form it's just magical.
Axum also can only parse flat forms. By flat I mean, that only one level of struct nesting. Nothing like nested attributes in Axum. You have to bring your own crate for that.
-
Since we're talking about responses let’s address the elephant in the room: HTML.
In Ruby pretty much every framework support some form of templating. Even barebones Sinatra gives you ERB out of the box and pretty much any other template engine is only one line in the gemfile away.
Axum doesn't provide any templating. You’ll have to bring your own.
I picked #Askama as it was the first templating engine on Are We Web Yet.
It's a dialect of Jinja. But maybe not 100% compatible. No matter.
One thing you learn fast is that in Rust everything is a type. So your template has to have an actual template and a struct that provides data for the template. You can't just put random code in your templates. On one hand it’s great as you can't by accident have n+1 queries in your template. On the other, to change something on the page you might to edit three files: the actual template, the struct for the template, and the handler to populate the struct.
There's no support for layouts. Well, there's kinda. Through template inheritance. It’s where you extend your layout by overriding some blocks in it. It's much more awkward than in Ruby. In Ruby layouts are conceptually separate. In Askama your template struct has to provide all the data for the template and all its parent templates. I don't even know if it's possible to render the same template in different layouts. The thing that is extremely easy in Ruby.
There's also no support for partials. At best you can insert renders of other templates. But that's awkward for many of the same reasons (mostly around providing data for the templates).
One major downside is that Askama uses proc macro to compile the templates to Rust. It makes it extremely fast but debugging templates is a nightmare. It gives you an error that something is missing or has a wrong type but doesn't tell you what it is or where in the template it is. Even with enabled proc macro backtraces it gives you a snippet of generated Rust code and not the template. Even the barebones ERB will give you the exact position in the template in case of an error.
So yeah, lots of frustration.
-
Now, that was request. For responses it's basically the same, in a way. Your handled has to return something that can be converted into a response. It’s literally
impl IntoResponse.Axum provides implementations for a few things like tuples of relevant pieces of information. You can return a bag or response pieces and it will glue them together into a proper thing.
It can be a redirect, or a status code and HTML string (
HTML(“my html”), or a JSON string (JSON(serialized_json)). You can add headers in there. It can be aResultso you can propagate errors around.It's very neat when it clicks but it's very hard to find out what actual types have that trait implemented for. So you have to gerp examples and dive deep in to the framework code to see if the trait is implemented for what you want to return or you have to come up with your own type and implement the trait for it.
It's not a good learning experience.
-
I had to start with something. I picked #Axum. It’s one of the most popular frameworks and it's actively developed. So good enough for start.
First I have to address the “framework” here. IT terms of scope Axum is closer to Sinatra than Rails. And closer from the opposite side. It's somewhere between Rack and Sinatra.
The central part of Axum is the router and API for request-response mapping into types.
So in Ruby pretty much every web framework has some sort of Request and Response objects. They completely encapsulate both concepts and you have to stick your fingers deep into Request object to get anything you may want.
You still can do that in Axum but generally your “actions” (in Rails terminology) are just functions. And arguments to those functions pieces of the request that you need to process the request. It can be a piece of the request path (like your post id from /posts/42), or cookies, or any specific header, or parsed json request body, or form data, etc. So where in Rails you get
request(or at bestsparams) in Axum you get very specific and typed pieces of information.Your handler may look like this:
fn create_post(Form(post_form): Form<PostForm>, cookies: CookieJar) -> Result<(), StatusCode> {
//…
}Now, Rails docs are great. Specifically the Guides. You can learn every piece of Rails from them. There are no guides for Axum. There are API docs. They're very different to Rails docs. It will take some time learning to read the docs. But the main learning material seems to be examples. Examples are indispensable. But they're sort of terrible to learn all the possible types the handler function can take.
I had to actually go and lear the magic that makes this typed handlers witchcraft work to understand what I can plug in there. (It's explicit type coercion and a little macro.) I'm glad I understand it now but I have to point out that I spend much longer trying to figure that out reading the docs and still didn't until I read the code. It's not a good learning experience.
-
Rust unit testing: basic HTTP testing
Real-world application testing - Beginning with Axum
🦀 https://jorgeortiz.dev/posts/rust_unit_testing_basic_http_srvr/
#rust #rustlang #axum #http #testing #dev #web #realworld #beginner #srv #learnrust #beginnerfriendly #webdev #apptesting
-
Rust unit testing: basic HTTP testing
Real-world application testing - Beginning with Axum
🦀 https://jorgeortiz.dev/posts/rust_unit_testing_basic_http_srvr/
#rust #rustlang #axum #http #testing #dev #web #realworld #beginner #srv #learnrust #beginnerfriendly #webdev #apptesting
-
Rust unit testing: basic HTTP testing
Real-world application testing - Beginning with Axum
🦀 https://jorgeortiz.dev/posts/rust_unit_testing_basic_http_srvr/
#rust #rustlang #axum #http #testing #dev #web #realworld #beginner #srv #learnrust #beginnerfriendly #webdev #apptesting
-
Rust unit testing: basic HTTP testing
Real-world application testing - Beginning with Axum
🦀 https://jorgeortiz.dev/posts/rust_unit_testing_basic_http_srvr/
#rust #rustlang #axum #http #testing #dev #web #realworld #beginner #srv #learnrust #beginnerfriendly #webdev #apptesting
-
Rust unit testing: basic HTTP testing
Real-world application testing - Beginning with Axum
🦀 https://jorgeortiz.dev/posts/rust_unit_testing_basic_http_srvr/
#rust #rustlang #axum #http #testing #dev #web #realworld #beginner #srv #learnrust #beginnerfriendly #webdev #apptesting
-
When debugging an #axum handler in the context of a failing test. Is there a quick way to print the body of the response? The following is a mouthful
```rust
let err = String::from_utf8(
axum::body::to_bytes(res.into_body(), usize::MAX).await.unwrap().to_vec(),
);
println!("==> body {:?}", err);
``` -
End of an era for my last legacy project: just finished migrating it from Rocket to Axum.
I still love Rocket's DX, but with the long-term maintenance silence, it was time to move to the more active tokio_rs ecosystem. Axum feels solid, but I'll miss Rocket.
-
NEW BLOG POST!
In this article soberly entitled "The world's most interesting contact form", we'll learn about OpenPGP, what it is and how it works, then use OpenPGPjs, a Javascript implementation of it to send an end-to-end encrypted email, with the help of a little Rust Axum backend.
The second part of the article talks about Proton Mail, their promises, what they entail, and how we can verify them. At the very end, there's also a quick word about the Chat Control, the EU's latest mass surveillance project.
Check it out! https://zoug.fr/world-most-interesting-contact-form/
#openpgp #pgp #openpgpjs #rust #axum #chatcontrol #proton #protonmail #e2ee #encryption #privacy
-
RE: https://hachyderm.io/@conjured_ink/115572573996228576
Hey so you wanna work on a cool Rust project? Like an actual webapp that's seriously taking advantage of Rust's abilities not to scale up, but to scale DOWN?
-
First rough prerelease of @conjured_ink 's eshop software is up on codeberg: https://codeberg.org/conjured/silverfish/releases/tag/v0.0.1
It's so tiny. That's the whole binary. There's no external dependencies. There's only a single binary in it, and it has both the database and the job queue software embedded right in it.
For folks familiar with hosting mastodon: Imagine if that was literally your hosting experience, and the entire thing barely used 80mb to serve thousands of requests per second on a single-core vm. No need to set up and manage mysql, or sidekiq. You just run the executable.
Silverfish (what we're calling this tiny thing) is still in very early stages and only really has a CMS with custom theming support so far, but new features are rapidly being added, and the guts of the thing are really featureful, with light/dark theme support, i18n, and a literal 1kb JS bundle where the entire admin interface works with JS completely disabled and is still super snappy.
I'm very excited
#ConjuredInk #IndieWeb #SmallWeb #ECommerce #Rust #RustLang #Axum
-
Architecting and building medium-sized web services in Rust with Axum, SQLx and PostgreSQL: https://kerkour.com/rust-web-services-axum-sqlx-postgresql
-
I've been playing with #RustLang again.
Using #Axum #Handlebars #Htmx #Sqlx and #Sqlite
It's a really joyful environment to work with. I'm finding it far easier than last time, a combination of much improved compiler errors, clippy guidance, #VSCode also seems to have improved understanding of the code (I'm not using #AI just Rust-Analyser and Even Better TOML
Plus I'm building depth rather than width, fits much better for exploration and learning.
The amount of syntax feels much reduced :-) -
Form data (x-www-form-urlencoded) support in #Axum is a bit disappointing. It uses #serde’s serde_urlencoded underneath, which in principle is fine. But the problem is that HTML forms don’t let you *not send* a value, which makes the whole thing useless with optional fields. You can set a field in a form to not be required and send an empty value (`?foo&bar=3&…` or `?foo=&bar=3&…` for empty `foo`) but then serde treats it as a present empty string and fails deserialization.
-
#StandingStoneSunday #Stelae #Obelisks
#Panoramio #PhotoShare Richard Lozin https://web.archive.org/web/20161018011259/http://www.panoramio.com/photo/49503411
#Geolocation 14.132, 38.7194 #Axum #Ethiopia #Archaeology
Copied the #Panoramio number when saving the photo, searched the #WayBackMachine for http://www.panoramio.com/photo/49503411. Same URL for every Panoramio photo, just change the numbers to match other photos. The 2016 cache was just before Google closed down Panoramio.com. Massive #geolocated #archaeology photo base. -
#StandingStoneSunday #Stelae #Obelisks
#Panoramio #PhotoShare Richard Lozin https://web.archive.org/web/20161018011259/http://www.panoramio.com/photo/49503411
#Geolocation 14.132, 38.7194 #Axum #Ethiopia #Archaeology
Copied the #Panoramio number when saving the photo, searched the #WayBackMachine for http://www.panoramio.com/photo/49503411. Same URL for every Panoramio photo, just change the numbers to match other photos. The 2016 cache was just before Google closed down Panoramio.com. Massive #geolocated #archaeology photo base. -
#StandingStoneSunday #Stelae #Obelisks
#Panoramio #PhotoShare Richard Lozin https://web.archive.org/web/20161018011259/http://www.panoramio.com/photo/49503411
#Geolocation 14.132, 38.7194 #Axum #Ethiopia #Archaeology
Copied the #Panoramio number when saving the photo, searched the #WayBackMachine for http://www.panoramio.com/photo/49503411. Same URL for every Panoramio photo, just change the numbers to match other photos. The 2016 cache was just before Google closed down Panoramio.com. Massive #geolocated #archaeology photo base. -
#StandingStoneSunday #Stelae #Obelisks
#Panoramio #PhotoShare Richard Lozin https://web.archive.org/web/20161018011259/http://www.panoramio.com/photo/49503411
#Geolocation 14.132, 38.7194 #Axum #Ethiopia #Archaeology
Copied the #Panoramio number when saving the photo, searched the #WayBackMachine for http://www.panoramio.com/photo/49503411. Same URL for every Panoramio photo, just change the numbers to match other photos. The 2016 cache was just before Google closed down Panoramio.com. Massive #geolocated #archaeology photo base. -
#StandingStoneSunday #Stelae #Obelisks
#Panoramio #PhotoShare Richard Lozin https://web.archive.org/web/20161018011301/http://www.panoramio.com/photo/49503414
#Geolocation 14.132, 38.7194 #Axum #Ethiopia #Archaeology
#GoogleEarth #Photo layer, my frequent window to the whole world, leads to great archaeology site photographers by navigating the #WebArchive 2016 cached pages. https://archive.org/web/ -
#StandingStoneSunday #Stelae #Obelisks
#Panoramio #PhotoShare Richard Lozin https://web.archive.org/web/20161018011301/http://www.panoramio.com/photo/49503414
#Geolocation 14.132, 38.7194 #Axum #Ethiopia #Archaeology
#GoogleEarth #Photo layer, my frequent window to the whole world, leads to great archaeology site photographers by navigating the #WebArchive 2016 cached pages. https://archive.org/web/ -
Been playing a lot with #SurrealDB on #RustLang with #Axum and #Handlebars_rs
My #PrayerOfHannah app on #CodeBerg at https://codeberg.org/Dave42W/PrayerOfHannah now has working #CRUD for SongBooks and Authors using the embedded file db engine which is #RocksDB under the covers.
Starting to get to a more productive place. -
A little #RustLang update.
1. I'm now Dave42W on GitHub to match everywhere else.
2. My learning project "daves-dashboard" is at https://github.com/dave42w/daves_dashboard
3. I've started an #Axum branch for the web framework
4. I'll be using #Handlebars_rs for templating (it works with Rust inside the browser too)
5. Some cool new #VSCode extensions #Crates #Better_TOML #Error_Lens #Thunder_Client should help with #Rust complexities
6. I want to look at #YEW for the client end in the future