Given the following code snippet:
mod handlers;
mod utils;
use actix_files;
use actix_web::{middleware::Logger, web, App, HttpServer};
use handlers::upload_handler;
use std::path::Path;
use tokio::fs;
#[actix_web::main]
async fn main() -> std::io::Result<()> {
env_logger::init_from_env(env_logger::Env::new().default_filter_or("debug"));
if !Path::new("./upload").exists() {
fs::create_dir("./upload").await?;
}
HttpServer::new(|| {
App::new()
.wrap(Logger::default())
.service(web::resource("/upload").route(web::post().to(upload_handler::upload_handler)))
.service(actix_files::Files::new("/", "./src/static").index_file("index.html"))
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
Why does swapping the lines serving the static file index.html
and handling the upload break the code? With the lines in the following order
.service(actix_files::Files::new("/", "./src/static").index_file("index.html"))
.service(web::resource("/upload").route(web::post().to(upload_handler::upload_handler)))
uploading a file (i.e., creating a POST
request) will result in a error:
POST http://127.0.0.1:8080/upload 405 (Method Not Allowed)
The documentation for actix-files' Files
says:
Implementation Notes
If the mount path is set as the root path
/
, services registered after this one will be inaccessible. Register more specific handlers and services first.
In general, .service()
s are processed in the order added to your App
/Scope
. In this case actix-files is at the root and vacuously handles all paths, and thus would handle the /upload
path as well and not give the resource a chance.