@@ -33,6 +33,21 @@ use url::form_urlencoded;
3333
3434use 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
3752const 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