[HN Gopher] A small reivew of the Poem Rust web framework
___________________________________________________________________
A small reivew of the Poem Rust web framework
Author : rendaw
Score : 36 points
Date : 2022-09-11 16:06 UTC (6 hours ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| rendaw wrote:
| After wasting a couple days trying to wrangle Axum, Hyper, Rocket
| and a couple others I tried Poem and it solves every problem I
| had with the other frameworks. Waiting for the other shoe to
| drop.
|
| 1. The response object type isn't generic (as per project goals).
| In other frameworks, if I had branches returning different
| response types the types would conflict - no such issue here.
|
| 2. The cookie middleware is easy to use. In axum you had to
| return the cookie jar from your handler and trust the response
| tuple magic to do something with it to set the cookie in the
| response. I wasn't using tuples though, and due to the above it
| was non-obvious (and awkward) how to set the cookie in the
| response using response objects.
|
| 3. When you enable TLS via rustls it automatically makes non-
| default config changes to negotiate http2 (this is boilerplate in
| other frameworks).
|
| 4. Endpoint handlers are non-closures, and state must be shared
| via extensions/middleware (not captures). Rust closures are a
| hornet's nest so I'm plenty happy just being able to avoid them,
| but I also like that there's a single way to do things (and that
| way has good DX). In other frameworks you need to use async
| closures in order to get the compiler to intuit the future type
| since they're complex and you'd have to define it manually with a
| non-closure.
|
| 5. TLS configs are a stream to handle live cert refreshes.
|
| It feels like a batteries included/one size fits all solution,
| but it's very well integrated and there are a lot of batteries.
| It's pretty locked down, where you can't easily tweak the
| internals. I haven't hit limitations from that yet, despite
| having some somewhat weird use cases.
|
| There are also a lot of examples in the repo.
|
| I was fighting with other frameworks for the last 3 days (a good
| 20+ hours), and when I hit another future-handler-generic-
| incompatibility error I threw my hands up and tried Poem, and got
| my code compiling in 30m.
| 0x457 wrote:
| Can't talk about hyper and rocket, but I use Axum extensively.
|
| 1. This one is annoying, but easily solvable by making your own
| return type that implements IntoResponse
|
| 2. I'm not sure what you're talking about? You just add
| `Cookies` extractor to your handler and use that. You don't
| need to add it to the return, middleware takes care of it.
|
| Middleware in axum split into two: Tower middleware and Axum
| middleware. Tower middleware is...hard to write, but it's
| faster, axum middleware is easier to write, but it's slower.
|
| 4. axum doesn't force using closures, and state is shared via
| extensions?
|
| I'm currently working on a service where I have tonic (gRPC)
| and axum on the same port, and they share a lot of middleware.
| davidpdrsn wrote:
| > This one is annoying, but easily solvable by making your
| own return type that implements IntoResponse
|
| You can just call `.into_response()` like documented here htt
| ps://docs.rs/axum/latest/axum/response/index.html#returni...
|
| > I'm not sure what you're talking about? You just add
| `Cookies` extractor to your handler and use that. You don't
| need to add it to the return, middleware takes care of it.
|
| I think you're thinking of tower-cookies which works the same
| way poem's CookieJarManager does.
|
| axum-extra's cookies work differently in that you have to
| return the updated jar from handlers. We chose this design
| because it composes better when you have multiple libraries
| that all wanna set cookies. tower-cookies doesn't work if you
| accidentally add multiple cookie middleware, whereas axum-
| extra's approach does. So its a trade-off.
| 0x457 wrote:
| > I think you're thinking of tower-cookies which works the
| same way poem's CookieJarManager does.
|
| Yes, that's what I'm using.
|
| > You can just call `.into_response()` like documented here
| https://docs.rs/axum/latest/axum/response/index.html#return
| i...
|
| Oh yeah, totally forgot about that one.
| pdimitar wrote:
| Pretty useful to know, thanks for sharing. <3
|
| Shame you didn't try ActixWeb. That's the one I'd start with --
| I heard a lot of praise for it but haven't tried it yet.
|
| I'll make sure to check Poem next time I want to write a web
| service in Rust, thanks to you.
| capableweb wrote:
| > Shame you didn't try ActixWeb. That's the one I'd start
| with -- I heard a lot of praise for it but haven't tried it
| yet.
|
| actix_web is what I go for as well, really simple to setup
| and haven't hit any major blockers for as long as I've been
| using it (~7 months, 3-4 projects)
| electromech wrote:
| > The cookie middleware is easy to use. In axum...
|
| Been there, fought that! By the end, I had thoroughly abused
| the Axum API to get it working.
| electromech wrote:
| Ah shoot, poem's websocket implementation uses
| tokio_tungstenite like most of the other hyper-adjacent Rust
| web frameworks. It's unfortunate that library has become the
| default for websockets because the performance is rather
| lacking. (new allocations for each incoming message IIRC)
| paulgb wrote:
| Is there a good alternative in the tokio world currently?
| Actix-web does WebSockets but it expects to run on an actix
| executor AFAIK.
| the__alchemist wrote:
| Does anyone else think generics detract from the usefulness of
| Rust docs? I often hit walls on learning libs when trying to
| figure out what type to use when the API uses a generic. A non-
| generic flow might be like this: fn accepts param y. Param y is
| of type z. Docs for z shows it constructed with z::new(), or z
| { (fields }. When it's a generic instead, there's no link to
| click, and you're on your own to figure it out, possibly by
| browsing source code.
|
| This is exacerbated by the same libs using minimal examples
| that don't show the code used in a function, struct etc where
| explicit types are required.
| the__alchemist wrote:
| "unsafe forbidden" (GH tag)
|
| Is this practical for web programming? In the domains I'm used to
| (embedded and graphics programming), this isn't feasible. I
| recall some Actix drama re `unsafe` that this tag presumably
| alludes to. Perhaps web programming is abstract enough where this
| is a reasonable goal (?)
|
| Unrelated: What have y'all been using these minimal Rust web
| frameworks for? I've found them too sparse for websites, eg
| missing automatic DB migrations, auth, admin, email etc. On the
| plus side, Serde and Chrono are both things that apply to web
| programming and are (IMO) best-in-class.
|
| > Minimizing the use of generics.
|
| From the readme. Love this!
| lovingCranberry wrote:
| > "unsafe forbidden" (GH tag)
|
| Unrelated to this project, but I dislike the obsession of
| "unsafe" within the rust community.
|
| Sometimes I _need_ to dereference a raw pointer (rare!).
|
| Sometimes I actually _know_ what I 'm doing (very rare!!).
|
| Sometimes I rigorously tested my code (exceptionally rare!!!).
|
| When I see people making PRs (to e.g. Actix) to change unsafe
| code to safe code in an API the user *never* sees, which
| results in a performance penalty, just for the sake of not
| using the word "unsafe" in the code, I get mad. I totally
| understood Nikolay's reaction back then. Random people opened
| PRs and flamed him without knowing anything about the internals
| and the consequences.
|
| The unsafe keyword means that I know what I'm doing. Just trust
| me for once, please.
|
| Edit: if you actually want to know what you're doing too, I
| recommend you writing some linked lists. I hate linked lists
| with passion, I think they are a bad data structure and you
| should use Vectors 90% of the time and VecDeque the other 10%
| of cases. But they help you to understand what you're spending
| your electricity on.
| huimang wrote:
| What does it matter if a user never interacts with that API
| or not?
|
| Rust is focused around -safety- and performance. I would
| rather have a slight performance hit and safe code, rather
| than trusting some random person to 100% correctly write
| unsafe code. Which is why tools like cargo-audit and cargo-
| geiger exist. IIRC Nikolay didn't communicate well about
| -why- unsafe was used, and just closed PRs that converted
| unsafe code to safe code.
|
| > The unsafe keyword means that I know what I'm doing. Just
| trust me for once, please.
|
| No, it means you think you know what you're doing.
|
| It's more likely that you don't know what you're doing and/or
| are unnecessarily invoking unsafe for convenience, than the
| opposite. Theoretically I can look at your code and see if
| it's correct... or I could just use projects that don't use
| unsafe at all and save the time/headache.
|
| When it comes to web server frameworks and security, I would
| like to see as little unsafe usage as possible, and
| documentation as to exactly why it's needed. Which is why
| people switched to Warp/Tower and now Axum which forbids
| unsafe code entirely.
|
| If all I cared about were eking out all performance at the
| cost of safety, I wouldn't be using Rust in the first place.
| the__alchemist wrote:
| I think the different philosophies you see re `unsafe` may
| be due to 2 related use-case pairs that both come up here:
|
| #1: Low level vice applications programming. In the former,
| unsafe is a regular part of (at least certain layers) of
| code; ie you're working with memory (MMIO etc) as core
| operations, so will need `unsafe`. The situation gets
| ambiguous for things like peripheral typestates and owned
| singletons for register blocks etc; the line is blurred
| about what you're using the ownership model for, and what
| APIs should be marked as `unsafe`. For higher level uses
| like desktop programs and web servers, you may not need any
| `unsafe`.
|
| #2: Libraries vice programs This is directly related to
| your main point: If using someone else's code as a
| dependency, unsafe can be a liability if you don't know why
| it's is used. This is one aspect of the broader topic of
| whether you can/should trust any given dependency, and
| balancing not re-inventing wheels with learning library
| quirks, edge-cases, subtle bugs, complexity etc. A spin on
| this is making infrastructure specifically; I think Actix's
| creators and users may have had different opinions on this.
| CJefferson wrote:
| The problem is, do people know what they are doing?
|
| I didn't follow the whole Actix situation carefully, but here
| is a discussion where someone found of 15 ways to trigger
| undefined behaviour in safe code, caused by the unsafes in
| Actix:
|
| https://github.com/actix/actix-
| web/issues/289#issuecomment-3...
|
| Personally, I'd take halving the speed of my project to
| reduce the possibility of remote security holes. We live in a
| dangerous world nowadays, and we should take every chance to
| minimise the risk of serious security issues.
| brundolf wrote:
| It's all context-dependent. You're right that people
| shouldn't just drop into a project they don't understand and
| demand that all unsafes be factored out, but just because an
| unsafe block is internal and carefully vetted that doesn't
| mean it's totally fine and chill either.
|
| Here's a recent example where an unsafe led to a memory
| corruption vulnerability in a thoroughly battle-tested
| codebase: https://www.graplsecurity.com/post/attacking-
| firecracker
| 0x457 wrote:
| Most frameworks in rust a like Sinatra and Flask. There aren't
| any Rails level frameworks. I don't think there are any Rails
| level frameworks besides Django and a few JVM frameworks.
|
| Rust web frameworks just give you tools to get from request to
| response, the rest is up to you. I think that is fine, yeah it
| leads to some boilerplate to wire up a few libraries together,
| but you did it once, and you're done.
| brundolf wrote:
| Is the URL wrong? This says "a small review of" but it just links
| to Poem's GitHub repo
| homarp wrote:
| Another comment is the review:
| https://news.ycombinator.com/item?id=32800797
| bryanlarsen wrote:
| The author of poem is not a native English speaker so the
| documentation is not extensive. However, the examples in the repo
| are superb, so treat those as the primary documentation.
|
| He's also responsive to GitHub issues.
|
| I love the native openapi integration. Its also convenient to
| exercise your API ad hoc.
|
| Two thumbs up from me.
___________________________________________________________________
(page generated 2022-09-11 23:01 UTC)