2

Normally React builds are just served as static files from a webserver like nginx but I want to serve the front end static files using Rust Rocket from a React build and I'm struggling to find a nice way of doing it, here are the routes I've set up

#[get("/")]
 fn index() -> io::Result<NamedFile> {
NamedFile::open("build/index.html")
}

#[get("/<file..>", rank = 2)]
fn build_dir(file: PathBuf) -> Option<NamedFile> {
    NamedFile::open(Path::new("build/").join(file)).ok()
}

#[get("/static/<file..>")]
fn static_dir(file: PathBuf) -> Option<NamedFile> {
    NamedFile::open(Path::new("build/static/").join(file)).ok()
}

fn rocket() -> rocket::Rocket {
    rocket::ignite()
        .mount("/", routes![index, build_dir])
        .mount("/static", routes![static_dir])
}

This works but it doesn't serve things like favicons or the manifest.json file and I'd rather not add specific routes for each of these files, has anybody solved this problem in a better way ?

Please see the project code here

NiallJG
  • 1,881
  • 19
  • 22

1 Answers1

2

/<path..> pattern is recursive, you don't need to include subfolders. Just serve your whole build on / and it will work as expected.

The only thing to worry about is redirecting from ambiguous page paths like /.

#![feature(proc_macro_hygiene, decl_macro)]

use std::{io, path::{Path, PathBuf}};

use rocket::{get, routes, response::{NamedFile, Redirect}};

#[get("/")]
fn index() -> Redirect {
    Redirect::permanent("/index.html")
}

#[get("/<file..>")]
fn build_dir(file: PathBuf) -> io::Result<NamedFile> {
    NamedFile::open(Path::new("build/").join(file))
}

fn rocket() -> rocket::Rocket {
    rocket::ignite()
        .mount("/", routes![index, build_dir])
}

fn main() {
    rocket().launch();
}
Yamirui
  • 169
  • 6