Settings

Theme

Rocket, Rust Web Framework, v0.3: Fairings, TLS, Private Cookies

rocket.rs

165 points by sbenitez 8 years ago · 74 comments

Reader

jamescostian 8 years ago

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.

[0] https://rocket.rs/guide/getting-started/#minimum-nightly

  • kibwen 8 years ago

    > 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.

  • Manishearth 8 years ago

    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)

  • moosingin3space 8 years ago

    Rocket uses compiler plugins to do its magic, and compiler plugins aren't stable.

  • leshow 8 years ago

    Rocket uses some advanced codegen and procedural macro stuff that's not on stable if memory serves. The annotations for routes, for example.

  • lholden 8 years ago

    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.

continuations 8 years ago

How is the performance of Rocket?

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

    * iron isn't using async io which is very important for Techempower

    * 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.

    • moomin 8 years ago

      How is the async web server story looking? I keep thinking I'd like to port a small tornado app to Rust, but I'd rather it was fairly easy for some to verify it was behavioural similar.

      (Literally, I don't care about the performance, I just want that style of API.)

      • steveklabnik 8 years ago

        I don't know now much about tornado's API, so I can't say for sure.

        Right now, the async APIs are largely based on Futures. There's an experimental branch of the compiler that implements coroutines and therefore async/await on top of them though, so that syntax may or may not be coming in the future.

Nelkins 8 years ago

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?

[1] http://www.arewewebyet.org/

[2] https://github.com/iron/iron

  • fiedzia 8 years ago

    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.

  • Tobu 8 years ago

    This list has been updated more recently: https://github.com/flosse/rust-web-framework-comparison

  • steveklabnik 8 years ago

    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.

    • zanny 8 years ago

      This is actually driving me a bit insane trying to do anything more than the simplest Rust samples. There are... a lot of competing libraries implementing the same concepts. Input validators, crypto, tls, http (there are I believe at least 3 http/2 implementations, and hyper doesn't even support it yet) and pretty much every concept under the sun (hell, hyper has its own implementation of a url type independent from servo_url).

      There are several Json types across all the various crates, multiple Url types, multiple Http::Request or Hmac or SHA cipher types. They all use the same names but are always distinct constructs that cannot interop.

      It might be one of the most significant ergonomic issues with Rust going forward. Having a dozen Url types in Python is fine since the typing usually just coerces them all to Strings for interop anyway. Most Url types are (thankfully) serializiable and have a to_string, but in a statically typed language the performance implications of having the compiler generate strings from objects to be consumed by another object's constructor are dreadful.

      • pimeys 8 years ago

        > there are I believe at least 3 http/2 implementations, and hyper doesn't even support it yet

        Hyper 0.11 with Tokio is the thing to choose for http/1. It's fast and composes nicely. Http/2 support is coming soon and looking pretty nice already.

      • steveklabnik 8 years ago

        Yup, that's what early ecosystems are like! It'll settle down eventually.

bpicolo 8 years ago

Hey Sergio,

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.

  • sbenitezOP 8 years ago

    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:

      on_response => |request, response| {
          if response.status() == Status::NotFound && request.uri().path().ends_with('/') {
              response.set_status(Status::Found);
              response.set_header(Location(request.uri().path()[..-1]));
              response.take_body();
          }
      }
    
    Take a look at the fairings guide [0] and fairings documentation [1] for more ideas!

    [0]: https://rocket.rs/guide/fairings/

    [1]: https://api.rocket.rs/rocket/fairing/trait.Fairing.html

pc2g4d 8 years ago

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.

  • sbenitezOP 8 years ago

    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.

    [0]: https://api.rocket.rs/rocket_contrib/index.html

    [1]: https://rocket.rs/guide/introduction/#foreword

  • StavrosK 8 years ago

    Isn't Postgres worth coupling to? SQLite is a close favorite, for different reasons.

    • yen223 8 years ago

      Web servers and database management are two vastly different domains. I'm wary of frameworks that attempt to impose an opinion on both.

      • StavrosK 8 years ago

        Rocket isn't a web server, it's a web framework. That's what frameworks should do, impose opinions on things to get all the best practices sorted.

    • mixedCase 8 years ago

      As someone who only uses Postgres and SQLite: No. It's not.

      People inevitably have to deal with preexisting systems they can't modify for their needs.

      • StavrosK 8 years ago

        Should a framework optimize for the vanishingly rare case?

        • e12e 8 years ago

          Integrating with legacy systems (that one cannot, or is difficult to modify) a vanishingly rare case? Thats... quite an assumption.

wyldfire 8 years ago

> Private Cookies #

> 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

    Yesod does this too and it sometimes causes problems you first deploy an app to production.

  • zimbatm 8 years ago

    Rails had encrypted cookies for ages

    • wtetzner 8 years ago

      I think wyldfire was referring to the part about generating a new key on launch. Of course, Rails might do that too, for all I know.

      • floatboth 8 years ago

        uhh generating a new key on launch means every time you restart the app, everyone's cookies must be reset because the old ones can't be decrypted anymore.

        It's just a convenience feature for development.

dvnguyen 8 years ago

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?

  • fiedzia 8 years ago

    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.

    • pimeys 8 years ago

      Having written tons of Python, Rust and several other languages, I have to add one more thing:

      - The Cargo dependency and build tool is the best in any ecosystem. Easy to configure, works like a charm and gets improvements done regularly.

      I don't miss setup.py/virtualenv/pip/pex at all.

  • kibwen 8 years ago

    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

    • kevan 8 years ago

      We also shouldn't discount it just because Python is usually fast enough (all my personal projects are in Python). Developer time is cheaper than hardware 99% of the time. For the 1% that are running millions of requests per second through their web stacks the value proposition is pretty compelling.

      • mmargerum 8 years ago

        Not when you are renting the hardware. Lean languages like Swift, Rust and even Go look pretty attractive when you are paying by the hour.

      • xfer 8 years ago

        > Developer time is cheaper than hardware 99% of the time.

        I find the exact opposite to be true in most cases.

        • mixedCase 8 years ago

          In bare metal deployments or cloud? If the latter, then moving to the former seems like an obvious choice.

        • kevan 8 years ago

          Whoops, I stated that backwards. My time is more valuable than the CPU's most of the time.

    • OJFord 8 years ago

      > fearless refactoring really is something that compiled langs excel at

      Would you say that's a feature of compilation? I'd have said it's Rust's strong and static type system that makes refactoring 'fearless' and generally aids productivity and maintainability.

      Python ≥3.6 with liberal type hinting is a more interesting comparison in my view.

  • zanny 8 years ago

    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.

    • pimeys 8 years ago

      It's not that bad. Having written some Rust libraries, there are things to like that the other ecosystems don't provide. One is the rustdoc, where you document your interfaces in code, and if you write code examples in the documentation, `cargo test` will automatically check that they work.

      And like I said in another comment, there is nothing as good as cargo in anywhere else.

  • zem 8 years ago

    one nice use case is to add a quick web frontend to a rust project.

  • Scarbutt 8 years ago

    Rust doesn't have a stable/mature HTTP implementation/abstraction yet.

    • pimeys 8 years ago

      We push millions of requests daily through Hyper 0.11, which is async and uses tokio. I've had crazy three month uptimes for these systems. Basically they just do their work fast and I don't really need to focus on fixing any problems with them.

      And did I tell my test coverage is quite minimal with these projects.

    • bluejekyll 8 years ago

      Hyper is pretty darn good and I haven't seen issues with it not being mature.

      • Scarbutt 8 years ago

        from hyper's readme:

        Be aware that hyper is still actively evolving towards 1.0, and is likely to experience breaking changes before stabilising. You can also see the 1.0 issue milestone.

eptcyka 8 years ago

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.

  • zanny 8 years ago

    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.

  • biokoda 8 years ago

    It's far from clear if tokio is not a dead end.

    • mercurial 8 years ago

      How so?

      • biokoda 8 years ago

        Overly complicated

        • mercurial 8 years ago

          I'm not sure it is an issue of complexity. From what I have seen, it is more a problem of ergonomics. Currently, programming something fairly simple with a few loops and if statements using Futures is painful, but I could see a Futures-based async/await version take off.

shmerl 8 years ago

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.

leshow 8 years ago

Rocket is great. Congrats on the new release!

lholden 8 years ago

Fantastic Sergio! I'm glad v0.3 has landed :D

Scarbutt 8 years ago

Since its async, do you have to develop in it using callbacks?

  • steveklabnik 8 years ago
  • zanny 8 years ago

    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.

Keyboard Shortcuts

j
Next item
k
Previous item
o / Enter
Open selected item
?
Show this help
Esc
Close modal / clear selection