Backend Web Frameworks
Theres several production ready frameworks and the Rust working groups are also working on a new player, Tide. Well discuss the ecosystem in general and then well have Christopher Miller talking about his use of rocket.rs and its design decisions vs Tower.
Well probably keep most front end chat for another (next months?) meetup but maybe a brief digression. So come with your questions and help set the agenda.
Backend Web Overview via @jacobRosenthal
Why Rust for backend:
- speed and footprint. Certainly huge gains over something like Node or Python. Performs well against c++ and golang but theyre all in the mix. https://www.techempower.com/benchmarks/#section=data-r15&hw=ph&test=plaintext Though frankly not that many of us are deploying load balancers
- presumably because we like Rust and want to write more of it
What is the backend space
- api servers
- database connectors
- websockets
- much more https://www.arewewebyet.org
Backend Web Frameworks
The barest tcp server example http://rosettacode.org/wiki/Hello_world/Web_server#Rust like the node few liner from years back http://rosettacode.org/wiki/Hello_world/Web_server#JavaScript/
what does a web page request even look like? we can talk to that server with a browser obviously.
we dont need a webbrowser to connect though, we could use already installed telnet to telnet localhost 8080
and we literally get our Content text sent to us
but pretty much everyone goes one step up and uses hyper for a bare minimum server
Up from that you have full featured platforms (many of which might use hyper themselves) not unlike you might have used in other languages Tons of options available to choose from https://github.com/flosse/rust-web-framework-comparison
The big split is those that are trying to implmenet the (still not shipped) asynchronous networking. Those trying might still be stuck on nightly. Other more stable projects are delaying their implementation until really soon so expect some churn or try to build for the future now. Most of the existing ones use Tokio, a userland library that has been where most async code has lived the past few years.
Beyond that its a personal choice of syntax (procedural, declaritive). Things like if you're setting up routes with macros decorating functions like rocket, or calling a function like actix
The rust web-wg is building Tide in order to find and bolster the underlying crates and show idiomatic style especially around the new async and future language features. not sure if they expect that it becomes standard or just teaching tool. IE they want to show how not to use tokio but the underlying core libraries for async.
Websockets
Ive personally used ws-rs
cargo run --example server
and cargo run --example client
But instead of using the client example, we can also test on the command line. I like the pure Rust websocat for communicating / testing
Keep the server running and do
websocat --linemode-strip-newlines ws://127.0.0.1:3012
and you can type and see the results on your server
Basically youll start with a match statement in the server to detect strings probably (though binary is avialable) where you're just calling a funciton based on the string you get sent and trying to parse params. Well that gets silly fast, so theres a standard for that. jsonrpc
jsonrpc from paritytech implements it for us in Rust and uses ws-rs under the hood so its a pretty simple switch for I think much cleaner interface. And now you're using a standard so all client that supports jsonrpc (all of them) in whatever language you might want to use on the client side can call your exposed functions with parameters even.
cargo run --example ws
and echo 'say_hello' | websocat -n1 --jsonrpc ws://127.0.0.1:3030
But these patterns are not very async-ey.. want them to spit out a future/ stream instead of spin of an event loop. And you're going to have a thread pool of some kind, manual or something like tokio or core futures. It would be cool for the http and the websocket to share the same thread pool, all in one application. Plus that really helps us tie websocket directly into our web flow, theres no reason these should be seperate, theyre just tcp routes
I still havent settled on anything myself, but my googling has found these might be better implementations, but I dont think either has jsonrpc:
- https://github.com/snapview/tokio-tungstenite
- https://github.com/websockets-rs/rust-websocket/blob/master/examples/async-server.rs
Probably most promising, actix server has a nice web server and websocket example websocat --linemode-strip-newlines ws://127.0.0.1:8080/ws
Meet Rocket via @mysteriouspants
Why rocket
I like Rocket because it focuses heavily on programmer ergonomics with lots of macros. A strong convention-over-configuration pattern makes it easy to get going rapidly. Negatives are, of course, nightly-only compiler support.
Getting Started
-
to get templates out of rocket contrib first activate the feature
toml rocket_contrib = { version = "0.4.1", features = ["handlebars_templates"] }
-
default templates dir is $crate_root/templates
-
requires serde
toml serde = "1.0.90" serde_derive = "1.0.90"
-
you can drive the template using contexts which are serializable to Object (must be a map of thing to thing). these elements are available to your templates
#[derive(Serialize)] struct TemplateContext { title: &'static str, // This key tells handlebars which template is the parent. parent: &'static str, }
-
render using a template
fn index() -> Template { Template::render("index", &TemplateContext { title: "page title", parent: "layouts/base" }) }
the parent is used to pick the layout - this is totally by convention and can be omitted for pages that aren't laid out