Hacker News new | past | comments | ask | show | jobs | submit login
Rocket v0.4: Typed URIs, Database Support, Revamped Queries (rocket.rs)
395 points by sbenitez 3 months ago | hide | past | web | favorite | 83 comments



I am truly moved by what this small (probably one, maybe two person?) team has accomplished here. Just look at their code and its organization, while noting how languages like Rust, Nim, and Go show us how to tackle the software complexity in various software domains. Having been in the enterprise field for a handful of decades, I am convinced that work such as this is signaling a brave new world of software development that is just ahead of us -- small teams, phenomenal productivity, which needs to combine with a grasp of architecture processes to taken on complex IT stuff. After having been in the SAP, Dessault PLM, and Oracle database-centric industries for some decades now, and I am convinced that a new generation of software software engineers with imagination and willingness to learn aspects of the businesses they serve, they will take on these sprawling legacy systems with much less effort than we think it should take right now. Exiting times are ahead for those who use these opportunities, I'd say.


> a brave new world of software development that is just ahead of us -- small teams, phenomenal productivity

It's also the brave new world that lies behind us. Doom, one of the most influential computer games due to technical innovation, was created by a team of 3 programmers (and 8 non-programmers).

Small teams of brilliant people can produce phenonemal results. Unfortunately in big companies a manager is not only measured by his results, but also by his budget and the number of people under him. The division of 100 people simply looks more impressive than the room of 10. So you end up hiring lots of (at best) mediocre programmers, pay them as little as possible, and use big architectures and processes designed to cope with idiots (Enterprise architectures and Enterprise processes, as we call them).


Calling anyone who isn't brilliant an idiot is a bit. . . uncharitable. Most of us here, myself included, (and probably you) are not rockstar/ninja programmers.


While you're correct it's becoming more of the rule, this has been true a for a very long time.

Clayton Christen wrote about this in 1997 with "The Innovator's Dilemma". He believed it was still repeatable in large organizations via 'intrapreneurship', which I'm not convinced is entirely true... considering the enterprises continued obsession with middle management and hierarchy, and top-down R&D.


I assumed, I guess incorrectly, that Racket was more than a 1-2 person team. Also was perturbed that they were only at a v0.4. Not sure how things like SAP and Oracle are valid in a conversation about Racket...


FYI: This is Rocket, a web framework for Rust, not Racket, the programming language.


Ah my bad, assume we have to use a nightly build then?


The link contains release notes for 0.4, which state that nightly is no longer required. An important milestone for the team, for sure.


Not quite yet- that's a planned change for 0.5.


There's some super exciting stuff in this release, but what caught my eye was this:

