From 519ee2c91af3f4049b516f90b085efccae948d6b Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Wed, 20 Dec 2023 14:12:47 +0100 Subject: [PATCH] controllers/helpers/pagination: Return `400 Bad Request` for invalid seek parameters well... it's still `200 OK` due to the cargo rewrite middleware, but it would be 400 if that wasn't there... --- src/controllers/helpers/pagination.rs | 4 ++-- src/tests/routes/crates/list.rs | 10 ++++++++++ ..._routes__crates__list__invalid_seek_parameter.snap | 11 +++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 src/tests/routes/crates/snapshots/all__routes__crates__list__invalid_seek_parameter.snap diff --git a/src/controllers/helpers/pagination.rs b/src/controllers/helpers/pagination.rs index 5055012e68a..27e8f737705 100644 --- a/src/controllers/helpers/pagination.rs +++ b/src/controllers/helpers/pagination.rs @@ -248,7 +248,7 @@ pub(crate) struct RawSeekPayload(String); impl RawSeekPayload { pub(crate) fn decode Deserialize<'a>>(&self) -> AppResult { - decode_seek(&self.0) + decode_seek(&self.0).map_err(|_| bad_request("invalid seek parameter")) } } @@ -294,7 +294,7 @@ pub(crate) fn encode_seek(params: S) -> AppResult { } /// Decode a list of params previously encoded with [`encode_seek`]. -pub(crate) fn decode_seek Deserialize<'a>>(seek: &str) -> AppResult { +pub(crate) fn decode_seek Deserialize<'a>>(seek: &str) -> anyhow::Result { let decoded = serde_json::from_slice(&general_purpose::URL_SAFE_NO_PAD.decode(seek)?)?; Ok(decoded) } diff --git a/src/tests/routes/crates/list.rs b/src/tests/routes/crates/list.rs index e8b16fccdc5..d5ac3fb24e3 100644 --- a/src/tests/routes/crates/list.rs +++ b/src/tests/routes/crates/list.rs @@ -6,6 +6,7 @@ use crates_io::schema::crates; use diesel::{dsl::*, prelude::*, update}; use googletest::prelude::*; use http::StatusCode; +use insta::assert_json_snapshot; #[test] fn index() { @@ -793,6 +794,15 @@ fn test_pages_work_even_with_seek_based_pagination() { assert!(second.meta.next_page.unwrap().contains("page=3")); } +#[test] +fn invalid_seek_parameter() { + let (_app, anon, _cookie) = TestApp::init().with_user(); + + let response = anon.get::<()>("/api/v1/crates?seek=broken"); + assert_eq!(response.status(), StatusCode::OK); + assert_json_snapshot!(response.into_json()); +} + #[test] fn pagination_parameters_only_accept_integers() { let (app, anon, user) = TestApp::init().with_user(); diff --git a/src/tests/routes/crates/snapshots/all__routes__crates__list__invalid_seek_parameter.snap b/src/tests/routes/crates/snapshots/all__routes__crates__list__invalid_seek_parameter.snap new file mode 100644 index 00000000000..82149660a6a --- /dev/null +++ b/src/tests/routes/crates/snapshots/all__routes__crates__list__invalid_seek_parameter.snap @@ -0,0 +1,11 @@ +--- +source: src/tests/routes/crates/list.rs +expression: response.into_json() +--- +{ + "errors": [ + { + "detail": "invalid seek parameter" + } + ] +}