The first thing I want to do is get a web server running with Rust. I'm going to walk through installing Rust, creating a new project, using an Actix-Web server, and using Handlebar templates to render HTML.
First, the rustup toolchain manager needs to be installed. Rustup is to Rust as rvm/rbenv is to Ruby, nvm to Node, etc... Run the command below and it'll also install Rustup and the latest stable version of Rust.
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Afterwards, you should be able to check the installed version of Rust and Cargo. Cargo is the package manager; think of it like npm, gem, etc...
$ rustc --version
rustc 1.39.0 (4560ea788 2019-11-04)
$ cargo --version
cargo 1.39.0 (1c6ec66d5 2019-09-30)
Create a new directory for your project. In this case, create a directory called
"running-a-rust-web-server". Change into the newly created directory and run cargo init
. This will create the
basic files
needed for a Rust app. Plenty of resources exist that go into detail about what initially gets
created, so I wont do that here. Next, run the application with cargo run
and view it's output.
$ mkdir running-a-rust-web-server
$ cd running-a-rust-web-server
$ cargo init
Created binary (application) package
$ cargo run
Hello, world!
Rust has a few different web frameworks to choose from which can be viewed here. I've chosen to use Actix-Web. Open the Cargo.toml file and add Actix-Web. It should look similar to the file below
[package]
name = "running-a-rust-web-server"
version = "0.1.0"
authors = ["Logan Keenan"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
actix-web = "1.0.9"
You can install your projects dependencies with cargo fetch
. Cargo will also install
dependencies when you build (cargo build
). Note for javascript devs, dependencies are not download at a project
level. They are downloaded once per version of Rust. Once dependencies have been fetched then the Cargo.lock
file
is updated automatically.
Actix-Web has made it super easy to get started. Their home page
has some great sample code which we'll use too. Copy the code below to your src/main.rs file and start your Rust
web server (cargo run
). You should be able to visit http://localhost:8000 and see Hello World.
use actix_web::{web, App, HttpRequest, HttpServer, Responder};
fn greet(req: HttpRequest) -> impl Responder {
let name = req.match_info().get("name").unwrap_or("World");
format!("Hello {}!", &name)
}
fn main() {
HttpServer::new(|| {
App::new()
.route("/", web::get().to(greet))
.route("/{name}", web::get().to(greet))
})
.bind("127.0.0.1:8000")
.expect("Can not bind to port 8000")
.run()
.unwrap();
}
I decided to go with Handlebars because it's a really simple templating language. We'll create a layout page which all other pages can use and then an index page which will be served at the root (http://localhost:8000).
handlebars = "2.0.2"
to you dependencies in the Cargo.toml file<!--running-a-rust-web-server/src/templates/index.hbs-->
{{#> layout_page}}
{{#*inline "page_content"}}
<p>
{{paragraph_text}}
</p>
{{/inline}}
{{/layout_page}}
<!--running-a-rust-web-server/src/templates/layout_page.hbs-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Rust Web Server Example</title>
</head>
<body>
{{> page_content}}
</body>
</html>
Next we need to update our src/main.rs file. The root route is going to register the directory containing the
Handlebar templates and then pass data to the index template to render. The src/main.rs file should look like
the code below. Now you should be able to start the server (cargo run
) and view the rendered html!
use actix_web::{web, App, HttpRequest, HttpServer, HttpResponse};
use handlebars::Handlebars;
use std::collections::BTreeMap;
fn root(_req: HttpRequest) -> HttpResponse {
let mut handlebars = Handlebars::new();
handlebars
.register_templates_directory(".hbs", "./src/templates")
.unwrap();
let mut data = BTreeMap::new();
data.insert("paragraph_text", "This page was rendered using Actix-Web as the web server and handlebars as the templating language!");
let body = handlebars.render("index", &data).unwrap();
HttpResponse::Ok().body(body)
}
fn main() {
HttpServer::new(|| {
App::new()
.route("/", web::get().to(root))
})
.bind("127.0.0.1:8000")
.expect("Can not bind to port 8000")
.run()
.unwrap();
}