use headers::{HeaderMap, HeaderValue};
use hyper::StatusCode;
use std::fs::Metadata;
use std::path::PathBuf;
use crate::Result;
use crate::compression_static;
use crate::fs::meta::{FileMetadata, try_file_open, try_metadata, try_metadata_with_html_suffix};
use super::opts::DEFAULT_INDEX_FILES;
pub(super) fn file_metadata<'a>(
mut file_path: &'a mut PathBuf,
headers: &'a HeaderMap<HeaderValue>,
compression_static: bool,
mut index_files: &'a [&'a str],
) -> Result<FileMetadata<'a>, StatusCode> {
tracing::trace!("getting metadata for file {}", file_path.display());
match try_metadata(file_path) {
Ok((mut metadata, is_dir)) => {
let mut opened_file = None;
let mut resolved_exists = !is_dir;
if is_dir {
if index_files.is_empty() {
index_files = DEFAULT_INDEX_FILES;
}
for index in index_files {
tracing::debug!("dir: appending {} to the directory path", index);
file_path.push(index);
if let Ok((file, meta)) = try_file_open(file_path) {
metadata = meta;
opened_file = Some(file);
resolved_exists = true;
break;
}
file_path.pop();
let new_meta: Option<Metadata>;
(file_path, new_meta) = try_metadata_with_html_suffix(file_path);
if let Some(new_meta) = new_meta {
metadata = new_meta;
resolved_exists = true;
break;
}
}
if !resolved_exists && !index_files.is_empty() {
file_path.push(index_files.last().unwrap());
}
}
let precompressed = (compression_static && resolved_exists)
.then(|| compression_static::precompressed_variant(file_path, headers))
.flatten();
if let Some(ref variant) = precompressed {
metadata = variant.metadata.clone();
}
let precompressed_variant = precompressed.map(|p| (p.file_path, p.encoding));
if precompressed_variant.is_some() {
opened_file = None;
}
Ok(FileMetadata {
file_path,
metadata,
is_dir,
precompressed_variant,
file: opened_file,
})
}
Err(err) => {
let new_meta: Option<Metadata>;
(file_path, new_meta) = try_metadata_with_html_suffix(file_path);
let Some(new_meta) = new_meta else {
return Err(err);
};
let precompressed = compression_static
.then(|| compression_static::precompressed_variant(file_path, headers))
.flatten();
let metadata = match precompressed {
Some(ref variant) => variant.metadata.clone(),
None => new_meta,
};
let precompressed_variant = precompressed.map(|p| (p.file_path, p.encoding));
Ok(FileMetadata {
file_path,
metadata,
is_dir: false,
precompressed_variant,
file: None,
})
}
}
}