5 ms·
no that's ... a pretty extreme misreading of what I'm saying. I'm not saying "I don't want any abstraction", I'm saying "I don't think this abstraction is a ver
by zemo 4y ago
no that's ... a pretty extreme misreading of what I'm saying. I'm not saying "I don't want any abstraction", I'm saying "I don't think this abstraction is a very good one, I think it has problems, and I don't think I would rewrite my existing services to use this framework as a result". Here, I'll provide two high-level alternatives.
Here's some pseudo-code of an endpoint that can accept json or form data as an alternative to the Json<T> abstraction that Rocket and Axum both currently utilize:
async fn handler(thing: Thing) {
// the Thing is read from the request by a request decoder.
// The request decoder is chosen from a set of available
// request decoders based on the Content-Type header.
}
let mut app = App::new();
app.register_decoder(jsonDecoder);
app.register_decoder(formDecoder);
app.post("/thing", handler);
app.run()
> You rejected ancestor's suggestion of using Request<Body>... which is exactly what is provided by Go.
That's not really accurate. net/http provides an abstraction that has survived for a decade that has been leveraged by a lot of tools to make middleware interchangeable. For example, gorilla/mux uses the net/http standard, that has worked great for me for like 8 years running (unfortunately, that project lost its maintainer). The argument I'm making is that not all abstractions are equally good; Json<T> is an example of an abstraction that is used in Rocket that I have found to be cumbersome and Axum is repeating that abstraction. It's one of the very first examples in their docs. Why couple handler logic to request encoding? I think that abstraction is wrong, I don't think it will withstand the test of time, and in another year or two, will be back at it, updating our Axum services to use [some new thing].
So instead of the core abstraction being "every endpoint accepts whatever type it wants", the core abstraction could be "every endpoint accepts one value of the same type":
async fn handler(req: Request<Body>) {
// req.decoder looks at the content-type header and
// picks from a list of registered decoders. If
// the client picks an unsupported decoder it fails.
let dec = req.decoder()?;
let thing = dec.parse::<Thing>()?;
}
let mut app = App::new();
app.register_decoder(jsonDecoder);
app.register_decoder(formDecoder);
app.post("/thing", handler);
app.run()
So a really cool, useful, powerful, and general abstraction that I love in Rust is the string parse method: https://doc.rust-lang.org/std/string/struct.String.html#method.parse https://doc.rust-lang.org/std/string/struct.String.html#meth...
I honestly would rather have that for HTTP requests than making an assumption about the content encoding in the handler's signature.
> (Well, you didn't really respond to the content of my comment at all, but nevermind.)
I mean my argument is "a thing that is trivially expressible and easy to do in other stacks has poor ergonomics in this framework" and your response is basically "ok so take the product of all of your endpoints and all of your encodings, ez pz", which ... is also not ergonomic? Literally the opening prompt was me saying I think that coupling the encoding to the endpoint's logic means you'd have to write another endpoint and that feels wrong to me, so ... you're just telling me to do the thing that I specifically said is the thing that makes me think this abstraction is weak.
- jamincan 4y agoFor what it's worth, it's not that difficult to manually implement the `FromRequest` trait for `Thing` so that it parses the request based on the Content-Type.
- masklinn 4y agoIt’s literally how warp works but apparently they skipped right over that so… The objection is also incredibly weird, I think I’ve “needed” a variable type intake all of once, and it was a mistake to do so (as it’s an easy path towards inconsistent handling at different levels of processing).
- zemo 4y agoit’s a thread on an article about moving away from warp. I have a handful of warp services currently and we’re actively moving those services away from warp for other reasons. I’m not going to try to convince everyone at my org to stay on warp, it has the issues this article mentions. My argument is not that it’s impossible, it’s that the whole value proposition of these frameworks is that they make you jump through fewer hoops than building on top of Hyper yourself, but it looks like a lot of the problems that I’ve encountered with Rocket are being replicated with Axum. There’s a very good chance we -will- move our services to Axum, I’m just not confident that this is really stable ground. As for the specific example, I think you’re missing the forest through the trees. I used that specific example because it’s in the article and it’s in Axum’s readme, so it’s safe to assume that people discussing the article would be familiar with that case.