Fatima Nasim
Fatima Nasim

Reputation: 41

Serving static files with actix-web 2.0

I'm struggling with actix-web 2.0 framework of rust. I want my rust server to serve the my index.html file but most of the help available is of older versions and hence a lot has changed in newer version. I tried following code but it's not working for actix-web 2.0. Please suggest some working solution in actix-web 2.0.

use actix_files::NamedFile;
use actix_web::{HttpRequest, Result};
async fn index(req: HttpRequest) -> Result<NamedFile> {
    Ok(NamedFile::open(path_to_file)?)
}

By trying the code given in the answer I could serve a single html file but it is unable to load the linked JavaScript file. I have tried the following approach suggested in https://actix.rs/docs/static-files/ to serve the directory.

#[actix_rt::main]
async fn main() -> std::io::Result<()> {
    dotenv::dotenv().ok();
    std::env::set_var("RUST_LOG", "actix_web=debug");
    let database_url = std::env::var("DATABASE_URL").expect("set DATABASE_URL");

    // create db connection pool
    let manager = ConnectionManager::<PgConnection>::new(database_url);
    let pool: Pool = r2d2::Pool::builder()
        .build(manager)
        .expect("Failed to create pool.");
    
    //Serving the Registration and sign-in page
    async fn index(_req: HttpRequest) -> Result<NamedFile> {
        let path: PathBuf = "./static/index.html".parse().unwrap();
        Ok(NamedFile::open(path)?)
    }

    // Start http server
    HttpServer::new(move || {
        App::new()
            .data(pool.clone())
            .service(fs::Files::new("/static", ".").show_files_listing())
            .route("/", web::get().to(index))
            .route("/users", web::get().to(handler::get_users))
            .route("/users/{id}", web::get().to(handler::get_user_by_id))
            .route("/users", web::post().to(handler::add_user))
            .route("/users/{id}", web::delete().to(handler::delete_user))
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

Above is my main method. In browser console I'm still getting the error that unable to load the Registration.js resource. Following is my folder structure:

-migrations
-src
  -main.rs
  -handler.rs
  -errors.rs
  -models.rs
  -schema.rs
-static
 -index.html
 -Registration.js
-target
Cargo.toml
.env
Cargo.lock
diesel.toml

I have already built the backend with DB integration and it is working fine as checked by curl commands and now I'm trying to build front end and as first step trying to serve static files.

Upvotes: 3

Views: 12435

Answers (3)

Maicmi
Maicmi

Reputation: 1104

Please see the below code that it works for the whole subdirectories:

main.rs

use actix_files as fs;
use actix_web::{App, HttpServer};

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new().service(
            fs::Files::new("/", "./public")
                .show_files_listing()
                .index_file("index.html")
                .use_last_modified(true),
        )
    })
    .bind("0.0.0.0:8000")?
    .run()
    .await
}

Cargo.toml

[package]
name = "actixminimal"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
actix-web = "4"
actix-files = "0.6.2"

It perform file serving very fast ever I'd tried.

In this case, you can create a "public" or you can use your own "static" folder (then change your code related to the folder name) or you can export the static files from your web framework. I use GatsbyJS and I use deploy parameter to "public" folder. I share it on my github. https://github.com/openmymai/actixminimal.git

Upvotes: 4

cperez08
cperez08

Reputation: 749

I am not sure what problem you're facing since the description is not detailed, however, I ran the default example and it is working.

use actix_files::NamedFile;
use actix_web::{HttpRequest, Result};
use std::path::PathBuf;

/// https://actix.rs/docs/static-files/
async fn index(_req: HttpRequest) -> Result<NamedFile> {
    let path: PathBuf = "./files/index.html".parse().unwrap();
    Ok(NamedFile::open(path)?)
}

#[actix_rt::main]
async fn main() -> std::io::Result<()> {
    use actix_web::{web, App, HttpServer};

    HttpServer::new(|| App::new().route("/", web::get().to(index)))
        .bind("127.0.0.1:8088")?
        .run()
        .await
}

project structure

- files/index.html
- src/index.rs
- cargo.toml

dependencies

[dependencies]
actix-web = "2.0.0"
actix-files = "0.2.2"
actix-rt = "1.1.1"

Upvotes: 9

Alexander Korolev
Alexander Korolev

Reputation: 327

If you want to really embed resources into executable you can use https://crates.io/crates/actix-web-static-files.

It uses build.rs to prepare resources and later you can just have single executable without dependencies.

As extra it support npm based builds out of the box.

Basically I am an author of this crate. There are versions both for 2.x and 3.x versions of actix-web.

Upvotes: 7

Related Questions