Skip to content

Commit 18109da

Browse files
Add html_as_default_extension option to ServeDir
This mirrors the common behaviour of file servers
1 parent aeca262 commit 18109da

File tree

2 files changed

+30
-8
lines changed

2 files changed

+30
-8
lines changed

tower-http/src/services/fs/serve_dir/mod.rs

+17-3
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ impl ServeDir<DefaultServeDirFallback> {
7676
precompressed_variants: None,
7777
variant: ServeVariant::Directory {
7878
append_index_html_on_directories: true,
79+
html_as_default_extension: true,
7980
},
8081
fallback: None,
8182
call_fallback_on_method_not_allowed: false,
@@ -105,16 +106,27 @@ impl<F> ServeDir<F> {
105106
/// Defaults to `true`.
106107
pub fn append_index_html_on_directories(mut self, append: bool) -> Self {
107108
match &mut self.variant {
108-
ServeVariant::Directory {
109-
append_index_html_on_directories,
110-
} => {
109+
ServeVariant::Directory { append_index_html_on_directories, .. } => {
111110
*append_index_html_on_directories = append;
112111
self
113112
}
114113
ServeVariant::SingleFile { mime: _ } => self,
115114
}
116115
}
117116

117+
/// If the requested path doesn't specify a file extension, append `.html`.
118+
///
119+
/// Defaults to `true`.
120+
pub fn html_as_default_extension(mut self, append: bool) -> Self {
121+
match &mut self.variant {
122+
ServeVariant::Directory { html_as_default_extension, .. } => {
123+
*html_as_default_extension = append;
124+
self
125+
}
126+
ServeVariant::SingleFile { mime: _ } => self,
127+
}
128+
}
129+
118130
/// Set a specific read buffer chunk size.
119131
///
120132
/// The default capacity is 64kb.
@@ -443,6 +455,7 @@ opaque_future! {
443455
enum ServeVariant {
444456
Directory {
445457
append_index_html_on_directories: bool,
458+
html_as_default_extension: bool,
446459
},
447460
SingleFile {
448461
mime: HeaderValue,
@@ -454,6 +467,7 @@ impl ServeVariant {
454467
match self {
455468
ServeVariant::Directory {
456469
append_index_html_on_directories: _,
470+
html_as_default_extension: _,
457471
} => {
458472
let path = requested_path.trim_start_matches('/');
459473

tower-http/src/services/fs/serve_dir/open_file.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ pub(super) async fn open_file(
5959
let mime = match variant {
6060
ServeVariant::Directory {
6161
append_index_html_on_directories,
62+
html_as_default_extension,
6263
} => {
6364
// Might already at this point know a redirect or not found result should be
6465
// returned which corresponds to a Some(output). Otherwise the path might be
@@ -67,6 +68,7 @@ pub(super) async fn open_file(
6768
&mut path_to_file,
6869
req.uri(),
6970
append_index_html_on_directories,
71+
html_as_default_extension,
7072
)
7173
.await
7274
{
@@ -254,18 +256,23 @@ async fn maybe_redirect_or_append_path(
254256
path_to_file: &mut PathBuf,
255257
uri: &Uri,
256258
append_index_html_on_directories: bool,
259+
html_as_default_extension: bool,
257260
) -> Option<OpenFileOutput> {
258-
if !is_dir(path_to_file).await {
261+
if is_dir(path_to_file).await == Some(false) {
259262
return None;
260263
}
261264

262-
if !append_index_html_on_directories {
265+
if !append_index_html_on_directories && !html_as_default_extension {
263266
return Some(OpenFileOutput::FileNotFound);
264267
}
265268

266-
if uri.path().ends_with('/') {
269+
let path = uri.path();
270+
if append_index_html_on_directories && path.ends_with('/') {
267271
path_to_file.push("index.html");
268272
None
273+
} else if html_as_default_extension && path_to_file.extension().is_none() {
274+
path_to_file.set_extension("html");
275+
None
269276
} else {
270277
let location =
271278
HeaderValue::from_str(&append_slash_on_path(uri.clone()).to_string()).unwrap();
@@ -283,10 +290,11 @@ fn try_parse_range(
283290
})
284291
}
285292

286-
async fn is_dir(path_to_file: &Path) -> bool {
293+
async fn is_dir(path_to_file: &Path) -> Option<bool> {
287294
tokio::fs::metadata(path_to_file)
288295
.await
289-
.map_or(false, |meta_data| meta_data.is_dir())
296+
.ok()
297+
.map(|meta_data| meta_data.is_dir())
290298
}
291299

292300
fn append_slash_on_path(uri: Uri) -> Uri {

0 commit comments

Comments
 (0)