Skip to content

Commit 0bb46db

Browse files
committed
Check for 404 before redirecting on no-extension paths
The commit improves routing logic by checking if a path would result in a 404 fixes #971 before adding a trailing slash. This prevents unnecessary redirects when a custom 404 handler exists.
1 parent ae30d82 commit 0bb46db

File tree

1 file changed

+61
-9
lines changed

1 file changed

+61
-9
lines changed

src/webserver/routing.rs

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,35 @@ where
122122
let path_with_ext = path.with_extension(SQL_EXTENSION);
123123
match find_file(&path_with_ext, SQL_EXTENSION, store).await? {
124124
Some(action) => Ok(action),
125-
None => Ok(Redirect(append_to_path(path_and_query, FORWARD_SLASH))),
125+
None => {
126+
// Before redirecting to add trailing slash, check if the result would be a 404
127+
let mut path_with_slash = path.clone();
128+
path_with_slash.push(INDEX);
129+
match find_file(&path_with_slash, SQL_EXTENSION, store).await? {
130+
Some(_) => {
131+
// There's an index.sql file, so redirect to trailing slash
132+
Ok(Redirect(append_to_path(path_and_query, FORWARD_SLASH)))
133+
}
134+
None => {
135+
// No index.sql file found. Check if this would result in a custom 404
136+
let not_found_result = find_not_found(&path_with_slash, store).await?;
137+
match not_found_result {
138+
CustomNotFound(_) => {
139+
// There's a custom 404.sql that would handle this, don't redirect
140+
Ok(not_found_result)
141+
}
142+
NotFound => {
143+
// No custom 404, so redirect to trailing slash for consistency
144+
Ok(Redirect(append_to_path(path_and_query, FORWARD_SLASH)))
145+
}
146+
Execute(_) | Redirect(_) | Serve(_) => {
147+
// These shouldn't happen from find_not_found, but handle them
148+
Ok(not_found_result)
149+
}
150+
}
151+
}
152+
}
153+
}
126154
}
127155
}
128156
}
@@ -332,6 +360,22 @@ mod tests {
332360

333361
assert_eq!(expected, actual);
334362
}
363+
364+
#[tokio::test]
365+
async fn no_extension_path_that_would_result_in_404_does_not_redirect() {
366+
let actual = do_route("/nonexistent", Default, None).await;
367+
let expected = custom_not_found("404.sql");
368+
369+
assert_eq!(expected, actual);
370+
}
371+
372+
#[tokio::test]
373+
async fn no_extension_path_that_would_result_in_404_does_not_redirect_with_site_prefix() {
374+
let actual = do_route("/prefix/nonexistent", Default, Some("/prefix/")).await;
375+
let expected = custom_not_found("404.sql");
376+
377+
assert_eq!(expected, actual);
378+
}
335379
}
336380

337381
mod not_found {
@@ -402,8 +446,8 @@ mod tests {
402446
}
403447

404448
mod redirect {
405-
use super::StoreConfig::Default;
406-
use super::{do_route, redirect};
449+
use super::StoreConfig::{Default, Empty};
450+
use super::{custom_not_found, do_route, redirect};
407451

408452
#[tokio::test]
409453
async fn path_without_site_prefix_redirects_to_site_prefix() {
@@ -414,26 +458,34 @@ mod tests {
414458
}
415459

416460
#[tokio::test]
417-
async fn no_extension_and_no_corresponding_file_redirects_with_trailing_slash() {
461+
async fn no_extension_and_no_corresponding_file_with_custom_404_does_not_redirect() {
418462
let actual = do_route("/folder", Default, None).await;
419-
let expected = redirect("/folder/");
463+
let expected = custom_not_found("404.sql");
420464

421465
assert_eq!(expected, actual);
422466
}
423467

424468
#[tokio::test]
425-
async fn no_extension_no_corresponding_file_redirects_with_trailing_slash_and_query() {
469+
async fn no_extension_no_corresponding_file_with_custom_404_does_not_redirect_with_query() {
426470
let actual = do_route("/folder?misc=1&foo=bar", Default, None).await;
427-
let expected = redirect("/folder/?misc=1&foo=bar");
471+
let expected = custom_not_found("404.sql");
428472

429473
assert_eq!(expected, actual);
430474
}
431475

432476
#[tokio::test]
433-
async fn no_extension_site_prefix_and_no_corresponding_file_redirects_with_trailing_slash()
477+
async fn no_extension_site_prefix_and_no_corresponding_file_with_custom_404_does_not_redirect()
434478
{
435479
let actual = do_route("/prefix/folder", Default, Some("/prefix/")).await;
436-
let expected = redirect("/prefix/folder/");
480+
let expected = custom_not_found("404.sql");
481+
482+
assert_eq!(expected, actual);
483+
}
484+
485+
#[tokio::test]
486+
async fn no_extension_redirects_when_no_custom_404_available() {
487+
let actual = do_route("/folder", Empty, None).await;
488+
let expected = redirect("/folder/");
437489

438490
assert_eq!(expected, actual);
439491
}

0 commit comments

Comments
 (0)