3 ms·
sure you can get the underlying request, but if that’s the answer to everything that the framework author didn’t think of, that’s just an admission that the abs
by zemo 4y ago
sure you can get the underlying request, but if that’s the answer to everything that the framework author didn’t think of, that’s just an admission that the abstraction is wrong, which is kinda what I’m getting at. The entire conceptual model that views the Json<T> type as a handler argument type and then parsing the body based off of that is what Rocket does too. I think the entire strategy is conceptually incorrect. Axum may do Rocket better than Rocket, but if it’s using the same conceptual model, it seems like a lateral move. I’m looking for a new abstraction and conceptual model, not a better implementation of the same concepts or the same concepts with a larger pool of maintainers.
- infogulch 4y agoThat's not a wrong abstraction, it's just not the abstraction level that you want to work at for this problem. So... create multiple endpoints that all call the same function to perform the behavior you want? Maybe call it a "controller".
- zemo 4y agoI spent ten years writing Go HTTP servers and the abstraction used in net/http has served me well for a decade straight. I’ve been writing http servers in rust for 3 months. Rocket provides an abstraction with a lot of holes that makes me jump through a lot of hoops to do things that have been trivial and common in http programming for over a decade. I’ve written stuff using only Hyper, it’s very manual. Warp has the problems the article describes. With Go, I used the standard library HTTP implementation for a decade and was happy the whole time. I also wasn’t experienced with Go going into it, it was how I learned Go. Axum and Rocket have the same general thrust, the abstraction being that you define types to see a thing that’s not an HTTP request. That’s the abstraction that I think is incorrect. That design strategy is actively making things complicated for me on a daily basis at my dayjob writing services in Rust. I want something higher level than Hyper but with a different theory of abstraction than Rocket or Hyper want to provide. The theory of Rocket’s abstraction is that the framework handles the http request and response for you, what you see is something else. That’s not the toolkit I’m looking for. The toolkit I’m looking for makes it easy to interact with http request and response streams instead of making it easy to hide their existence.
- infogulch 4y agoYou don't want to use request guards / automatic deserialization into strict types because it's not flexible enough. You're not willing to use the tiniest abstraction (a function) to perform the same behavior for different strictly encoded requests. (Well, you didn't really respond to the content of my comment at all, but nevermind.) You rejected ancestor's suggestion of using Request<Body>... which is exactly what is provided by Go. I can't tell what you want, all of these opinions stacked together are incoherent. > The toolkit I’m looking for makes it easy to interact with http request and response streams > I want something higher level than Hyper So higher level than hyper, but no higher level than hyper. Crystal clear.
- zemo 4y agono 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.