https://linen.dev logo
Actix and Static folder / files
# help
r
Hey, I'm trying to deploy an actix shuttleapp/webserver/api with a static html page on it, nothing fancy just a title atm. The api part works fine, but the static page just gives me
No such file or directory (os error 2)
I have added the shuttle_static_folder dependency as in the example, but it was never used in main.rs there. I'm sure it's me doing something stupid. I've somewhat extrapolated from the actix-websocket example:
Copy code
rust
use actix_files::NamedFile;
use actix_web::{ web::{self, ServiceConfig}, Responder };
use shuttle_actix_web::ShuttleActixWeb;

mod api;
mod models;

async fn index() -> impl Responder {
    NamedFile::open_async("./static/index.html")
        .await
        .map_err(|e| actix_web::error::ErrorInternalServerError(e))
}

#[shuttle_runtime::main]
async fn actix_web(
) -> ShuttleActixWeb<impl FnOnce(&mut ServiceConfig) + Send + Clone + 'static> {
    let config = move |cfg: &mut ServiceConfig| {
        cfg.service(web::resource("/").route(web::get().to(index)));
        cfg.service(api::openmeteo::openmeteo);
    };

    Ok(config.into())
}
Here is the repo: https://github.com/christ-offer/shuttle-actix-api
a
Hey there, shuttle requires you to use the
shuttle_static_folder
lib for static folder support - you can find more about this here https://docs.shuttle.rs/resources/shuttle-static-folder
r
I did have a look there, but I'm a bit of a big dumdum, so I wasnt sure what to do with it since the example was Axum hah, and the actix websocked example didnt use it, so i didnt really know
a
Oh poop sorry, I didn't read your message fully
r
😛
a
You need to supply it as a parameter in your main function
r
so wrap everything in main inside it?
a
So for example:
Copy code
fn actix(
#[shuttle_static_folder::StaticFolder] pub: PathBuf
) -> .... etc
r
something like this? or am I way off 😛
Copy code
rust
#[shuttle_runtime::main]
async fn actix_web(
    #[shuttle_static_folder::StaticFolder] static_folder: PathBuf,
) -> ShuttleActixWeb<impl FnOnce(&mut ServiceConfig) + Send + Clone + 'static> {
    let config = move |cfg: &mut ServiceConfig| {
        cfg.service(web::resource("/").route(web::get().to(index)));
        cfg.service(api::openmeteo::openmeteo);
    };

    Ok(config.into())
}
a
Basically, yeah! You need to pass the static folder in wherever you'd normally use the namedfile path
I'm not hugely experienced with actix but that's how it works in axum at least
r
alright, should probably update the example repo 😄
probably just an oversight, since its imported in the dependencies here: https://docs.shuttle.rs/examples/actix#websocket-actorless
a
Oh that's not ideal 😅 thanks for the feedback! We're working on condensing a lot of our examples into more general guides rather than trying to just have random specific examples so we'll try to keep this in mind
r
From a beginners perspective, some standards like a simple example implementation in earch framework for stuff like static folders would be quite useful 😛
huh?

https://cdn.discordapp.com/attachments/1101834617025200201/1101840035445219368/image.pngâ–¾

a
what version of
cargo-shuttle
are you using at the moment?
r
0.14.0
a
try updating cargo-shuttle with
cargo install cargo-shuttle --force
, should work again after that
r
still the same error:

https://cdn.discordapp.com/attachments/1101834617025200201/1101841949545214082/image.pngâ–¾

This is the current code:
Copy code
rust
use actix_files::NamedFile;
use actix_web::{ web::{self, ServiceConfig}, Responder };
use shuttle_actix_web::ShuttleActixWeb;
use std::path::PathBuf;

mod api;
mod models;

async fn index() -> impl Responder {
    NamedFile::open_async("./static/index.html")
        .await
        .map_err(|e| actix_web::error::ErrorInternalServerError(e))
}

#[shuttle_runtime::main]
async fn actix_web(
    #[shuttle_static_folder::StaticFolder] static_folder: PathBuf,
) -> ShuttleActixWeb<impl FnOnce(&mut ServiceConfig) + Send + Clone + 'static> {
    let config = move |cfg: &mut ServiceConfig| {
        cfg.service(web::resource("/").route(web::get().to(index)));
        cfg.service(api::openmeteo::openmeteo);
    };

    Ok(config.into())
}
a
try updating all of your shuttle deps in cargo.toml to 0.15.0
r
yeah that makes sense...
hah
a
I think there might have been some breaking resource changes 😂 I can't remember exactly, but yeah
r
well, deploy doesnt fail, but still
No such file or directory (os error 2)
hah
api still works fine tho:

https://cdn.discordapp.com/attachments/1101834617025200201/1101843467195383918/image.pngâ–¾

https://cdn.discordapp.com/attachments/1101834617025200201/1101843605880066048/image.pngâ–¾

and it should have access
a
Does the function for returning static files use the pathbuf passed in the main function?
r
ehhh exposing my ignorance here 😛 not as i can see
i just copied what i could from the examples in the docs hah
a
Hmmm let me think
r
amedFile::open_async("./static/index.html")
so this needs the pathbuf somehow?
a
yeah so you'd just pass the pathbuf in as a parameter
although I'm not sure exactly how handlers work in actix
i guess you could try throwing something like this in the main function and seeing what happens:
Copy code
let static_folder = static_folder.join("index.html");

    let index = NamedFile::open_async(static_folder)
        .await
        .map_err(|e| actix_web::error::ErrorInternalServerError(e))
r
doesnt satisfy the namedfile handler Responder thingy, hah
ahh saturdays 😄
a
hmmm