I actually really love the restrictions on fairings. I'm working on a project right now that uses Node.js with Express, and there are all of these pieces of middleware that won't compose at all, and I often find myself ripping things out and putting them in new functions.
By having clear delineations between fairings, request guards, and data guards, I think you can really avoid making a lot of design mistakes. I'm going to try out Rust some more and definitely play around with this framework! The only thing that bothers me is that Rocket says it requires a nightly version of rust[0] - why is that necessary? I thought Rust was pretty stable by now.
> Rocket says it requires a nightly version of rust[0] - why is that necessary
I often joke that Rocket deliberately uses every single unstable feature solely to stymie the Rust developers' attempt to prioritize which features to stabilize. :P I'm kidding of course (hi, sbenitez!), but it's true that I've never seen any Rust project so taken with nightly features as Rocket is.
The author of Rocket explicitly wants to use Rocket to experiment with new features. A lot of the stuff could be done on stable (but in a more annoying way), but it's easier with experimental features. (I discussed moving it to stable with the author)
Rust Stable is great, but not all of the macro (the Macro 2.0 stuff) support is on the stable release channel yet. There are still some things you can't do on stable (or can do, but inconveniently).
(Rocket also depends on a few other nightly only features. Things will likely change in the future once the Macro stuff stabilizes though)
There is also the matter of compiler plugins... which may never land in stable.
I was just recently looking at the state of web frameworks[1] in Rust, and it seems like the two most popular are this and Iron[2]. Can anyone comment on some of the differences between the two? Also, can anyone point out a few sites that were made using these frameworks?
Iron provides a bare minimum of concepts that you need. Rocket comes with its opinions and a lot of features nicely integrated. Iron will allow you to design anything you want easily, because all elements are as simple as they possibly can be and compose nicely, but requires that you have your own vision and enough experience to know what you need and how to build it. So Iron is great if you need thin layer of web interface added to some existing non-web project, or have enough experience with web and Rust to have own vision. It also work fine with stable. Rocket is great for all other cases - if you are new to webdevelopment and/or Rust, expect framework to tell you how to do things and don't mind using unstable. I don't have examples of sites, but none of those frameworks deals with UI, so I am not sure how would that help you.
arewewebyet hasn't been updated since March, and there's been some big developments since then.
Those probably are the two most popular, but there's a Cambrian Explosion going on right now, with new frameworks like Susanoo and Cargonauts appearing on the regular. Heck, I even have my own little half-baked one.
Regarding fairings, it seems a missing "middleware" case might be the sorts of things that cause redirects on entry (e.g. redirect routes with/without trailing slashes to the latter as a super trivial example). Is that something you'd expect to support in some way? I think that's something that doesn't feel like it maps either to guards or fairings well at the moment.
I did see where you mentioned your dislike of rails/sinatra/... style blunt force middleware, fwiw.
This is actually possible with fairings! Because fairings can rewrite requests, it's possible to create a fairing that rewrites a request URI of `path/` to `path` or vice-versa as needed. Rocket will route the rewritten request normally. In psuedocode, such a fairing might look like:
on_request => |request, _| {
if request.uri().path().ends_with('/') {
let new_path = request.uri().path()[..-1];
request.set_uri(URI::new(new_path));
}
}
You can also use a fairing If you want to return a 302 (or similar) so that the browser does the redirect instead. In this case, you'd implement a response fairing that rewrites failed responses to return a redirect to the appropriate URI. Again, in pseudocode, this would look like:
I'm a Rocket fan and glad to see this big slate of improvements. On the other hand, I do want to register a bit of concern regarding the plan to add "first-class database support" for 0.4. I hope that doesn't result in a close coupling to any particular database, or to using a database in general.
Database support will live outside of Rocket's core in Rocket's contrib [0] library. Everything in contrib is implemented independently of Rocket and is entirely optional to use. The implementation will be database agnostic and extensible to any database. I'm a big believer in pluggable, optional components with no forced decisions [1], and database support will follow the same philosophy.
> To encrypt private cookies, Rocket uses the 256-bit key specified in the secret_key configuration parameter. If one is not specified, Rocket automatically generates a fresh key at launch.
Seems like a pretty clever idea. Do other servers/middlewares offer a similar feature? Seems like it would complicate deployment/scaling a bit if the secret has to be sent to all the nodes. Especially if they could silently ignore it if you accidentally don't configure the key for some nodes.
I don't have any experience in Rust. From what I read, Rust is a low level / system programming language. Comparing to dynamic languages like Python, I understand that Rust is much faster. However, Python is fast enough for most web applications. So why should I use Rust in web development? Even if the library ecosystem were mature enough, could I expect my productivity could become nearly high as in Python?
In terms of ecosystem maturity Rust is far behind Python, but ignoring that and performance, it still has some merits:
- static analysis helps you avoid numerous issues that plague Python. Runtime errors are far less likely and you are forced to greater discipline when coding
- it is modern language. After using algebraic data types, pattern matching and traits it is hard to go back to old style OOP.
- You can extend existing types with your own traits, and so can library authors, so you have plenty of extremely useful extensions. Just add use clause referencing some library, and everything gets more useful methods, without any magic or monkeypatching, so it causes no issues as it could in some dynamic languages.
I'd say it is massive gain in terms of quality and maintainability, but at the cost of upfront investment. Rust isn't a language I'd expect people to write prototypes in, but with few crates it can be as expressive as Python in many cases.
I'd say it's true that Python is fast enough for most web servers. Rather than strictly considering performance, I'd guess that people seeking to do webdev in Rust are looking to leverage Rust's static analysis to improve resilience, trading off up-front productivity for long-term maintainability (which isn't to denigrate Python, which I love, but fearless refactoring really is something that compiled langs excel at). It's not the right tradeoff for everyone or every application, certainly. And maybe other people just really like Rust. :P
It takes longer to get the code to compile, but once it does the integration pains and debugging needed will be significantly less. I'd absolutely argue that productivity can be higher in Rust, especially the larger the project is, or the longer you expect to support it for.
A lot of what people miss when approaching Rust is that writing libraries is really hard and time consuming, but writing applications using libraries is often as easy as Python. Libraries need to provide abstractions, and thus use really complex features like code generation macros, trait extension, generics, type conversion, and the annoying lifetimes that most people beat their heads on when first learning Rust. Rust for an application developer feels almost entirely OOP, like Java, and much nicer than C++ because simple data structures don't hit undefined behavior every other line with the other half being full of memory leaks.
It's really a shame they haven't jumped on tokio yet. Then again, I tried to look at the code, and it didn't seem to be a simple dropin thing to move over to tokio.
Rocket might have an easier time doing async than, for example, Python. You get 90% of the benefit from only having the async internal - you can make all the route handlers async without needing the user to do anything else, and even if the occasional route is blocked by io you can just generate a ton of threads. It still means the "average" use case of static page returns or fast redis access will be able to handle a ton more requests.
Even going all the way, I don't see much more of an issue than just exposing a handle to routes to do async IO with if they want to and making the internal async core available to fairings and other code from main().
Internally it would probably be a big mess right now, though.
What's not clear from the front page. Is it its own Web server? Is it a framework which uses another Web server? I think that would be useful to clarify from the start.
Unlike with Python and similar single-threaded languages you can actually avoid a lot of the complexity of having async everywhere by using the CpuPool reactor for Rust futures.
I imagine Rocket, when it gets its async support, will have the ability to use callbacks to create fully async routes, but the halfway compromise until then will be to have async-dispatched routes that are themselves blocking to a very large threadpool. As long as you have enough generated threads to rarely get all of them stuck in blocking IO you get all the benefits of concurrency without having to callback every IO operation in a route handler.
jamescostian|8 years ago
By having clear delineations between fairings, request guards, and data guards, I think you can really avoid making a lot of design mistakes. I'm going to try out Rust some more and definitely play around with this framework! The only thing that bothers me is that Rocket says it requires a nightly version of rust[0] - why is that necessary? I thought Rust was pretty stable by now.
[0] https://rocket.rs/guide/getting-started/#minimum-nightly
kibwen|8 years ago
I often joke that Rocket deliberately uses every single unstable feature solely to stymie the Rust developers' attempt to prioritize which features to stabilize. :P I'm kidding of course (hi, sbenitez!), but it's true that I've never seen any Rust project so taken with nightly features as Rocket is.
Manishearth|8 years ago
moosingin3space|8 years ago
leshow|8 years ago
lholden|8 years ago
(Rocket also depends on a few other nightly only features. Things will likely change in the future once the Macro stuff stabilizes though)
There is also the matter of compiler plugins... which may never land in stable.
continuations|8 years ago
So far all the Rust web frameworks I've seen have pretty disappointing performances.
I was expecting C++/Java/Go level of performance. Instead, Tokio & Iron turn out to be slower than many frameworks in Ruby, Python, PHP, JS:
https://www.techempower.com/benchmarks/#section=data-r14&hw=...
https://www.techempower.com/benchmarks/#section=data-r14&hw=...
https://www.techempower.com/benchmarks/#section=data-r14&hw=...
steveklabnik|8 years ago
* Tokio-minihttp is #4 overall on the plaintext benchmark there, which is sort of the "what is the max performance" benchmark
I don't know of anyone who is really actively looking at Techempower and optimizing based on it, which is how you win benchmarks.
Nelkins|8 years ago
[1] http://www.arewewebyet.org/
[2] https://github.com/iron/iron
fiedzia|8 years ago
Tobu|8 years ago
steveklabnik|8 years ago
Those probably are the two most popular, but there's a Cambrian Explosion going on right now, with new frameworks like Susanoo and Cargonauts appearing on the regular. Heck, I even have my own little half-baked one.
bpicolo|8 years ago
Regarding fairings, it seems a missing "middleware" case might be the sorts of things that cause redirects on entry (e.g. redirect routes with/without trailing slashes to the latter as a super trivial example). Is that something you'd expect to support in some way? I think that's something that doesn't feel like it maps either to guards or fairings well at the moment.
I did see where you mentioned your dislike of rails/sinatra/... style blunt force middleware, fwiw.
sbenitez|8 years ago
[0]: https://rocket.rs/guide/fairings/
[1]: https://api.rocket.rs/rocket/fairing/trait.Fairing.html
pc2g4d|8 years ago
sbenitez|8 years ago
[0]: https://api.rocket.rs/rocket_contrib/index.html
[1]: https://rocket.rs/guide/introduction/#foreword
StavrosK|8 years ago
wyldfire|8 years ago
> To encrypt private cookies, Rocket uses the 256-bit key specified in the secret_key configuration parameter. If one is not specified, Rocket automatically generates a fresh key at launch.
Seems like a pretty clever idea. Do other servers/middlewares offer a similar feature? Seems like it would complicate deployment/scaling a bit if the secret has to be sent to all the nodes. Especially if they could silently ignore it if you accidentally don't configure the key for some nodes.
coolsunglasses|8 years ago
zimbatm|8 years ago
dvnguyen|8 years ago
fiedzia|8 years ago
- static analysis helps you avoid numerous issues that plague Python. Runtime errors are far less likely and you are forced to greater discipline when coding
- it is modern language. After using algebraic data types, pattern matching and traits it is hard to go back to old style OOP.
- You can extend existing types with your own traits, and so can library authors, so you have plenty of extremely useful extensions. Just add use clause referencing some library, and everything gets more useful methods, without any magic or monkeypatching, so it causes no issues as it could in some dynamic languages.
I'd say it is massive gain in terms of quality and maintainability, but at the cost of upfront investment. Rust isn't a language I'd expect people to write prototypes in, but with few crates it can be as expressive as Python in many cases.
kibwen|8 years ago
zanny|8 years ago
A lot of what people miss when approaching Rust is that writing libraries is really hard and time consuming, but writing applications using libraries is often as easy as Python. Libraries need to provide abstractions, and thus use really complex features like code generation macros, trait extension, generics, type conversion, and the annoying lifetimes that most people beat their heads on when first learning Rust. Rust for an application developer feels almost entirely OOP, like Java, and much nicer than C++ because simple data structures don't hit undefined behavior every other line with the other half being full of memory leaks.
zem|8 years ago
Scarbutt|8 years ago
eptcyka|8 years ago
zanny|8 years ago
Even going all the way, I don't see much more of an issue than just exposing a handle to routes to do async IO with if they want to and making the internal async core available to fairings and other code from main().
Internally it would probably be a big mess right now, though.
biokoda|8 years ago
shmerl|8 years ago
kpcyrd|8 years ago
leshow|8 years ago
lholden|8 years ago
Scarbutt|8 years ago
steveklabnik|8 years ago
zanny|8 years ago
I imagine Rocket, when it gets its async support, will have the ability to use callbacks to create fully async routes, but the halfway compromise until then will be to have async-dispatched routes that are themselves blocking to a very large threadpool. As long as you have enough generated threads to rarely get all of them stuck in blocking IO you get all the benefits of concurrency without having to callback every IO operation in a route handler.