@@ -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 {
@@ -234,8 +215,59 @@ impl IntoResponse for AxumNope {
234
215
}
235
216
}
236
217
218
+ impl From < Nope > for AxumNope {
219
+ fn from ( err : Nope ) -> Self {
220
+ match err {
221
+ Nope :: ResourceNotFound => AxumNope :: ResourceNotFound ,
222
+ Nope :: BuildNotFound => AxumNope :: BuildNotFound ,
223
+ Nope :: CrateNotFound => AxumNope :: CrateNotFound ,
224
+ Nope :: OwnerNotFound => AxumNope :: OwnerNotFound ,
225
+ Nope :: VersionNotFound => AxumNope :: VersionNotFound ,
226
+ Nope :: InternalServerError => AxumNope :: InternalServerError ,
227
+ }
228
+ }
229
+ }
230
+
237
231
pub ( crate ) type AxumResult < T > = Result < T , AxumNope > ;
238
232
233
+ /// spawn-blocking helper for usage in axum requests.
234
+ ///
235
+ /// Should be used when spawning tasks from inside web-handlers
236
+ /// that return AxumNope as error. The join-error will also be
237
+ /// converted into an `anyhow::Error`. Any standard AxumNope
238
+ /// will be left intact so the error-handling can generate the
239
+ /// correct status-page with the correct status code.
240
+ ///
241
+ /// Examples:
242
+ ///
243
+ /// with standard `tokio::task::spawn_blocking`:
244
+ /// ```ignore
245
+ /// let data = spawn_blocking(move || -> Result<_, AxumNope> {
246
+ /// let data = get_the_data()?;
247
+ /// Ok(data)
248
+ /// })
249
+ /// .await
250
+ /// .context("failed to join thread")??;
251
+ /// ```
252
+ ///
253
+ /// with this helper function:
254
+ /// ```ignore
255
+ /// let data = spawn_blocking(move || {
256
+ /// let data = get_the_data()?;
257
+ /// Ok(data)
258
+ /// })
259
+ /// .await?
260
+ /// ```
261
+ pub ( crate ) async fn spawn_blocking_web < F , R > ( f : F ) -> AxumResult < R >
262
+ where
263
+ F : FnOnce ( ) -> AxumResult < R > + Send + ' static ,
264
+ R : Send + ' static ,
265
+ {
266
+ tokio:: task:: spawn_blocking ( f)
267
+ . await
268
+ . context ( "failed to join thread" ) ?
269
+ }
270
+
239
271
#[ cfg( test) ]
240
272
mod tests {
241
273
use crate :: test:: wrapper;
0 commit comments