> Aynchronous Request Handling (#17) > > In 0.5, Rocket will migrate to the latest asynchronous version of hyperand futures with compatibility for async/await syntax. Of utmost importance is preserving Rocket's usability. As such, these changes will be largely internal, with asynchronous I/O peeking over the covers only when explicitly desired or required. As a side effect, we expect a substantial performance boost from the migration as well as resolution to long-standing issues.

Lacking async was my main reason at the time for switching out a hobby project from Rocket to Actix, It's exciting to see that this might change soon as Rocket really just hits the nail on the head when it comes to useability. It _feels_ fantastic compared to so many frameworks both in Rust and other languages.


I don’t really understand this. Futures don’t “peak from under the covers” they hit you over the head with syntax. And iirc Rocket uses a thread per request model.

So I’m guessing they have optimized their threaded model with futures, plus given you the ability to turn on a non blocking mode, but your routes will need to use futures if you do that?


All of this is done while pursuing a computer science PhD at Stanford, teaching, and other life activities. Sergio has been digging deep for a really long time. It is great to see that others are helping to advance Rocket's mission but as with most open source projects, the primary author moves it forward. This release isn't just about new features or rewrites. It's about passion for one's work. It's about grit. It's about uncompromising commitment to excellence.

While there will ever be only one Sergio in the world, there are many others in the broader Rust community who are signaling many of the same positive qualities. The signal is only increasing in strength as new talent adopts the language for critical path work.

I am more optimistic than ever about Rust as a tool for general use, not just because of the tools but because of the leadership in its community.


Once rocket makes it to stable, I think it will be the go to choice for web development in Rust. The focus on creating a great developer story makes rocket a joy to use.

I am shocked that Sergio maintained rocket alone for so long. I would have figured there was a team of 3-4 people working on rocket. Glad to see he is getting help!


I'm really eager to push for use of rocket (and thus rust) at work, but while rocket being on version 0.x it probably is a tough sell. The benefits rocket (at least seems to) bring feels obvious and I notice every now and then at work that "hey, this would be so easy to do with rocket".


As a whole, Rust developers see 1.0 as a stability commitment and to my knowledge, everybody (well, not Rouille) wants to be async and depend on Futures 1.0. I believe Futures 0.3 is most of the way to where the Futures team wants 1.0 to be and the initial roadmap was trying for 1.0 in 2018 so my uninformed guess is that we'll see Futures 1.0 in the first half of 2019. I expect the whole Rust network server ecosystem to shift around over the coming months as Futures and async/await come online in the next few months.


So, Futures are moving into the standard library; there’s been a last minute procedural issue over one name, and then they’ll be in. So “futures 1.0” isn’t as important, the futures library mostly provides extra utilities, not the core of futures themselves. It’s likely this means they’ll be in 1.33, February 28 (if my math is right)


> So, Futures are moving into the standard library; there’s been a last minute procedural issue over one name, and then they’ll be in.

That's just the open issue around pinning.

There are however a few open discussions around the futures/task/waker parts, from the other RFC. I just wrote down a list of the open points here: https://github.com/aturon/rfcs/pull/15#issuecomment-44549238...


Oh right, I forgot about that but, thank you!


> benefits rocket (at least seems to) bring feels obvious

Sorry I am not a webdev. Curious what these are compared to something like RoR.


I'm not familiar with RoR, but with rocket, to know which requirements needs to be met in order for a handler to run, you just look at the function definition while in other web framework you usually need to know which middlewares are present etc.

Here are couple of examples (didn't test them, but they should illustrate the point):

    // Simple with admin user.

    #[get("/admin")]
    fn admin(user: AdminUser) -> String {
        // Request is made as admin user.
        format!("Allowed.")
    }

    #[get("/admin"), rank = 2]
    fn admin(user: User) -> String {
        // Request is made as a normal user.
        format!("Not allowed!")
    }

    #[get("/admin"), rank = 3]
    fn admin(user: AnonymousUser) -> String {
        // Request is made as a anonymous user.
        format!("Please login.")
    }


    // More flexable, with permissions.

    #[get("/article/<id>/edit")]
    fn aritcle_edit(permission: PermissionEditContent, article_id: u64) -> String {
        // Request is made with a user that has the correct permission.
        format!("Allowed.")
    }

    #[get("/article/<id>/edit"), rank = 2]
    fn aritcle_edit(article_id: u64) -> String {
        // Request is made with a user that doesn't have the correct permission.
        format!("Not allowed!")
    }

    // Or in single handler.

    #[get("/article/<id>/edit")]
    fn aritcle_edit(permission: Option<PermissionEditContent>, article_id: u64) -> String {
        if permissions.is_some() {
            format!("Allowed.")
        } else {
            format!("Not allowed!")
        }
    }
This is just one of the nice things that rocket brings. To know more, the guide is really good source: https://rocket.rs/v0.4/guide/.


Does it make any sense to use this with FaaS?


I would assume so. At a high level, not much different than node with express (Edit: for FaaS).


Lambda just announced native support for Rust last week.


Sure thing, but does it make any sense to use Rocket on it?


Rocket specifically? Lots of people like it. Rust generally? Stuff like https://andre.arko.net/2018/10/25/parsing-logs-230x-faster-w... is one success story we’ve already seen.


gp is asking abt rocket inside lambda.


I don't personally think that there's anything inherently specific to Rocket that makes it better for lambdas than any other Rust web framework.

That's just my opinion, of course.


Ah okay.

I wasn't sure if bare-bones Rust+Lamba-Rust-Runtime was already enough.


Speaking as the co-author AWS's Rust Lambda Runtime: there's no fundamental impediment for us supporting Rocket (or any other web framework), but I suspect there'd need to be changes made in Rocket to support how Lambda expects input. Namely, Lambda functions don't see raw HTTP requests, but instead, fully parsed JSON. This blog post shows how Lambda expects data to be formatted: https://aws.amazon.com/blogs/networking-and-content-delivery...


If you're not trying to run a website on lambda, sure that's enough and there's no need for rocket.


Are ther plans to get to stable?


The plan was always to get on stable[1]. Sergio just wasn't willing to compromise on the API to make it happen sooner and I appreciate that since it's a motivation to stabilize the things Rocket depends on. The release notes being discussed here mention that Rocket should be on stable with the next major (Rocket) release.

[1] https://github.com/SergioBenitez/Rocket/issues/19

edit: specify Rocket release, not Rust release


To be clear, it means the next major release of Rocket, not Rust (I misinterpreted your comment and had to go look, so I thought I'd save others time if they also misinterpreted your comment.)


Yes, progress is tracked here: https://github.com/SergioBenitez/Rocket/issues/19


I've toyed with various Rust web frameworks and I think rocket is one of the most promising. A thought out, high quality project. The person behind it strikes me as someone who pays attention to details, from the codebase, docs, all the way to the presentational website. Kudos!


I lurk the Matrix room for Rocket and I have no idea where Sergio finds the time to near single handedly develop a huge web framework while helping at least a dozen people a day get into it on the IRC.


I've never tried Rust or Rocket, but it appears to be gaining popularity, so I have the following questions for existing users:

What's it like to work with? Do you prefer it to JS/PHP/Python for web related projects?

Can you iterate on code quickly, or is there a compile step on every iteration?

Are there stable libraries for interacting with MySQL/Redis/Postgres asynchronously?

Is there good IDE support, for example in Atom?

Thanks!


It's a bit rough to work with still - the IDE support is still a work in progress (though improving) and there is a compile step with every iteration (incremental compilation has improved this too).

Diesel is the main library for interacting with SQL databases, it wasn't async last time I used it, and a quick web search tells me it still isn't - this has been a BIG problem with Rust over the last year, as everyone waits for the async implementation to finally become stable.

Rust is a funny beast at the moment - you have to deal with the learning curve, you have to deal with the unstable/pre-1.0 libraries (some of which are fine), you have to deal with all the errors the compiler throws at you.

But once you've done all that, something magical happens: you end up with software that is mind-blowingly stable and blazingly fast. It doesn't throw segfaults, it doesn't leak memory, it just works, and works amazingly well.


Isn't diesel being sync largely hid behind a connection/thread pool? Generally you want to limit the connections to the database anyway, so a connection pool is desirable...


Aren't those orthogonal concerns? A connection pool lets you share the same connection across multiple threads of execution. Async lets you share the same thread of execution across multiple actions waiting for IO to happen. For the best performance, you want both.


>it doesn't leak memory

Fairly sure you can leak memory, just no memory safety issues (in safe Rust).


You can also cause segfaults, the point I think is more that it is hard to do this instead of easy as it is in some languages, like C.


Memory leaks can happen in safe code, segfaults cannot. That’s at least one major difference.


That's a great summary, thank you. What about the rate of improvement? Do you think it will be significantly more developer friendly in a few months?


Futures should be in Rust within a few months and the next Rocket release will switch to async. The Rust plugin for JetBrains IDEs is also getting better every release[1].

In short, I'd say Q2 2019 would be a time to seriously jump into it if you don't want to do it now.

1 - https://intellij-rust.github.io


I've bumped around a site idea I've been working on for five years now. I started with Flask, then Django, then felt bad about page load times so I looked for something faster.

That basically made me shelf it for about two years, until last year when Rocket was rising and I gave it a shot. Got hung up again that year due to missing expressiveness in query handling and shelved it again. In the last month I picked it back up and have been working on it again and I must say - this is the best server side development experience I've had, either on the side or working with node / rails / etc for money.

I also definitely feel the performance bump, even without async in yet, and scaling Rocket apps is much more trivial than trying to scale Flask / Django via multiprocess.

I've also been spoiled by the Rust compiler and RLS, despite its breakages its still some really impressive stuff with how if you can get something to compile it is substantially more likely to work and not have errant edge cases that something written in a less prudent language would struggle with.

I haven't really gotten involved in any larger scale Rust projects or took on a maintainer role on anything substantial - I've just made a few patches to Rocket and some support libraries - but I can easily imagine this is the best kind of environment to do collaborative work in. You get rustfmt for style, you get the best compiler ever for debugging, and the project management of Cargo is just impossibly elegant and delightful over anything else I've used. Its definitely something I'd love to work in at a day job as it matures onto the market.


> with how if you can get something to compile it is substantially more likely to work

That is what expected the least, when I was starting out. I was looking for something that is a little like Python, but faster than it. It gives me a sense of security to see the compiler call me out for a reason, telling me exactly which cases I forgot. Together with the type system I often find myself in situation where I do something quite complicated (for my experience) and then I am at a point where I am confident it works, I `cargo run` the whole thing and it works like a charm.

In Python a lot of things would run, but also broken things. Having it run was no guarantee at all it won't end up in a convoluted traceback later. In Rust having it run is a great part of the deal, I rarely encountered Panics afterwards, and when I encountered them it was me willfully defining where I would encounter them.

The weird thing is: because it takes much more to just get a program that compiles – even if you're lazy you end up with a higher code quality. It won't let you take some shortcuts that will haunt you later and that is a good thing.


I also find that Rust drives me to document more - because when I do something "intuitively" that doesn't work and then spend an hour refactoring until it does work I usually leave a comment about it.

And those are almost always the good "in depth" reasoning comments you want in software, not the mandatory "Function save saves the file to where parameter location is" which just repeats the definition.

I still love Python, but I can't even argue its a productivity win for me to use over Rust anymore, because while I might sometimes make something that seems to work faster the lack of confidence makes scaling the program much harder and there really is nothing syntactically in Rust besides the static typing (which is a good thing in my book anyway, its why Python added function signature type hints after all) and verbosity (semicolons, mandatory braces, etc) that prevents you from writing code as fast as a Python variant with the right library support.


"with the right library support"

Well that's the thing it's all about libraries, and now in Rust it's nowhere compare to Python for the web dev.


> What's it like to work with? Do you prefer it to JS/PHP/Python for web related projects?

Of the popular frameworks in languages you mention, Rocket is fairly close to Flask in terms of feel. Rust is a typed language and Rocket uses code generation and function's type signatures to automatically check the incoming parameters.

This can be fairly simple, like verifying+converting a param to a number. It can be fairly involved like setting it up so that if one of your handler function's arguments is an AdminUser, Rocket will take the user id from the request/cookie, connect to the database, and verify that the user is an admin. This is doable with middleware in many frameworks for the languages you mention but the difference is that this is on-demand based on the argument types.

> Can you iterate on code quickly, or is there a compile step on every iteration?

Rust is a compiled language. There's a compile step when you make a code change.

> Are there stable libraries for interacting with MySQL/Redis/Postgres asynchronously?

There are libraries for interacting with all those things. That said, the Rust async ecosystem is in a transition period at the moment. If you're familiar with the JS transition from callbacks to Promises to async/await, it's basically that. Check back in 6 months.

> Is there good IDE support, for example in Atom?

IDE support in Rust isn't particularly good yet. In general, find references and go to defintion work but autocomplete does not.


> Rust is a compiled language. There's a compile step when you make a code change.

That said, it really depends on what you're doing. If you are debugging something, it can be a bit painful but not terrible (typically, you're just changing a few things as you go along). If you're implementing a feature or refactoring, you're better served using "cargo check" (especially in combination with "cargo watch") to only run typechecking but not code generation, which means extremely fast feedback.


> What's it like to work with? Do you prefer it to JS/PHP/Python for web related projects?

Coming from dynamic languages it will feel very different, especially if you don't have a lot of experience with typed compiled languages. Personally, I came from a JS background and I love it. It totally sold me on the benefits of a good type system so much so that I sorely miss it when working with JS now.

Writing web servers in Rust is a fairly new space, it's not as mature as js/php/python, however things are moving quickly. Having your code run orders of magnitude faster is pretty nice too.

> Can you iterate on code quickly, or is there a compile step on every iteration?

I think conflating 'working on code quickly' with compilation is a mistake, however, yes, you do need to compile your code. IMO a compiler will help you iterate more quickly because it's able to check for errors before you run your code.

> Are there stable libraries for interacting with MySQL/Redis/Postgres asynchronously?

If you want an ORM the thing you want to look at is diesel. I'm not sure if it's async or not.

> Is there good IDE support, for example in Atom?

rust language server (RLS) has plugins for most editors. I think the best experience for developing rust right now is in VScode or vim, IMO.


> Are there stable libraries for interacting with MySQL/Redis/Postgres asynchronously?

> > If you want an ORM the thing you want to look at is diesel. I'm not sure if it's async or not.

Diesel isn't async yet, but interfacing with it in async frameworks such as actix seems to be pretty straightforward: https://actix.rs/docs/databases/


>I think the best experience for developing rust right now is in VScode or vim, IMO.

Intellij + Rust Intellij plugin is probably the best, in terms of actual usefulness (code completion etc) and stability.


I really dislike intellij, so I've not spend much time trying their rust plugin. If memory serves according to the rust survey, vim or vscode are the most widely used environments.


I am a long time Pythonist and I started with Rust a year ago. Rust has become my goto language now. I mostly use python with the interpreter nowadays (as a enhanced calculator) or for scripting.

Rust has such a great tooling. In Python starting new projects, remembering whether to use pipenv pyenv, pew, pip virtualenv, which file was supposed to mean what feels much much more convoluted. In rust this is a two word shell command.

The compiler will fuck with you more than you would like, but if you don't fight it, but try to figure out why it is right, you will find that most compile errors are totally for a reason. I had FAR less runtime errors with rust. If the code compiles it is either code with a logic error or it just works as intended.

And it is performant as hell.


I did a lot of stuff with Django and Flask. On current project I was free to choose a platform, so I went with Rocket.

The framework itself is similar to Flask in productivity and amount of boilerplate, though it's even better. It converts all input data to proper types for you using type signatures of handlers. So I don't need to convert strings into ints, or into json and then check if it conforms to a schema. If handler is called, input is parsed and converted.

Rust itself is more verbose than python. Typical data manipulation, like put something in dict, extract/count uniques, "transpose" a datastructure, load data from file, usually takes 1.5x-3x as much chars. For this price you get strict compile-time type checks that take lots and lots of mental load off code refactoring, C++ level performance, and real multithreading, including easy data parallelism with libs like rayon. Rust also has enums (aka algebraic types or tagged unions) that can help to represent problem space better and make fewer logic mistakes later.

It would be all unicorns and rainbows for me if a more concise database interface was awailable. Currently the go-to ORM is Diesel, and it's very verbose comparing to, say, python's sqlalchemy. Current solution is to move database access from views into methods of a model.

About iteration: code requires recompilation. Changes to non-compiled templates do not. I use Maud templates and they make html look suprisingly clean, they compile and are fast, but well, you need to recompile them every time. Currently debug build takes ~10s, though parsing and typecheking are done in the first several seconds.

Diesel doesn't support async yet, AFAIK. But async is usually used to save on context switches and stack space, allowing to support tens of thousands of live connections. You won't ever have tens of thousands of connections to database like Postgres. 100 connections is quite generous. 500 connections may be possible on the fattest DB boxes. Postgres is not async itself, it allocates a 4MB scratch buffer for each client from the start, IIRC. The only good reason to use async for communication with postgres may be if all of your other code is async and you don't want to deal with sync/async impedance mismatch. Though you'll likely want have connection pool anyway.

About IDEs I can't say much, I use emacs with LSP, it works most of the time.


It concerns me that you have to use a Rust nightly build to use Rocket. Am I off the mark on being concerned about this?


Honestly, the nightly compiler is _really_ stable for the "nightly" moniker it receives. It's basically just the rolling release of the current Rust codebase each night. I've run into issues before where I get an internal compiler error, but those have been rare and rolling back a version (or waiting to roll forward) resolves them.

For the most part, there's very little risk running Rust nightly and in fact, that's my MO. I like being able to receive the latest benefits and opt into compiler gates and whatnot. I couldn't do that on Rust stable.

Overall, I feel very little friction sticking with nightly rust and using libraries that are still nightly-only.


I think it is healthy to have some projects pushing the envelope on what is possible. It provides a goal to work towards and helps test out those new language features so they can be further refined before hitting stable.

It becomes less healthy if the whole community is relying on nightly.


AFAIK Rocket has always been focused on developing an ergonomic type safe API to building web applications. Many things it depends on, codegen, proc macros, that sort of thing, are yet to be stabilized. I'm not affiliated with the project, this is just what I've read about it.

There are other frameworks you can use if you want to use stable, many of them are async already. Granted, none are really 'mature', but this is a new-ish space for Rust anyway.


Most of that stuff is now stable; the major thing it’s waiting on is a fairly technical detail that gives Rocket more informative errors. If Sergio was willing to regress a bit there, it could be on stable, in my understanding. But developer experience is kind of the whole point, so he’s making the call to wait longer.

(EDIT: I just reviewed the flag list and I am 99% sure this is true; the never type could use a library instead, and I am pretty (but not %100) sure proc_macro_hack could fix the other one. It’s quite possible I’m wrong, but in the end, it’s still basically three features left to go.)


It’s an extremely common objection, you’re not alone.

The post does discuss this as well.


Is anyone able to lay out some of the reasons why you might want to write web applications in rust? I was under the impression rust was designed as a safer language for low level systems programming. Thanks!


I'd say that in all the talk of Rust being a C replacement, what gets lost is that it is also a very expressive, modern, functionally flavored language, perfectly suitable for higher-level programming.

If you want type safety, speed, expressive language & native binaries, Rust is a good choice.


Sure, however you do pay the significant cost of having to satisfy the borrow checker. There are other nice expressive languages where you don't have to do that so if you actually don't need the speed Rust is maybe not the best choice.


> you do pay the significant cost of having to satisfy the borrow checker

Right, but this is presumably a one-time investment while learning Rust, much less of an ongoing hurdle.


I disagree. It's something you always have to think about. It might get easier but it doesn't magically go away.


You often should think about it in other languages too, ie to avoid concurrency bugs. If you don't, there's a good chance your program isn't correct, even if accepted by a less strict compiler.


Yes. But the point is that you don't have to "dumb down" your program to prove to a static analyser that it is correct.

Look at the kind of programs that NLL now allows. You wouldn't have to jump through those hoops in another language.


Satisfying the borrow-checker usually ends up implying that either:

a) you used .clone() everywhere and therefore are probably modifying something and failing to propagate the modifications to where they need to go; or

b) your design is inherently better, saner, easier-to-optimize, etc., than one which doesn't have to satisfy the borrow checker.


