index : static-web-server.git

ascending towards madness

author Syrus Akbary <me@syrusakbary.com> 2023-03-05 20:05:58.0 +00:00:00
committer GitHub <noreply@github.com> 2023-03-05 20:05:58.0 +00:00:00
commit
7ed7b0398ee0c3faf1ce553e8345b92d1fdedebc [patch]
tree
1e6f92a410af8103a1e92a72bb3492c0732ce249
parent
87a0896bf0fcf1f2bb2d8e9868127484ddba995f
download
7ed7b0398ee0c3faf1ce553e8345b92d1fdedebc.tar.gz

feat: add support for .html prefixing when request path doesn't exist (#180)

* Added support for path serving with html wrapping
* Elide explicit 'a lifetime

---------

Co-authored-by: Jose Quintana <joseluisquintana20@gmail.com>

Diff

 src/static_files.rs | 44 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 43 insertions(+), 1 deletion(-)

diff --git a/src/static_files.rs b/src/static_files.rs
index d8fbed4..7c915fb 100644
--- a/src/static_files.rs
+++ b/src/static_files.rs
@@ -138,11 +138,32 @@ pub async fn handle<'a>(opts: &HandleOpts<'a>) -> Result<(Response<Body>, bool),
    Ok((resp, is_precompressed))
}

/// Returns the result of trying to append `.html` to the file path.
/// * If the prefixed html path exists, it mutates the path to the prefixed one and returns the Metadata
/// * If the prefixed html path doesn't exist, it reverts the path to it's original value
fn prefix_file_html_metadata(file_path: &mut PathBuf) -> (&mut PathBuf, Option<Metadata>) {
    tracing::debug!("file: appending .html to the path");
    if let Some(filename) = file_path.file_name() {
        let owned_filename = filename.to_os_string();
        let mut owned_filename_with_html = owned_filename.clone();
        owned_filename_with_html.push(".html");
        file_path.set_file_name(owned_filename_with_html);
        if let Ok(meta_res) = file_metadata(file_path.as_ref()) {
            let (meta, _) = meta_res;
            return (file_path, Some(meta));
        } else {
            // We roll-back to the previous filename
            file_path.set_file_name(owned_filename);
        }
    }
    (file_path, None)
}

/// Returns the final composed metadata information (tuple) containing
/// the Arc `PathBuf` reference wrapper for the current `file_path` with its file metadata
/// as well as its optional pre-compressed variant.
async fn composed_file_metadata<'a>(
    file_path: &'a mut PathBuf,
    mut file_path: &'a mut PathBuf,
    headers: &'a HeaderMap<HeaderValue>,
    compression_static: bool,
) -> Result<(&'a PathBuf, Metadata, bool, Option<(PathBuf, &'a str)>), StatusCode> {
@@ -170,12 +191,33 @@ async fn composed_file_metadata<'a>(
                // Also noting that it's still a directory request
                if let Ok(meta_res) = file_metadata(file_path.as_ref()) {
                    (meta, _) = meta_res
                } else {
                    // We remove the appended index.html
                    file_path.pop();
                    let new_meta: Option<Metadata>;
                    (file_path, new_meta) = prefix_file_html_metadata(file_path);
                    if let Some(new_meta) = new_meta {
                        meta = new_meta;
                    } else {
                        // We append the index.html to preserve previous behavior
                        file_path.push("index.html");
                    }
                }
            }

            Ok((file_path, meta, is_dir, None))
        }
        Err(err) => {
            if err == StatusCode::NOT_FOUND {
                // If the file path doesn't exist, we try to find the path suffixed with `.html`.
                // For example: `/posts/article` will fallback to `/posts/article.html`
                let new_meta: Option<Metadata>;
                (file_path, new_meta) = prefix_file_html_metadata(file_path);
                if let Some(new_meta) = new_meta {
                    return Ok((file_path, new_meta, false, None));
                }
            }

            // Second pre-compressed variant check for the given file path
            if compression_static && !tried_precompressed {
                if let Some((path, meta, ext)) =