From 197d11a231dbaacf780aa52b8b93462fbbe8d89a Mon Sep 17 00:00:00 2001
From: Denis Cornehl <denis@cornehl.org>
Date: Tue, 27 May 2025 20:50:05 +0200
Subject: [PATCH] rustdoc json: check target existance before redirecting to S3

---
 src/web/rustdoc.rs | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/web/rustdoc.rs b/src/web/rustdoc.rs
index cd0189a10..c62f64f9d 100644
--- a/src/web/rustdoc.rs
+++ b/src/web/rustdoc.rs
@@ -830,6 +830,7 @@ pub(crate) async fn json_download_handler(
     Path(params): Path<JsonDownloadParams>,
     mut conn: DbConnection,
     Extension(config): Extension<Arc<Config>>,
+    Extension(storage): Extension<Arc<AsyncStorage>>,
 ) -> AxumResult<impl IntoResponse> {
     let matched_release = match_version(&mut conn, &params.name, &params.version)
         .await?
@@ -875,6 +876,10 @@ pub(crate) async fn json_download_handler(
         format_version,
     );
 
+    if !storage.exists(&storage_path).await? {
+        return Err(AxumNope::ResourceNotFound);
+    }
+
     // since we didn't build rustdoc json for all releases yet,
     // this redirect might redirect to a location that doesn't exist.
     Ok(super::axum_cached_redirect(
@@ -3166,6 +3171,7 @@ mod test {
 
     #[test_case("0.1.0/json"; "rustdoc status false")]
     #[test_case("0.2.0/unknown-target/json"; "unknown target")]
+    #[test_case("0.2.0/json/99"; "target file doesnt exist")]
     #[test_case("0.42.0/json"; "unknown version")]
     fn json_download_not_found(request_path_suffix: &str) {
         async_wrapper(|env| async move {