fix: serve SPA fallback with 200 instead of 404

`ServeDir::not_found_service` wraps the fallback in `SetStatus`, which forces
every response to `404 Not Found`. Client side routes such as `/note/<id>` and
`/about` were therefore served the correct `index.html` but with a 404 status.

Use `ServeDir::fallback` instead, which leaves the status untouched. A note that
genuinely does not exist is still reported as 404 by `/api/notes/<id>`.

Behind a reverse proxy this made effectively every document request show up as a
4xx, skewing error rate dashboards and triggering false alerts.

Fixes #217
This commit is contained in:
Matheus Leal
2026-09-03 16:09:40 -03:00
parent 1f180a2e53
commit 8034b1a501
2 changed files with 23 additions and 1 deletions
+4 -1
View File
@@ -51,8 +51,11 @@ async fn main() {
.merge(status_routes);
let index = format!("{}{}", config::FRONTEND_PATH.to_string(), "/index.html");
// SPA fallback: serve `index.html` for client side routes.
// `fallback` instead of `not_found_service`, as the latter forces a `404` status code,
// while the document itself is served successfully. A missing note is signalled by the API.
let serve_dir =
ServeDir::new(config::FRONTEND_PATH.to_string()).not_found_service(ServeFile::new(index));
ServeDir::new(config::FRONTEND_PATH.to_string()).fallback(ServeFile::new(index));
let app = Router::new()
.nest("/api", api_routes)
.fallback_service(serve_dir)