Deploy A Rust Website on Heroku
Rust is a blazing fast and memory efficient programming language that's used by tech companies like Firefox, Dropbox and Cloudflare to name a few.
Today we are going to focus on the web side of Rust, hence the name "Rocket".
Well, per the official website rocket.rs - "Rocket is a web framework for Rust that makes it simple to write fast, secure web applications without sacrificing flexibility, usability, or type safety". That's a self explanatory introduction, nothing more I can add.
Having completed the formalities, let's launch some Rockets.
Setting up Rocket
To run Rocket locally we need to have installed a compatible version of Rust (install Rust), and since Rocket uses advanced and unstable features of Rust we'll need to use the nightly
version of Rust. To configure the nightly version of Rust as the default toolchain run the following command on your terminal.
rustup default nightly
or you can set it as the default toolchain for your Rocket project only by running the following command inside the Rocket project's directory after having created it.
rustup override set nightly
Now, proceed with creating a new cargo project
Cargo new rocket-demo-app --bin
# switch into the project's directory
cd rocket-demo-app
Add Rocket as a dependency in the Cargo.toml
file found on the project's root.
[dependencies]
rocket = "0.4.7"
Update the src/main.rs
file by adding a bit of Rocket code
#![feature(proc_macro_hygiene, decl_macro)]
#[macro_use] extern crate rocket;
#[get("/")]
fn index() -> &'static str {
"This is my Rocket Demo app"
}
fn main() {
rocket::ignite().mount("/", routes![index]).launch();
}
Then run the following command,
Cargo run
Rust will fetch all the dependencies used by Rocket, make a dev build of our project and run the binary code, launching our project.
Finished dev [unoptimized + debuginfo] target(s) in 3m 00s
Running `target\debug\rocket-demo-app.exe`
🔧 Configured for development.
=> address: localhost
=> port: 8000
=> log: normal
=> workers: 8
=> secret key: generated
=> limits: forms = 32KiB
=> keep-alive: 5s
=> read timeout: 5s
=> write timeout: 5s
=> tls: disabled
🛰 Mounting /:
=> GET / (index)
🚀 Rocket has launched from http://localhost:8000
In the output above, Rocket has launched our project on the 8000
port, so to view it navigate to http://localhost:8000
.
All we did on the main/src.rs
file is declare an index route, mount it at the "/" path and launch our rocket app.
Rocket routes
Rocket applications center around routes and handlers, where a Rocket route
is simply a combination of parameters matching an incoming request and a handler that processes the request and returns a response.
A route is declared by annotating a function just as in the example above, the index route is:
#[get("/")]
fn index() -> &'static str {
"This is my Rocket Demo app"
}
Where the annotation at the top - #[get("/")]
is the route's attribute and the function that follows below it fn index()
is the route's handler.
Route mounting
Let's add a new route to our Rocket project. Add the following code after the index route.
#[get("/about")]
fn about() -> &'static str {
"This is the about page of my Rocket Demo app"
}
And re-run the cargo project.
When you try navigating to the /about
page, you'll see a 404: Not Found
error.
What happened?
Well, Rocket needs to mount routes before dispatching requests to them, that is the reason we have rocket::ignite().mount("/", routes![index]).launch();
inside the main()
function for the first route. Let's mount our _about page route too. Update the main()
function with the following code.
fn main(){
rocket::ignite().mount("/", routes![index, about]).launch();
}
Re-run cargo and try visiting the "/about" route again.
After declaring and mounting our routes, we call the lauch()
method which starts up the server and has our Rocket app up and running waiting for incoming requests to dispatch them accordingly.
For more on Rocket requests head to the official documentation
Before proceeding with the next step, use git to stage and commit all the changes done to the app.
git add . && git commit -m "initialize Rocket project"
Setting up Heroku
Start with creating an account on Heroku if you do not have one before proceeding.
Inside the Heroku dashboard add a new app and fill in it's details
Next, download and install the Heroku CLI, then proceed with running the following command inside the project's directory.
heroku login
Follow the instructions which will redirect you to your browser and let you log into your Heroku account.
Back on the project, link the remote Heroku app to your Rocket project with the following command.
heroku git:remote -a rocket-demo-app
Create a new file on the project's root and name it Procfile
without any extensions, add the following code into it.
web: ROCKET_PORT=$PORT ROCKET_KEEP_ALIVE=0 ./target/release/rocket-demo-app
Specify a nightly version of Rust to work with by creating another file on the project's root, naming it rust-toolchain
(without a file extension). The following nightly version is a good start:
nightly-2020-10-24
Commit the new changes.
heroku buildpacks:set emk/rust
Then push the changes to heroku.
git push heroku master
After finishing all it needs to do, the command-line tool will give you the link your app has been deployed to, open the link and view the deployed app.
remote: -----> Building application using Cargo
remote: Compiling rocket-demo v0.1.0 (/tmp/build_898d5ac6)
remote: Finished release [optimized] target(s) in 3.39s
remote: -----> Discovering process types
remote: Procfile declares types -> web
remote:
remote: -----> Compressing...
remote: Done: 1.5M
remote: -----> Launching...
remote: Released v6
remote: https://rocket-demo-app.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/rocket-demo-app.git
13450ef..0febf7c main -> main
Above is an example output you'd expect from the heroku-cli tool.
This is a nice start when delving into deploying Rust applications and in this particular case we were deploying a Rocket framework app on Heroku.
There is so much more to learn and experiment in this "fast, easy, and flexible" framework, this has just been a short intro into deploying it, more can be learnt here.
Go out there and launch some Rockets.