How to host a html page in actix-web 2.0

So in actix-web "0.7.19" I managed to build the following which hosts a webpage:

use actix_web::{App, fs, server::HttpServer};

fn main()
{
    HttpServer::new(||
    {
        App::new()
        .handler
        (
            "/", fs::StaticFiles::new("main_page")
            .unwrap()
            .show_files_listing()
            .index_file("index.html")
        )
        .finish()
    })
    .bind("127.0.0.1:8088")
    .unwrap()
    .run();
}

and in actix-web "2.0" I created some request handlers:

use actix_web::{App, get, HttpResponse, HttpServer, Responder, web};

async fn index() -> impl Responder
{
    HttpResponse::Ok().body("Hello world!")
}

async fn index2() -> impl Responder
{
    HttpResponse::Ok().body("Hello world again!")
}

#[get("/hello")]
async fn index3() -> impl Responder
{
    HttpResponse::Ok().body("Hey there!")
}

#[actix_rt::main]
async fn main() -> std::io::Result<()>
{
    HttpServer::new(||
    {
        App::new()
        .route("/", web::get().to(index))
        .route("/again", web::get().to(index2))
        .service(index3)
        .service(web::scope("/app").route("/index.html", web::get().to(index)))
    })
    .bind("127.0.0.1:8088")?
    .run()
    .await
}

and I'm trying to merge the two so that I have a server that hosts a html file and also handles requests, the thing is I can't put both actix 2.0 and actix 0.7.19 in my dependencies. Actix 2.0 misses somethings that are in actix 0.7.19 and 0.7.19 misses the things needed from 2.0. Any suggestions?

Not sure if you've seen this Static Files but this seems to be how to do it in the latest actix.

From that, if you have a hard coded file, it seems you would do

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

Hi what should I put for the "path_to_file" if my "index.html" is inside a folder called "main_page"? Also it seems my css and javascript associated with the file doesn't run with "index.html" - what can I do to fix this issue? Thank you for all your help.

Edit: Figured out the pathing, for some reason it didn't work the first time.

The path should be relative to where you called cargo run. As for css and Javascript, those are fetched via separate web calls, so you must have endpoints for those files too.

Part of my actix-web server code:

    HttpServer::new(move || {
        App::new()
            .route("/visualizer.css", web::get().to(get_css))
            // Lots of other stuff

and

fn get_css() -> impl Responder {
    let css = fs::read_to_string("./html/visualizer.css").expect("Cannot read CSS file");
    HttpResponse::Ok()
        .content_type("text/css")
        .body(css)
}

Note that you should prefer NamedFiled to std::fs::read when responding with a file.

Hi Alice,
my main_page folder is located right next to the src folder and I cargo run just outside both main_page and src. Under these conditions what should my path be? Also I'm not sure what you mean by endpoints. I had it so that the html file calls upon .css and .javascript.

Edit: Figured out the pathing, for some reason it didn't work the first time.

Thanks. I didn't know about NamedFile. Why should I use it?

It returns a file handle. I then have to create a mutable buffer and do a read_to_string(&mut buf) on it instead of just fs::read_to_string().

Hi alan,
can I ask why you're calling css using the server instead of referencing it in the html file? Is it just better practice?

Not instead, but as well as. CSS is referenced in HTML, and that's why browser will pull it from the same server.

Sorry, could someone explain why my css and javascript stopped getting called when I call on the html file as drewkett showed? It used to be fine in the previous way of hosting index.html.

Your original code was probably sharing the whole folder "main_page", so it was automatically handling serving the css files as well. To replicate that, it looks like instead you'll need to do the following

use actix_files::fs;
App::new()
       .route("/", web::get().to(index))
       .route("/again", web::get().to(index2))
      .service(fs::Files::new("/app", ".").show_files_listing())

or the following if you still have the ./main_page/ folder

use actix_files::fs;
App::new()
       .route("/", web::get().to(index))
       .route("/again", web::get().to(index2))
      .service(fs::Files::new("/app", "./main_page").show_files_listing())

Edit:
This information can also be found in the original link i shared, just so you know where to find it in the future.

Hi drew, thanks for all your help - one question though, what route do I head into to see it open the files? I tried localhost:8088/app but it doesn't seem to work.

Sorry you can add an index_file() command to that like this

fs::Files::new("/app", "./main_page").show_files_listing().index_file("index.html")

All that is doing is making /app point to the same place as /app/index.html

1 Like

Super helpful, thank you very much.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.