Skip to content

Commit 656ae1f

Browse files
authored
Merge pull request #31 from radu-matei/subdirectory-fallback
2 parents b881d30 + 10f6aa2 commit 656ae1f

File tree

4 files changed

+32
-12
lines changed

4 files changed

+32
-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_manifest_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: 27 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,31 @@ 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 site 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+
let directory_fallback = PathBuf::from(path).join(DIRECTORY_FALLBACK_PATH);
96+
if e.to_string().contains("Is a directory") && directory_fallback.exists() {
97+
let directory_fallback = directory_fallback
98+
.to_str()
99+
.context("cannot convert path to string")?;
100+
eprintln!("Attempting directory fallback {directory_fallback}");
101+
FileServer::read(directory_fallback, &enc).ok()
102+
} else {
103+
match std::env::var(FALLBACK_PATH_ENV) {
104+
// try to read the fallback path
105+
Ok(fallback_path) => FileServer::read(fallback_path.as_str(), &enc).ok(),
106+
// fallback path config not found
107+
Err(_) => {
108+
eprintln!("Cannot read file: {e:?}");
109+
None
110+
}
111+
}
93112
}
94-
},
113+
}
95114
};
96115

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

0 commit comments

Comments
 (0)