1
votes

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. Sorry for mistakes as i'm quite new in rust.

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

Edit1: I was getting type mismatch error but using pathBuf as answered in comments rescued me.

Edit2: By trying the code given in 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 buitl the backend with db integration and it is working fine as checked by curl commands and now i' trying to build front end and as first step trying to serve static files.

Edit3: The example which also helped me along with the answers here to solve this issue is https://github.com/actix/examples/tree/master/static_index

2
What is happening when you try your existing code? In what way is it not doing what you want?harmic
@harmic i have edited my question . Have a look if you could find something .Fatima Nasim
The second argument for fs::Files::new is the directory you want to serve. "." would be the current directory - which would be whatever directory you are running from, not the 'static' dir. Try putting the full path to the static dir.harmic
@yes thanks for explaining. i find that out. I'm also putting a good example of usage in my question.Fatima Nasim

2 Answers

5
votes

I am not sure what problem you're facing since the description is not detailed,however, I run the default example and 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"

hope this works for you

1
votes

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.