Skip to content

Commit d78d645

Browse files
edde746claude
andcommitted
Split fallback into api_not_found + serve_spa
serve_spa serving API responses was a misnamed abstraction. Restore single-purpose handlers and dispatch from a small `fallback` based on path prefix. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent cd31ef1 commit d78d645

1 file changed

Lines changed: 21 additions & 14 deletions

File tree

src/api/frontend.rs

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,26 @@ struct Asset;
1717
pub fn routes() -> Router<AppState> {
1818
Router::new()
1919
.route("/assets/{*path}", get(serve_asset))
20-
.fallback(get(serve_spa))
20+
.fallback(get(fallback))
21+
}
22+
23+
/// Catch-all for unmatched routes. Dispatches API paths to a JSON-404
24+
/// handler and everything else to the SPA shell. A `/api/{*rest}` route
25+
/// would be cleaner but matchit refuses to register a glob that overlaps
26+
/// existing `/api/{project_id}/...` ingest routes.
27+
async fn fallback(uri: Uri) -> axum::response::Response {
28+
if uri.path().starts_with("/api/") {
29+
api_not_found().await.into_response()
30+
} else {
31+
serve_spa().await.into_response()
32+
}
33+
}
34+
35+
async fn api_not_found() -> impl IntoResponse {
36+
(
37+
StatusCode::NOT_FOUND,
38+
Json(json!({ "detail": "not found" })),
39+
)
2140
}
2241

2342
async fn serve_asset(Path(path): Path<String>) -> impl IntoResponse {
@@ -36,19 +55,7 @@ async fn serve_asset(Path(path): Path<String>) -> impl IntoResponse {
3655
}
3756
}
3857

39-
async fn serve_spa(uri: Uri) -> impl IntoResponse {
40-
// Unmatched /api/* requests return JSON 404 instead of falling through
41-
// to the SPA HTML — sentry-cli (and any other API client) expects JSON
42-
// and "200 OK text/html" surfaces as "not a JSON response". Can't use
43-
// a `/api/{*rest}` route here because matchit refuses to register a
44-
// glob that overlaps existing `/api/{project_id}/...` ingest routes.
45-
if uri.path().starts_with("/api/") {
46-
return (
47-
StatusCode::NOT_FOUND,
48-
Json(json!({ "detail": "not found" })),
49-
)
50-
.into_response();
51-
}
58+
async fn serve_spa() -> impl IntoResponse {
5259
match Asset::get("index.html") {
5360
Some(content) => (
5461
StatusCode::OK,

0 commit comments

Comments
 (0)