@@ -4,24 +4,34 @@ use crate::{
44 build_queue:: QueuedCrate ,
55 cdn:: { self , CrateInvalidation } ,
66 db:: { Pool , PoolClient } ,
7- impl_webpage,
7+ impl_axum_webpage , impl_webpage,
88 utils:: report_error,
9- web:: { error:: Nope , match_version, page:: WebPage , parse_url_with_params, redirect_base} ,
9+ web:: {
10+ error:: { Nope , WebResult } ,
11+ match_version,
12+ page:: WebPage ,
13+ parse_url_with_params, redirect_base,
14+ } ,
1015 BuildQueue , Config ,
1116} ;
12- use anyhow:: { anyhow, Result } ;
17+ use anyhow:: { anyhow, Context as _, Result } ;
18+ use axum:: {
19+ extract:: { Extension , Path } ,
20+ response:: IntoResponse ,
21+ } ;
1322use chrono:: { DateTime , NaiveDate , Utc } ;
1423use iron:: {
1524 headers:: { ContentType , Expires , HttpDate } ,
1625 mime:: { Mime , SubLevel , TopLevel } ,
1726 modifiers:: Redirect ,
18- status, IronError , IronResult , Request , Response , Url ,
27+ status, IronError , IronResult , Request , Response as IronResponse , Url ,
1928} ;
2029use postgres:: Client ;
2130use router:: Router ;
2231use serde:: { Deserialize , Serialize } ;
2332use std:: collections:: { BTreeMap , HashMap } ;
2433use std:: str;
34+ use tokio:: task:: spawn_blocking;
2535use tracing:: { debug, warn} ;
2636use url:: form_urlencoded;
2737
@@ -63,7 +73,7 @@ pub(crate) fn get_releases(
6373 limit : i64 ,
6474 order : Order ,
6575 latest_only : bool ,
66- ) -> Vec < Release > {
76+ ) -> Result < Vec < Release > > {
6777 let offset = ( page - 1 ) * limit;
6878
6979 // WARNING: it is _crucial_ that this always be hard-coded and NEVER be user input
@@ -100,8 +110,8 @@ pub(crate) fn get_releases(
100110 }
101111 ) ;
102112
103- conn . query ( query . as_str ( ) , & [ & limit , & offset , & filter_failed ] )
104- . unwrap ( )
113+ Ok ( conn
114+ . query ( query . as_str ( ) , & [ & limit , & offset , & filter_failed ] ) ?
105115 . into_iter ( )
106116 . map ( |row| Release {
107117 name : row. get ( 0 ) ,
@@ -112,7 +122,7 @@ pub(crate) fn get_releases(
112122 build_time : row. get ( 5 ) ,
113123 stars : row. get :: < _ , Option < i32 > > ( 6 ) . unwrap_or ( 0 ) ,
114124 } )
115- . collect ( )
125+ . collect ( ) )
116126}
117127
118128struct SearchResult {
@@ -255,9 +265,12 @@ impl_webpage! {
255265 HomePage = "core/home.html" ,
256266}
257267
258- pub fn home_page ( req : & mut Request ) -> IronResult < Response > {
268+ pub fn home_page ( req : & mut Request ) -> IronResult < IronResponse > {
259269 let mut conn = extension ! ( req, Pool ) . get ( ) ?;
260- let recent_releases = get_releases ( & mut conn, 1 , RELEASES_IN_HOME , Order :: ReleaseTime , true ) ;
270+ let recent_releases = ctry ! (
271+ req,
272+ get_releases( & mut conn, 1 , RELEASES_IN_HOME , Order :: ReleaseTime , true )
273+ ) ;
261274
262275 HomePage { recent_releases } . into_response ( req)
263276}
@@ -272,9 +285,12 @@ impl_webpage! {
272285 content_type = ContentType ( Mime ( TopLevel :: Application , SubLevel :: Xml , vec![ ] ) ) ,
273286}
274287
275- pub fn releases_feed_handler ( req : & mut Request ) -> IronResult < Response > {
288+ pub fn releases_feed_handler ( req : & mut Request ) -> IronResult < IronResponse > {
276289 let mut conn = extension ! ( req, Pool ) . get ( ) ?;
277- let recent_releases = get_releases ( & mut conn, 1 , RELEASES_IN_FEED , Order :: ReleaseTime , true ) ;
290+ let recent_releases = ctry ! (
291+ req,
292+ get_releases( & mut conn, 1 , RELEASES_IN_FEED , Order :: ReleaseTime , true )
293+ ) ;
278294
279295 ReleaseFeed { recent_releases } . into_response ( req)
280296}
@@ -290,25 +306,26 @@ struct ViewReleases {
290306 owner : Option < String > ,
291307}
292308
293- impl_webpage ! {
309+ impl_axum_webpage ! {
294310 ViewReleases = "releases/releases.html" ,
295311}
296312
297313#[ derive( Debug , Copy , Clone , PartialEq , Eq , Serialize ) ]
298314#[ serde( rename_all = "kebab-case" ) ]
299- pub ( super ) enum ReleaseType {
315+ pub ( crate ) enum ReleaseType {
300316 Recent ,
301317 Stars ,
302318 RecentFailures ,
303319 Failures ,
304320 Search ,
305321}
306322
307- fn releases_handler ( req : & mut Request , release_type : ReleaseType ) -> IronResult < Response > {
308- let page_number: i64 = extension ! ( req, Router )
309- . find ( "page" )
310- . and_then ( |page_num| page_num. parse ( ) . ok ( ) )
311- . unwrap_or ( 1 ) ;
323+ pub ( crate ) async fn releases_handler (
324+ pool : Pool ,
325+ page : Option < i64 > ,
326+ release_type : ReleaseType ,
327+ ) -> WebResult < impl IntoResponse > {
328+ let page_number = page. unwrap_or ( 1 ) ;
312329
313330 let ( description, release_order, latest_only) = match release_type {
314331 ReleaseType :: Recent => ( "Recently uploaded crates" , Order :: ReleaseTime , false ) ,
@@ -329,52 +346,65 @@ fn releases_handler(req: &mut Request, release_type: ReleaseType) -> IronResult<
329346 }
330347 } ;
331348
332- let releases = {
333- let mut conn = extension ! ( req , Pool ) . get ( ) ?;
349+ let releases = spawn_blocking ( move || -> Result < _ > {
350+ let mut conn = pool . get ( ) ?;
334351 get_releases (
335352 & mut conn,
336353 page_number,
337354 RELEASES_IN_RELEASES ,
338355 release_order,
339356 latest_only,
340357 )
341- } ;
358+ } )
359+ . await
360+ . context ( "failed to join thread" ) ??;
342361
343362 // Show next and previous page buttons
344363 let ( show_next_page, show_previous_page) = (
345364 releases. len ( ) == RELEASES_IN_RELEASES as usize ,
346365 page_number != 1 ,
347366 ) ;
348367
349- ViewReleases {
368+ Ok ( ViewReleases {
350369 releases,
351370 description : description. into ( ) ,
352371 release_type,
353372 show_next_page,
354373 show_previous_page,
355374 page_number,
356375 owner : None ,
357- }
358- . into_response ( req)
376+ } )
359377}
360378
361- pub fn recent_releases_handler ( req : & mut Request ) -> IronResult < Response > {
362- releases_handler ( req, ReleaseType :: Recent )
379+ pub ( crate ) async fn recent_releases_handler (
380+ page : Option < Path < i64 > > ,
381+ Extension ( pool) : Extension < Pool > ,
382+ ) -> WebResult < impl IntoResponse > {
383+ releases_handler ( pool, page. map ( |p| p. 0 ) , ReleaseType :: Recent ) . await
363384}
364385
365- pub fn releases_by_stars_handler ( req : & mut Request ) -> IronResult < Response > {
366- releases_handler ( req, ReleaseType :: Stars )
386+ pub ( crate ) async fn releases_by_stars_handler (
387+ page : Option < Path < i64 > > ,
388+ Extension ( pool) : Extension < Pool > ,
389+ ) -> WebResult < impl IntoResponse > {
390+ releases_handler ( pool, page. map ( |p| p. 0 ) , ReleaseType :: Stars ) . await
367391}
368392
369- pub fn releases_recent_failures_handler ( req : & mut Request ) -> IronResult < Response > {
370- releases_handler ( req, ReleaseType :: RecentFailures )
393+ pub ( crate ) async fn releases_recent_failures_handler (
394+ page : Option < Path < i64 > > ,
395+ Extension ( pool) : Extension < Pool > ,
396+ ) -> WebResult < impl IntoResponse > {
397+ releases_handler ( pool, page. map ( |p| p. 0 ) , ReleaseType :: RecentFailures ) . await
371398}
372399
373- pub fn releases_failures_by_stars_handler ( req : & mut Request ) -> IronResult < Response > {
374- releases_handler ( req, ReleaseType :: Failures )
400+ pub ( crate ) async fn releases_failures_by_stars_handler (
401+ page : Option < Path < i64 > > ,
402+ Extension ( pool) : Extension < Pool > ,
403+ ) -> WebResult < impl IntoResponse > {
404+ releases_handler ( pool, page. map ( |p| p. 0 ) , ReleaseType :: Failures ) . await
375405}
376406
377- pub fn owner_handler ( req : & mut Request ) -> IronResult < Response > {
407+ pub fn owner_handler ( req : & mut Request ) -> IronResult < IronResponse > {
378408 let router = extension ! ( req, Router ) ;
379409 let mut owner = router. find ( "owner" ) . unwrap ( ) ;
380410 if owner. starts_with ( '@' ) {
@@ -414,7 +444,7 @@ impl Default for Search {
414444 }
415445}
416446
417- fn redirect_to_random_crate ( req : & Request , conn : & mut PoolClient ) -> IronResult < Response > {
447+ fn redirect_to_random_crate ( req : & Request , conn : & mut PoolClient ) -> IronResult < IronResponse > {
418448 // We try to find a random crate and redirect to it.
419449 //
420450 // The query is efficient, but relies on a static factor which depends
@@ -480,7 +510,7 @@ impl_webpage! {
480510 status = |search| search. status,
481511}
482512
483- pub fn search_handler ( req : & mut Request ) -> IronResult < Response > {
513+ pub fn search_handler ( req : & mut Request ) -> IronResult < IronResponse > {
484514 let url = req. url . as_ref ( ) ;
485515 let mut params: HashMap < _ , _ > = url. query_pairs ( ) . collect ( ) ;
486516 let query = params
@@ -526,7 +556,7 @@ pub fn search_handler(req: &mut Request) -> IronResult<Response> {
526556 ctry ! ( req, Url :: parse( & format!( "{base}/crate/{krate}/{version}" ) ) )
527557 } ;
528558
529- let mut resp = Response :: with ( ( status:: Found , Redirect ( url) ) ) ;
559+ let mut resp = IronResponse :: with ( ( status:: Found , Redirect ( url) ) ) ;
530560 resp. headers . set ( Expires ( HttpDate ( time:: now ( ) ) ) ) ;
531561
532562 return Ok ( resp) ;
@@ -607,7 +637,7 @@ impl_webpage! {
607637 ReleaseActivity = "releases/activity.html" ,
608638}
609639
610- pub fn activity_handler ( req : & mut Request ) -> IronResult < Response > {
640+ pub fn activity_handler ( req : & mut Request ) -> IronResult < IronResponse > {
611641 let mut conn = extension ! ( req, Pool ) . get ( ) ?;
612642
613643 let data: Vec < ( NaiveDate , i64 , i64 ) > = ctry ! (
@@ -676,7 +706,7 @@ impl_webpage! {
676706 BuildQueuePage = "releases/build_queue.html" ,
677707}
678708
679- pub fn build_queue_handler ( req : & mut Request ) -> IronResult < Response > {
709+ pub fn build_queue_handler ( req : & mut Request ) -> IronResult < IronResponse > {
680710 let mut queue = ctry ! ( req, extension!( req, BuildQueue ) . queued_crates( ) ) ;
681711 for krate in queue. iter_mut ( ) {
682712 // The priority here is inverted: in the database if a crate has a higher priority it
@@ -730,7 +760,7 @@ mod tests {
730760 // release without stars will not be shown
731761 env. fake_release ( ) . name ( "baz" ) . version ( "1.0.0" ) . create ( ) ?;
732762
733- let releases = get_releases ( & mut db. conn ( ) , 1 , 10 , Order :: GithubStars , true ) ;
763+ let releases = get_releases ( & mut db. conn ( ) , 1 , 10 , Order :: GithubStars , true ) . unwrap ( ) ;
734764 assert_eq ! (
735765 vec![
736766 "bar" , // 20 stars
0 commit comments