tide icon indicating copy to clipboard operation
tide copied to clipboard

serve_dir does not serve an index path

Open jbr opened this issue 5 years ago • 3 comments

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 avatar Jun 17 '20 22:06 jbr

@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

bbigras avatar Sep 16 '20 21:09 bbigras

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)
}

zelda-at-tempus avatar Oct 27 '20 15:10 zelda-at-tempus

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.

najamelan avatar Nov 23 '20 19:11 najamelan