Skip to content

Commit 34a21b1

Browse files
committed
Categorize search errors
1 parent 054b69f commit 34a21b1

File tree

1 file changed

+68
-4
lines changed

1 file changed

+68
-4
lines changed

src/web/releases.rs

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,21 @@ use url::form_urlencoded;
3333

3434
use super::cache::CachePolicy;
3535

36+
// Introduce SearchError as new error type
37+
#[derive(Debug, thiserror::Error)]
38+
pub enum SearchError {
39+
#[error("crates.io error: {0}")]
40+
CratesIo(String),
41+
#[error(transparent)]
42+
Other(#[from] anyhow::Error),
43+
}
44+
45+
impl From<sqlx::Error> for SearchError {
46+
fn from(err: sqlx::Error) -> Self {
47+
SearchError::Other(anyhow::Error::from(err))
48+
}
49+
}
50+
3651
/// Number of release in home page
3752
const RELEASES_IN_HOME: i64 = 15;
3853
/// Releases in /releases page
@@ -149,8 +164,13 @@ async fn get_search_results(
149164
conn: &mut sqlx::PgConnection,
150165
registry: &RegistryApi,
151166
query_params: &str,
152-
) -> Result<SearchResult, anyhow::Error> {
153-
let crate::registry_api::Search { crates, meta } = registry.search(query_params).await?;
167+
) -> Result<SearchResult, SearchError> {
168+
// Capture responses returned by registry
169+
let result = registry.search(query_params).await;
170+
let crate::registry_api::Search { crates, meta } = match result {
171+
Ok(results_from_search_request) => results_from_search_request,
172+
Err(err) => return handle_registry_error(err),
173+
};
154174

155175
let names = Arc::new(
156176
crates
@@ -233,6 +253,37 @@ async fn get_search_results(
233253
})
234254
}
235255

256+
// Categorize errors from registry
257+
fn handle_registry_error(err: anyhow::Error) -> Result<SearchResult, SearchError> {
258+
// Capture crates.io API error
259+
if let Some(registry_request_error) = err.downcast_ref::<reqwest::Error>() {
260+
if let Some(status) = registry_request_error.status() {
261+
if status.is_client_error() || status.is_server_error() {
262+
return Err(SearchError::CratesIo(format!(
263+
"crates.io returned {}: {}",
264+
status, registry_request_error
265+
)));
266+
}
267+
}
268+
}
269+
// Move all other error types to this wrapper
270+
Err(SearchError::Other(err))
271+
}
272+
273+
//Error message to gracefully display
274+
fn create_search_error_response(query: String, sort_by: String) -> Search {
275+
Search {
276+
title: "Search service is not currently available".to_owned(),
277+
releases: vec![],
278+
search_query: Some(query),
279+
search_sort_by: Some(sort_by),
280+
previous_page_link: None,
281+
next_page_link: None,
282+
release_type: ReleaseType::Search,
283+
status: http::StatusCode::SERVICE_UNAVAILABLE,
284+
}
285+
}
286+
236287
#[derive(Template)]
237288
#[template(path = "core/home.html")]
238289
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -589,19 +640,32 @@ pub(crate) async fn search_handler(
589640
}
590641
}
591642

592-
get_search_results(&mut conn, &registry, query_params).await?
643+
get_search_results(&mut conn, &registry, query_params).await
593644
} else if !query.is_empty() {
594645
let query_params: String = form_urlencoded::Serializer::new(String::new())
595646
.append_pair("q", &query)
596647
.append_pair("sort", &sort_by)
597648
.append_pair("per_page", &RELEASES_IN_RELEASES.to_string())
598649
.finish();
599650

600-
get_search_results(&mut conn, &registry, &query_params).await?
651+
get_search_results(&mut conn, &registry, &query_params).await
601652
} else {
602653
return Err(AxumNope::NoResults);
603654
};
604655

656+
let search_result = match search_result {
657+
Ok(result) => result,
658+
Err(SearchError::CratesIo(_)) => {
659+
// Return a user-friendly error response
660+
return Ok(create_search_error_response(query, sort_by).into_response());
661+
}
662+
Err(SearchError::Other(err)) => {
663+
// For other errors, propagate them normally
664+
// NOTE - Errrors that are not 400x or 500x will be logged to Sentry
665+
return Err(err.into());
666+
}
667+
};
668+
605669
let title = if search_result.results.is_empty() {
606670
format!("No results found for '{query}'")
607671
} else {

0 commit comments

Comments
 (0)