serve_dir does not serve an index path
In order to serve an index file, the following is currently required:
let static_dir = PathBuf::from("/some/path");
app.at("/")
.get(|_| async { Ok(Body::from_file(static_dir.join("index.html")).await?) })
.serve_dir(static_dir)?;
Many uses of serve_dir would want to attach an index route, so either this pattern should be documented, or serve_dir/ServeDir should support the definition of an index route/file.
@jbr Any idea how to avoid the error?
error[E0373]: closure may outlive the current function, but it borrows `static_dir`, which is owned by the current function
--> src/main.rs:431:10
|
431 | .get(|_| async { Ok(Body::from_file(static_dir.join("index.html")).await?) })
| ^^^ ---------- `static_dir` is borrowed here
| |
| may outlive borrowed value `static_dir`
|
note: function requires argument type to outlive `'static`
--> src/main.rs:430:1
|
430 | / app.at("/")
431 | | .get(|_| async { Ok(Body::from_file(static_dir.join("index.html")).await?) })
| |_________________________________________________________________________________^
help: to force the closure to take ownership of `static_dir` (and any other referenced variables), use the `move` keyword
|
431 | .get(move |_| async { Ok(Body::from_file(static_dir.join("index.html")).await?) })
| ^^^^^^^^
error[E0505]: cannot move out of `static_dir` because it is borrowed
--> src/main.rs:432:16
|
430 | / app.at("/")
431 | | .get(|_| async { Ok(Body::from_file(static_dir.join("index.html")).await?) })
| |__________---____________________________----------______________________________- argument requires that `static_dir` is borrowed for `'static`
| | |
| | borrow occurs due to use in closure
| borrow of `static_dir` occurs here
432 | .serve_dir(static_dir)?;
| ^^^^^^^^^^ move out of `static_dir` occurs here
I accomplished this by setting a separate handler for just the index file:
fn main() {
// ...
app.at("/").get(index);
app.at("/").serve_dir("static/").unwrap();
// ...
}
async fn index(_req: tide::Request<AppState>) -> tide::Result<Response> {
let mut res = Response::new(StatusCode::Ok);
res.set_body(Body::from_file("static/index.html").await.unwrap());
Ok(res)
}
The issue is when you need to calculate the directory at run time. The closure cannot be Fn if it captures other than a shared reference, but then that reference needs to be static. I think the only way to work around it is with OnceCell/lazy_static which requires an extra dependency and isn't great UX to say the least.
I suppose that if the alternative is returning 404, it'd be better that serve_dir automatically looks for an index.html imho.