@@ -4,6 +4,7 @@ use crate::{
4
4
db:: PoolError ,
5
5
web:: { page:: WebPage , releases:: Search , AxumErrorPage , ErrorPage } ,
6
6
} ;
7
+ use anyhow:: Context as _;
7
8
use axum:: {
8
9
http:: StatusCode ,
9
10
response:: { IntoResponse , Response as AxumResponse } ,
@@ -22,8 +23,6 @@ pub enum Nope {
22
23
OwnerNotFound ,
23
24
#[ error( "Requested crate does not have specified version" ) ]
24
25
VersionNotFound ,
25
- #[ error( "Search yielded no results" ) ]
26
- NoResults ,
27
26
#[ error( "Internal server error" ) ]
28
27
InternalServerError ,
29
28
}
@@ -37,8 +36,7 @@ impl From<Nope> for IronError {
37
36
| Nope :: BuildNotFound
38
37
| Nope :: CrateNotFound
39
38
| Nope :: OwnerNotFound
40
- | Nope :: VersionNotFound
41
- | Nope :: NoResults => status:: NotFound ,
39
+ | Nope :: VersionNotFound => status:: NotFound ,
42
40
Nope :: InternalServerError => status:: InternalServerError ,
43
41
} ;
44
42
@@ -96,29 +94,6 @@ impl Handler for Nope {
96
94
. into_response ( req)
97
95
}
98
96
99
- Nope :: NoResults => {
100
- let mut params = req. url . as_ref ( ) . query_pairs ( ) ;
101
-
102
- if let Some ( ( _, query) ) = params. find ( |( key, _) | key == "query" ) {
103
- // this used to be a search
104
- Search {
105
- title : format ! ( "No crates found matching '{}'" , query) ,
106
- search_query : Some ( query. into_owned ( ) ) ,
107
- status : Status :: NotFound ,
108
- ..Default :: default ( )
109
- }
110
- . into_response ( req)
111
- } else {
112
- // user did a search with no search terms
113
- Search {
114
- title : "No results given for empty search query" . to_owned ( ) ,
115
- status : Status :: NotFound ,
116
- ..Default :: default ( )
117
- }
118
- . into_response ( req)
119
- }
120
- }
121
-
122
97
Nope :: InternalServerError => {
123
98
// something went wrong, details should have been logged
124
99
ErrorPage {
@@ -151,8 +126,8 @@ pub enum AxumNope {
151
126
OwnerNotFound ,
152
127
#[ error( "Requested crate does not have specified version" ) ]
153
128
VersionNotFound ,
154
- // #[error("Search yielded no results")]
155
- // NoResults,
129
+ #[ error( "Search yielded no results" ) ]
130
+ NoResults ,
156
131
#[ error( "Internal server error" ) ]
157
132
InternalServerError ,
158
133
#[ error( "internal error" ) ]
@@ -207,9 +182,15 @@ impl IntoResponse for AxumNope {
207
182
}
208
183
. into_response ( )
209
184
}
210
- // AxumNope::NoResults => {
211
- // todo!("to be implemented when search-handler is migrated to axum")
212
- // }
185
+ AxumNope :: NoResults => {
186
+ // user did a search with no search terms
187
+ Search {
188
+ title : "No results given for empty search query" . to_owned ( ) ,
189
+ status : StatusCode :: NOT_FOUND ,
190
+ ..Default :: default ( )
191
+ }
192
+ . into_response ( )
193
+ }
213
194
AxumNope :: InternalServerError => {
214
195
// something went wrong, details should have been logged
215
196
AxumErrorPage {
@@ -254,14 +235,51 @@ impl From<Nope> for AxumNope {
254
235
Nope :: CrateNotFound => AxumNope :: CrateNotFound ,
255
236
Nope :: OwnerNotFound => AxumNope :: OwnerNotFound ,
256
237
Nope :: VersionNotFound => AxumNope :: VersionNotFound ,
257
- Nope :: NoResults => todo ! ( ) ,
258
238
Nope :: InternalServerError => AxumNope :: InternalServerError ,
259
239
}
260
240
}
261
241
}
262
242
263
243
pub ( crate ) type AxumResult < T > = Result < T , AxumNope > ;
264
244
245
+ /// spawn-blocking helper for usage in axum requests.
246
+ ///
247
+ /// Should be used when spawning tasks from inside web-handlers
248
+ /// that return AxumNope as error. The join-error will also be
249
+ /// converted into an `anyhow::Error`. Any standard AxumNope
250
+ /// will be left intact so the error-handling can generate the
251
+ /// correct status-page with the correct status code.
252
+ ///
253
+ /// Examples:
254
+ ///
255
+ /// with standard `tokio::task::spawn_blocking`:
256
+ /// ```ignore
257
+ /// let data = spawn_blocking(move || -> Result<_, AxumNope> {
258
+ /// let data = get_the_data()?;
259
+ /// Ok(data)
260
+ /// })
261
+ /// .await
262
+ /// .context("failed to join thread")??;
263
+ /// ```
264
+ ///
265
+ /// with this helper function:
266
+ /// ```ignore
267
+ /// let data = spawn_blocking(move || {
268
+ /// let data = get_the_data()?;
269
+ /// Ok(data)
270
+ /// })
271
+ /// .await?
272
+ /// ```
273
+ pub ( crate ) async fn spawn_blocking_web < F , R > ( f : F ) -> AxumResult < R >
274
+ where
275
+ F : FnOnce ( ) -> AxumResult < R > + Send + ' static ,
276
+ R : Send + ' static ,
277
+ {
278
+ tokio:: task:: spawn_blocking ( f)
279
+ . await
280
+ . context ( "failed to join thread" ) ?
281
+ }
282
+
265
283
#[ cfg( test) ]
266
284
mod tests {
267
285
use crate :: test:: wrapper;
0 commit comments