@@ -44,93 +44,71 @@ pub enum AxumNope {
44
44
// throughout instead of having the potential for a runtime error.
45
45
46
46
impl AxumNope {
47
- fn into_error_response ( self ) -> ErrorResponse {
47
+ fn into_error_info ( self ) -> ErrorInfo {
48
48
match self {
49
49
AxumNope :: ResourceNotFound => {
50
50
// user tried to navigate to a resource (doc page/file) that doesn't exist
51
- ErrorResponse :: ErrorInfo ( ErrorInfo {
51
+ ErrorInfo {
52
52
title : "The requested resource does not exist" ,
53
53
message : "no such resource" . into ( ) ,
54
54
status : StatusCode :: NOT_FOUND ,
55
- } )
55
+ }
56
56
}
57
- AxumNope :: BuildNotFound => ErrorResponse :: ErrorInfo ( ErrorInfo {
57
+ AxumNope :: BuildNotFound => ErrorInfo {
58
58
title : "The requested build does not exist" ,
59
59
message : "no such build" . into ( ) ,
60
60
status : StatusCode :: NOT_FOUND ,
61
- } ) ,
61
+ } ,
62
62
AxumNope :: CrateNotFound => {
63
63
// user tried to navigate to a crate that doesn't exist
64
64
// TODO: Display the attempted crate and a link to a search for said crate
65
- ErrorResponse :: ErrorInfo ( ErrorInfo {
65
+ ErrorInfo {
66
66
title : "The requested crate does not exist" ,
67
67
message : "no such crate" . into ( ) ,
68
68
status : StatusCode :: NOT_FOUND ,
69
- } )
69
+ }
70
70
}
71
- AxumNope :: OwnerNotFound => ErrorResponse :: ErrorInfo ( ErrorInfo {
71
+ AxumNope :: OwnerNotFound => ErrorInfo {
72
72
title : "The requested owner does not exist" ,
73
73
message : "no such owner" . into ( ) ,
74
74
status : StatusCode :: NOT_FOUND ,
75
- } ) ,
75
+ } ,
76
76
AxumNope :: VersionNotFound => {
77
77
// user tried to navigate to a crate with a version that does not exist
78
78
// TODO: Display the attempted crate and version
79
- ErrorResponse :: ErrorInfo ( ErrorInfo {
79
+ ErrorInfo {
80
80
title : "The requested version does not exist" ,
81
81
message : "no such version for this crate" . into ( ) ,
82
82
status : StatusCode :: NOT_FOUND ,
83
- } )
83
+ }
84
84
}
85
85
AxumNope :: NoResults => {
86
86
// user did a search with no search terms
87
- ErrorResponse :: Search ( Search {
88
- title : "No results given for empty search query" . to_owned ( ) ,
89
- status : StatusCode :: NOT_FOUND ,
90
- ..Default :: default ( )
91
- } )
87
+ unreachable ! ( )
92
88
}
93
- AxumNope :: BadRequest ( source) => ErrorResponse :: ErrorInfo ( ErrorInfo {
89
+ AxumNope :: BadRequest ( source) => ErrorInfo {
94
90
title : "Bad request" ,
95
91
message : Cow :: Owned ( source. to_string ( ) ) ,
96
92
status : StatusCode :: BAD_REQUEST ,
97
- } ) ,
98
- AxumNope :: Unauthorized ( what) => ErrorResponse :: ErrorInfo ( ErrorInfo {
93
+ } ,
94
+ AxumNope :: Unauthorized ( what) => ErrorInfo {
99
95
title : "Unauthorized" ,
100
96
message : what. into ( ) ,
101
97
status : StatusCode :: UNAUTHORIZED ,
102
- } ) ,
98
+ } ,
103
99
AxumNope :: InternalError ( source) => {
104
100
crate :: utils:: report_error ( & source) ;
105
- ErrorResponse :: ErrorInfo ( ErrorInfo {
101
+ ErrorInfo {
106
102
title : "Internal Server Error" ,
107
103
message : Cow :: Owned ( source. to_string ( ) ) ,
108
104
status : StatusCode :: INTERNAL_SERVER_ERROR ,
109
- } )
110
- }
111
- AxumNope :: Redirect ( target, cache_policy) => {
112
- match super :: axum_cached_redirect ( & encode_url_path ( & target) , cache_policy) {
113
- Ok ( response) => ErrorResponse :: Redirect ( response) ,
114
- // Recurse 1 step:
115
- Err ( err) => AxumNope :: InternalError ( err) . into_error_response ( ) ,
116
105
}
117
106
}
107
+ AxumNope :: Redirect ( _target, _cache_policy) => unreachable ! ( ) ,
118
108
}
119
109
}
120
110
}
121
111
122
- // A response representing an outcome from `AxumNope`, usable in both
123
- // HTML or JSON (API) based endpoints.
124
- enum ErrorResponse {
125
- // Info representable both as HTML or as JSON
126
- ErrorInfo ( ErrorInfo ) ,
127
- // Redirect,
128
- Redirect ( AxumResponse ) ,
129
- // To recreate empty search page; only valid in HTML based
130
- // endpoints.
131
- Search ( Search ) ,
132
- }
133
-
134
112
struct ErrorInfo {
135
113
// For the title of the page
136
114
pub title : & ' static str ,
@@ -140,60 +118,40 @@ struct ErrorInfo {
140
118
pub status : StatusCode ,
141
119
}
142
120
143
- impl ErrorResponse {
144
- fn into_html_response ( self ) -> AxumResponse {
145
- match self {
146
- ErrorResponse :: ErrorInfo ( ErrorInfo {
147
- title,
148
- message,
149
- status,
150
- } ) => AxumErrorPage {
151
- title,
152
- message,
153
- status,
154
- }
155
- . into_response ( ) ,
156
- ErrorResponse :: Redirect ( response) => response,
157
- ErrorResponse :: Search ( search) => search. into_response ( ) ,
158
- }
159
- }
160
-
161
- fn into_json_response ( self ) -> AxumResponse {
162
- match self {
163
- ErrorResponse :: ErrorInfo ( ErrorInfo {
164
- title,
165
- message,
166
- status,
167
- } ) => (
168
- status,
169
- Json ( serde_json:: json!( {
170
- "title" : title,
171
- "message" : message,
172
- } ) ) ,
173
- )
174
- . into_response ( ) ,
175
- ErrorResponse :: Redirect ( response) => response,
176
- ErrorResponse :: Search ( search) => {
177
- // FUTURE: this runtime error is avoidable by
178
- // splitting `enum AxumNope` into hierarchical parts,
179
- // see above.
180
- error ! (
181
- "expecting that handlers that return JSON error responses \
182
- don't return Search, but got: {search:?}"
183
- ) ;
184
- AxumNope :: InternalError ( anyhow ! (
185
- "bug: search HTML page returned from endpoint that returns JSON"
186
- ) )
187
- . into_error_response ( )
188
- . into_json_response ( )
189
- }
190
- }
121
+ fn redirect_with_policy ( target : String , cache_policy : CachePolicy ) -> AxumResponse {
122
+ match super :: axum_cached_redirect ( & encode_url_path ( & target) , cache_policy) {
123
+ Ok ( response) => response. into_response ( ) ,
124
+ Err ( err) => AxumNope :: InternalError ( err) . into_response ( ) ,
191
125
}
192
126
}
193
127
194
128
impl IntoResponse for AxumNope {
195
129
fn into_response ( self ) -> AxumResponse {
196
- self . into_error_response ( ) . into_html_response ( )
130
+ match self {
131
+ AxumNope :: NoResults => {
132
+ // user did a search with no search terms
133
+ Search {
134
+ title : "No results given for empty search query" . to_owned ( ) ,
135
+ status : StatusCode :: NOT_FOUND ,
136
+ ..Default :: default ( )
137
+ }
138
+ . into_response ( )
139
+ }
140
+ AxumNope :: Redirect ( target, cache_policy) => redirect_with_policy ( target, cache_policy) ,
141
+ _ => {
142
+ let ErrorInfo {
143
+ title,
144
+ message,
145
+ status,
146
+ } = self . into_error_info ( ) ;
147
+ AxumErrorPage {
148
+ title,
149
+ message,
150
+ status,
151
+ }
152
+ . into_response ( )
153
+ }
154
+ }
197
155
}
198
156
}
199
157
@@ -202,7 +160,29 @@ pub(crate) struct JsonAxumNope(pub AxumNope);
202
160
203
161
impl IntoResponse for JsonAxumNope {
204
162
fn into_response ( self ) -> AxumResponse {
205
- self . 0 . into_error_response ( ) . into_json_response ( )
163
+ match self . 0 {
164
+ AxumNope :: NoResults => {
165
+ // user did a search with no search terms; invalid,
166
+ // return 404
167
+ StatusCode :: NOT_FOUND . into_response ( )
168
+ }
169
+ AxumNope :: Redirect ( target, cache_policy) => redirect_with_policy ( target, cache_policy) ,
170
+ _ => {
171
+ let ErrorInfo {
172
+ title,
173
+ message,
174
+ status,
175
+ } = self . 0 . into_error_info ( ) ;
176
+ (
177
+ status,
178
+ Json ( serde_json:: json!( {
179
+ "title" : title,
180
+ "message" : message,
181
+ } ) ) ,
182
+ )
183
+ . into_response ( )
184
+ }
185
+ }
206
186
}
207
187
}
208
188
0 commit comments