Skip to content

Commit 05bc8ea

Browse files
committed
Add fallback to try to serve index.html when trying to read a directory
Signed-off-by: Radu Matei <[email protected]>
1 parent 95f70b1 commit 05bc8ea

File tree

4 files changed

+30
-12
lines changed

4 files changed

+30
-12
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
target/
2+
.spin/

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "spin-static-fs"
33
version = "0.1.0"
44
edition = "2021"
5-
authors = ["Radu Matei <radu.matei@fermyon.com>"]
5+
authors = ["Fermyon Engineering <engineering@fermyon.com>"]
66

77
[lib]
88
crate-type = ["cdylib"]

spin.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ spin_version = "1"
22
name = "spin-static-fs"
33
version = "0.1.0"
44
description = "A simple static server for Spin."
5-
authors = [ "Radu Matei <radu@fermyon.com>" ]
6-
trigger = {type = "http", base = "/" }
5+
authors = ["Fermyon Engineering <engineering@fermyon.com>"]
6+
trigger = { type = "http", base = "/" }
77

88
# For more on configuring a component, see: https://spin.fermyon.dev/configuration/
99
[[component]]
@@ -13,4 +13,4 @@ files = [{ source = "", destination = "/" }]
1313
[component.trigger]
1414
route = "/..."
1515
[component.build]
16-
command = "make"
16+
command = "make"

src/lib.rs

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use std::{
1010
fs::File,
1111
hash::{Hash, Hasher},
1212
io::Read,
13+
path::PathBuf,
1314
};
1415

1516
/// The default value for the cache control header.
@@ -27,6 +28,8 @@ const BROTLI_ENCODING: &str = "br";
2728
const PATH_INFO_HEADER: &str = "spin-path-info";
2829
// Environment variable for the fallback path
2930
const FALLBACK_PATH_ENV: &str = "FALLBACK_PATH";
31+
/// Directory fallback path (trying to map `/about/` -> `/about/index.html`).
32+
const DIRECTORY_FALLBACK_PATH: &str = "index.html";
3033

3134
/// Common Content Encodings
3235
#[derive(Debug, Eq, PartialEq)]
@@ -83,15 +86,29 @@ fn serve(req: Request) -> Result<Response> {
8386
let body = match FileServer::read(path, &enc) {
8487
// requested file was found
8588
Ok(b) => Some(b),
86-
Err(e) => match std::env::var(FALLBACK_PATH_ENV) {
87-
// try to read the fallback path
88-
Ok(fallback_path) => FileServer::read(fallback_path.as_str(), &enc).ok(),
89-
// fallback path config not found
90-
Err(_) => {
91-
eprintln!("Cannot read file: {e:?}");
92-
None
89+
Err(e) => {
90+
// if the error is because the path points to a directory, attempt to read `index.html`
91+
// from the directory. This is because most static file generators will generate this
92+
// file structure (where `/about` should be mapped to `/about/index.html`).
93+
eprintln!("Cannot find file {path}. Attempting fallback.");
94+
// TODO: ideally, we would return better errors throughout the implementation.
95+
if e.to_string().contains("Is a directory") {
96+
let path = PathBuf::from(path).join(DIRECTORY_FALLBACK_PATH);
97+
let path = path.to_str().context("cannot convert path to string")?;
98+
eprintln!("Attempting fallback {path}");
99+
FileServer::read(path, &enc).ok()
100+
} else {
101+
match std::env::var(FALLBACK_PATH_ENV) {
102+
// try to read the fallback path
103+
Ok(fallback_path) => FileServer::read(fallback_path.as_str(), &enc).ok(),
104+
// fallback path config not found
105+
Err(_) => {
106+
eprintln!("Cannot read file: {e:?}");
107+
None
108+
}
109+
}
93110
}
94-
},
111+
}
95112
};
96113

97114
let etag = FileServer::get_etag(body.clone());

0 commit comments

Comments
 (0)