11use axum:: response:: { IntoResponse , Response } ;
22use axum:: Json ;
3+ use std:: borrow:: Cow ;
34use std:: fmt;
45
56use super :: { AppError , BoxedAppError , InternalAppErrorStatic } ;
@@ -16,37 +17,6 @@ fn json_error(detail: &str, status: StatusCode) -> Response {
1617
1718// The following structs are empty and do not provide a custom message to the user
1819
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-
5020#[ derive( Debug ) ]
5121pub ( crate ) struct ReadOnlyMode ;
5222
@@ -66,63 +36,28 @@ impl fmt::Display for ReadOnlyMode {
6636
6737// The following structs wrap owned data and provide a custom message to the user
6838
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+ } )
7644}
7745
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 > ,
9150}
9251
93- impl fmt:: Display for BadRequest {
52+ impl fmt:: Display for CustomApiError {
9453 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
95- self . 0 . fmt ( f)
54+ self . detail . fmt ( f)
9655 }
9756}
9857
99- #[ derive( Debug ) ]
100- pub ( super ) struct ServerError ( pub ( super ) String ) ;
101-
102- impl AppError for ServerError {
58+ impl AppError for CustomApiError {
10359 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 )
12661 }
12762}
12863
@@ -198,93 +133,3 @@ impl fmt::Display for InsecurelyGeneratedTokenRevoked {
198133 Result :: Ok ( ( ) )
199134 }
200135}
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