It's fast. It's type safe. Solid developer tooling story.

Those three things are very appealing, whether it's web or anything else.


Web servers for embedded or otherwise constrained systems, bolt-on embedded api servers for your existing apps, or just any high perf app/gateway. All the reasons you would otherwise do it in cpp except nope.


Very efficient usage of CPU and RAM. Regarding cloud functions like AWS lambda: Fast startup.



With all due respect, 166 packages to compile for a 5 line hello-word is so Nodejsy. It is a smell, a red flag. We should learn more from Go and Erlang.

I hope the Tide will do.


Tide is pretty expressly being built as a collection of smaller packages; I would expect it to have far more than Rocket.


If you try to compile hello-world in C, you would need a gigantic libc.so, with a lot of stuff you do not need.

These 166 packages you need to compile Rocket, not your hello-world. Rocket itself is much more complex then your hello-world, like libc.so is much more complex than hello-world coded in C, I see nothing wrong with it. Rocket and libc.so were created for solving a wide class of problems and hello-world is just one problem from that class.


>166

Yikes!

Does anyone know where I can get an overview of the entirety of rocket's dependency graph. Crates.io only lists 11 direct dependencies.


You can use the `cargo graph` [0] command to get a graphviz view of the dependency graph. The `Cargo.lock` file which Cargo generates should also contain all the information you want in machine-readable form.

[0]: https://github.com/kbknapp/cargo-graph


No, but that would be a good project. Probably the easiest way at the moment is to see the compilation output. E.g. from the CI logs:

https://travis-ci.org/SergioBenitez/Rocket/jobs/465537062


I do agree, and Go is definitely better in this regard, but why is that the case? I can't see any technical reasons for it.


Did anyone manage to build a SaaS product in Rocket yet?

Looking for ActiveMerchant equivalent in Rust.

How do you handle subscription billing?




Applications are open for YC Summer 2019

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: