1
1
use axum:: response:: { IntoResponse , Response } ;
2
2
use axum:: Json ;
3
+ use std:: borrow:: Cow ;
3
4
use std:: fmt;
4
5
5
6
use super :: { AppError , BoxedAppError , InternalAppErrorStatic } ;
@@ -16,37 +17,6 @@ fn json_error(detail: &str, status: StatusCode) -> Response {
16
17
17
18
// The following structs are empty and do not provide a custom message to the user
18
19
19
- #[ derive( Debug ) ]
20
- pub ( crate ) struct NotFound ;
21
-
22
- impl AppError for NotFound {
23
- fn response ( & self ) -> Response {
24
- json_error ( "Not Found" , StatusCode :: NOT_FOUND )
25
- }
26
- }
27
-
28
- impl fmt:: Display for NotFound {
29
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
30
- "Not Found" . fmt ( f)
31
- }
32
- }
33
-
34
- #[ derive( Debug ) ]
35
- pub ( super ) struct Forbidden ;
36
-
37
- impl AppError for Forbidden {
38
- fn response ( & self ) -> Response {
39
- let detail = "must be logged in to perform that action" ;
40
- json_error ( detail, StatusCode :: FORBIDDEN )
41
- }
42
- }
43
-
44
- impl fmt:: Display for Forbidden {
45
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
46
- "must be logged in to perform that action" . fmt ( f)
47
- }
48
- }
49
-
50
20
#[ derive( Debug ) ]
51
21
pub ( crate ) struct ReadOnlyMode ;
52
22
@@ -66,63 +36,28 @@ impl fmt::Display for ReadOnlyMode {
66
36
67
37
// The following structs wrap owned data and provide a custom message to the user
68
38
69
- #[ derive( Debug ) ]
70
- pub ( super ) struct Ok ( pub ( super ) String ) ;
71
-
72
- impl AppError for Ok {
73
- fn response ( & self ) -> Response {
74
- json_error ( & self . 0 , StatusCode :: OK )
75
- }
39
+ pub fn custom ( status : StatusCode , detail : impl Into < Cow < ' static , str > > ) -> BoxedAppError {
40
+ Box :: new ( CustomApiError {
41
+ status,
42
+ detail : detail. into ( ) ,
43
+ } )
76
44
}
77
45
78
- impl fmt:: Display for Ok {
79
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
80
- self . 0 . fmt ( f)
81
- }
82
- }
83
-
84
- #[ derive( Debug ) ]
85
- pub ( super ) struct BadRequest ( pub ( super ) String ) ;
86
-
87
- impl AppError for BadRequest {
88
- fn response ( & self ) -> Response {
89
- json_error ( & self . 0 , StatusCode :: BAD_REQUEST )
90
- }
46
+ #[ derive( Debug , Clone ) ]
47
+ pub struct CustomApiError {
48
+ status : StatusCode ,
49
+ detail : Cow < ' static , str > ,
91
50
}
92
51
93
- impl fmt:: Display for BadRequest {
52
+ impl fmt:: Display for CustomApiError {
94
53
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
95
- self . 0 . fmt ( f)
54
+ self . detail . fmt ( f)
96
55
}
97
56
}
98
57
99
- #[ derive( Debug ) ]
100
- pub ( super ) struct ServerError ( pub ( super ) String ) ;
101
-
102
- impl AppError for ServerError {
58
+ impl AppError for CustomApiError {
103
59
fn response ( & self ) -> Response {
104
- json_error ( & self . 0 , StatusCode :: INTERNAL_SERVER_ERROR )
105
- }
106
- }
107
-
108
- impl fmt:: Display for ServerError {
109
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
110
- self . 0 . fmt ( f)
111
- }
112
- }
113
-
114
- #[ derive( Debug ) ]
115
- pub ( crate ) struct ServiceUnavailable ;
116
-
117
- impl AppError for ServiceUnavailable {
118
- fn response ( & self ) -> Response {
119
- json_error ( "Service unavailable" , StatusCode :: SERVICE_UNAVAILABLE )
120
- }
121
- }
122
-
123
- impl fmt:: Display for ServiceUnavailable {
124
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
125
- "Service unavailable" . fmt ( f)
60
+ json_error ( & self . detail , self . status )
126
61
}
127
62
}
128
63
@@ -198,93 +133,3 @@ impl fmt::Display for InsecurelyGeneratedTokenRevoked {
198
133
Result :: Ok ( ( ) )
199
134
}
200
135
}
201
-
202
- #[ derive( Debug ) ]
203
- pub ( super ) struct AccountLocked {
204
- pub ( super ) reason : String ,
205
- pub ( super ) until : Option < NaiveDateTime > ,
206
- }
207
-
208
- impl AppError for AccountLocked {
209
- fn response ( & self ) -> Response {
210
- json_error ( & self . to_string ( ) , StatusCode :: FORBIDDEN )
211
- }
212
- }
213
-
214
- impl fmt:: Display for AccountLocked {
215
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
216
- if let Some ( until) = self . until {
217
- let until = until. format ( "%Y-%m-%d at %H:%M:%S UTC" ) ;
218
- write ! (
219
- f,
220
- "This account is locked until {}. Reason: {}" ,
221
- until, self . reason
222
- )
223
- } else {
224
- write ! (
225
- f,
226
- "This account is indefinitely locked. Reason: {}" ,
227
- self . reason
228
- )
229
- }
230
- }
231
- }
232
-
233
- #[ derive( Debug ) ]
234
- pub ( crate ) struct OwnershipInvitationExpired {
235
- pub ( crate ) crate_name : String ,
236
- }
237
-
238
- impl AppError for OwnershipInvitationExpired {
239
- fn response ( & self ) -> Response {
240
- json_error ( & self . to_string ( ) , StatusCode :: GONE )
241
- }
242
- }
243
-
244
- impl fmt:: Display for OwnershipInvitationExpired {
245
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
246
- write ! (
247
- f,
248
- "The invitation to become an owner of the {} crate expired. \
249
- Please reach out to an owner of the crate to request a new invitation.",
250
- self . crate_name
251
- )
252
- }
253
- }
254
-
255
- #[ derive( Debug ) ]
256
- pub ( crate ) struct MetricsDisabled ;
257
-
258
- impl AppError for MetricsDisabled {
259
- fn response ( & self ) -> Response {
260
- json_error ( & self . to_string ( ) , StatusCode :: NOT_FOUND )
261
- }
262
- }
263
-
264
- impl fmt:: Display for MetricsDisabled {
265
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
266
- f. write_str ( "Metrics are disabled on this crates.io instance" )
267
- }
268
- }
269
-
270
- #[ derive( Debug ) ]
271
- pub ( crate ) struct RouteBlocked ;
272
-
273
- impl AppError for RouteBlocked {
274
- fn response ( & self ) -> Response {
275
- json_error ( & self . to_string ( ) , StatusCode :: SERVICE_UNAVAILABLE )
276
- }
277
- }
278
-
279
- impl fmt:: Display for RouteBlocked {
280
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
281
- f. write_str ( "This route is temporarily blocked. See https://status.crates.io." )
282
- }
283
- }
284
-
285
- impl IntoResponse for RouteBlocked {
286
- fn into_response ( self ) -> Response {
287
- let body = Json ( json ! ( { "errors" : [ { "detail" : self . to_string( ) } ] } ) ) ;
288
- ( StatusCode :: SERVICE_UNAVAILABLE , body) . into_response ( )
289
- }
290
- }
0 commit comments