http_types_rs/status_code.rs
1use std::fmt::{self, Debug, Display};
2
3/// HTTP response status codes.
4///
5/// As defined by [rfc7231 section 6](https://tools.ietf.org/html/rfc7231#section-6).
6/// [Read more](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status)
7#[repr(u16)]
8#[derive(Clone, Copy, Eq, PartialEq, Hash)]
9pub enum StatusCode {
10 /// 100 Continue
11 ///
12 /// This interim response indicates that everything so far is OK and that
13 /// the client should continue the request, or ignore the response if
14 /// the request is already finished.
15 Continue = 100,
16
17 /// 101 Switching Protocols
18 ///
19 /// This code is sent in response to an Upgrade request header from the
20 /// client, and indicates the protocol the server is switching to.
21 SwitchingProtocols = 101,
22
23 /// 103 Early Hints
24 ///
25 /// This status code is primarily intended to be used with the Link header,
26 /// letting the user agent start preloading resources while the server
27 /// prepares a response.
28 EarlyHints = 103,
29
30 /// 200 Ok
31 ///
32 /// The request has succeeded
33 Ok = 200,
34
35 /// 201 Created
36 ///
37 /// The request has succeeded and a new resource has been created as a
38 /// result. This is typically the response sent after POST requests, or
39 /// some PUT requests.
40 Created = 201,
41
42 /// 202 Accepted
43 ///
44 /// The request has been received but not yet acted upon. It is
45 /// noncommittal, since there is no way in HTTP to later send an
46 /// asynchronous response indicating the outcome of the request. It is
47 /// intended for cases where another process or server handles the request,
48 /// or for batch processing.
49 Accepted = 202,
50
51 /// 203 Non Authoritative Information
52 ///
53 /// This response code means the returned meta-information is not exactly
54 /// the same as is available from the origin server, but is collected
55 /// from a local or a third-party copy. This is mostly used for mirrors
56 /// or backups of another resource. Except for that specific case, the
57 /// "200 OK" response is preferred to this status.
58 NonAuthoritativeInformation = 203,
59
60 /// 204 No Content
61 ///
62 /// There is no content to send for this request, but the headers may be
63 /// useful. The user-agent may update its cached headers for this
64 /// resource with the new ones.
65 NoContent = 204,
66
67 /// 205 Reset Content
68 ///
69 /// Tells the user-agent to reset the document which sent this request.
70 ResetContent = 205,
71
72 /// 206 Partial Content
73 ///
74 /// This response code is used when the Range header is sent from the client
75 /// to request only part of a resource.
76 PartialContent = 206,
77
78 /// 207 Multi-Status
79 ///
80 /// A Multi-Status response conveys information about
81 /// multiple resources in situations where multiple
82 /// status codes might be appropriate.
83 MultiStatus = 207,
84
85 /// 226 Im Used
86 ///
87 /// The server has fulfilled a GET request for the resource, and the
88 /// response is a representation of the result of one or more
89 /// instance-manipulations applied to the current instance.
90 ImUsed = 226,
91
92 /// 300 Multiple Choice
93 ///
94 /// The request has more than one possible response. The user-agent or user
95 /// should choose one of them. (There is no standardized way of choosing
96 /// one of the responses, but HTML links to the possibilities are
97 /// recommended so the user can pick.)
98 MultipleChoice = 300,
99
100 /// 301 Moved Permanently
101 ///
102 /// The URL of the requested resource has been changed permanently. The new
103 /// URL is given in the response.
104 MovedPermanently = 301,
105
106 /// 302 Found
107 ///
108 /// This response code means that the URI of requested resource has been
109 /// changed temporarily. Further changes in the URI might be made in the
110 /// future. Therefore, this same URI should be used by the client in
111 /// future requests.
112 Found = 302,
113
114 /// 303 See Other
115 ///
116 /// The server sent this response to direct the client to get the requested
117 /// resource at another URI with a GET request.
118 SeeOther = 303,
119
120 /// 304 Not Modified
121 ///
122 /// This is used for caching purposes. It tells the client that the response
123 /// has not been modified, so the client can continue to use the same
124 /// cached version of the response.
125 NotModified = 304,
126
127 /// 307 Temporary Redirect
128 ///
129 /// The server sends this response to direct the client to get the requested
130 /// resource at another URI with same method that was used in the prior
131 /// request. This has the same semantics as the 302 Found HTTP response
132 /// code, with the exception that the user agent must not change the
133 /// HTTP method used: If a POST was used in the first request, a POST must
134 /// be used in the second request.
135 TemporaryRedirect = 307,
136
137 /// 308 Permanent Redirect
138 ///
139 /// This means that the resource is now permanently located at another URI,
140 /// specified by the Location: HTTP Response header. This has the same
141 /// semantics as the 301 Moved Permanently HTTP response code, with the
142 /// exception that the user agent must not change the HTTP method
143 /// used: If a POST was used in the first request, a POST must be used in
144 /// the second request.
145 PermanentRedirect = 308,
146
147 /// 400 Bad Request
148 ///
149 /// The server could not understand the request due to invalid syntax.
150 BadRequest = 400,
151
152 /// 401 Unauthorized
153 ///
154 /// Although the HTTP standard specifies "unauthorized", semantically this
155 /// response means "unauthenticated". That is, the client must
156 /// authenticate itself to get the requested response.
157 Unauthorized = 401,
158
159 /// 402 Payment Required
160 ///
161 /// This response code is reserved for future use. The initial aim for
162 /// creating this code was using it for digital payment systems, however
163 /// this status code is used very rarely and no standard convention
164 /// exists.
165 PaymentRequired = 402,
166
167 /// 403 Forbidden
168 ///
169 /// The client does not have access rights to the content; that is, it is
170 /// unauthorized, so the server is refusing to give the requested
171 /// resource. Unlike 401, the client's identity is known to the server.
172 Forbidden = 403,
173
174 /// 404 Not Found
175 ///
176 /// The server can not find requested resource. In the browser, this means
177 /// the URL is not recognized. In an API, this can also mean that the
178 /// endpoint is valid but the resource itself does not exist. Servers
179 /// may also send this response instead of 403 to hide the existence of
180 /// a resource from an unauthorized client. This response code is probably
181 /// the most famous one due to its frequent occurrence on the web.
182 NotFound = 404,
183
184 /// 405 Method Not Allowed
185 ///
186 /// The request method is known by the server but has been disabled and
187 /// cannot be used. For example, an API may forbid DELETE-ing a
188 /// resource. The two mandatory methods, GET and HEAD, must never be
189 /// disabled and should not return this error code.
190 MethodNotAllowed = 405,
191
192 /// 406 Not Acceptable
193 ///
194 /// This response is sent when the web server, after performing
195 /// server-driven content negotiation, doesn't find any content that
196 /// conforms to the criteria given by the user agent.
197 NotAcceptable = 406,
198
199 /// 407 Proxy Authentication Required
200 ///
201 /// This is similar to 401 but authentication is needed to be done by a
202 /// proxy.
203 ProxyAuthenticationRequired = 407,
204
205 /// 408 Request Timeout
206 ///
207 /// This response is sent on an idle connection by some servers, even
208 /// without any previous request by the client. It means that the server
209 /// would like to shut down this unused connection. This response is
210 /// used much more since some browsers, like Chrome, Firefox 27+,
211 /// or IE9, use HTTP pre-connection mechanisms to speed up surfing. Also
212 /// note that some servers merely shut down the connection without
213 /// sending this message.
214 RequestTimeout = 408,
215
216 /// 409 Conflict
217 ///
218 /// This response is sent when a request conflicts with the current state of
219 /// the server.
220 Conflict = 409,
221
222 /// 410 Gone
223 ///
224 /// This response is sent when the requested content has been permanently
225 /// deleted from server, with no forwarding address. Clients are
226 /// expected to remove their caches and links to the resource. The HTTP
227 /// specification intends this status code to be used for "limited-time,
228 /// promotional services". APIs should not feel compelled to indicate
229 /// resources that have been deleted with this status code.
230 Gone = 410,
231
232 /// 411 Length Required
233 ///
234 /// Server rejected the request because the Content-Length header field is
235 /// not defined and the server requires it.
236 LengthRequired = 411,
237
238 /// 412 Precondition Failed
239 ///
240 /// The client has indicated preconditions in its headers which the server
241 /// does not meet.
242 PreconditionFailed = 412,
243
244 /// 413 Payload Too Large
245 ///
246 /// Request entity is larger than limits defined by server; the server might
247 /// close the connection or return an Retry-After header field.
248 PayloadTooLarge = 413,
249
250 /// 414 URI Too Long
251 ///
252 /// The URI requested by the client is longer than the server is willing to
253 /// interpret.
254 UriTooLong = 414,
255
256 /// 415 Unsupported Media Type
257 ///
258 /// The media format of the requested data is not supported by the server,
259 /// so the server is rejecting the request.
260 UnsupportedMediaType = 415,
261
262 /// 416 Requested Range Not Satisfiable
263 ///
264 /// The range specified by the Range header field in the request can't be
265 /// fulfilled; it's possible that the range is outside the size of the
266 /// target URI's data.
267 RequestedRangeNotSatisfiable = 416,
268
269 /// 417 Expectation Failed
270 ///
271 /// This response code means the expectation indicated by the Expect request
272 /// header field can't be met by the server.
273 ExpectationFailed = 417,
274 ///
275 /// 418 I'm a teapot
276 ///
277 /// The server refuses the attempt to brew coffee with a teapot.
278 ImATeapot = 418,
279
280 /// 421 Misdirected Request
281 ///
282 /// The request was directed at a server that is not able to produce a
283 /// response. This can be sent by a server that is not configured to
284 /// produce responses for the combination of scheme and authority that
285 /// are included in the request URI.
286 MisdirectedRequest = 421,
287
288 /// 422 Unprocessable Entity
289 ///
290 /// The request was well-formed but was unable to be followed due to
291 /// semantic errors.
292 UnprocessableEntity = 422,
293
294 /// 423 Locked
295 ///
296 /// The resource that is being accessed is locked.
297 Locked = 423,
298
299 /// 424 Failed Dependency
300 ///
301 /// The request failed because it depended on another request and that
302 /// request failed (e.g., a PROPPATCH).
303 FailedDependency = 424,
304
305 /// 425 Too Early
306 ///
307 /// Indicates that the server is unwilling to risk processing a request that
308 /// might be replayed.
309 TooEarly = 425,
310
311 /// 426 Upgrade Required
312 ///
313 /// The server refuses to perform the request using the current protocol but
314 /// might be willing to do so after the client upgrades to a different
315 /// protocol. The server sends an Upgrade header in a 426 response to
316 /// indicate the required protocol(s).
317 UpgradeRequired = 426,
318
319 /// 428 Precondition Required
320 ///
321 /// The origin server requires the request to be conditional. This response
322 /// is intended to prevent the 'lost update' problem, where a client
323 /// GETs a resource's state, modifies it, and PUTs it back to the
324 /// server, when meanwhile a third party has modified the state on the
325 /// server, leading to a conflict.
326 PreconditionRequired = 428,
327
328 /// 429 Too Many Requests
329 ///
330 /// The user has sent too many requests in a given amount of time ("rate
331 /// limiting").
332 TooManyRequests = 429,
333
334 /// 431 Request Header Fields Too Large
335 ///
336 /// The server is unwilling to process the request because its header fields
337 /// are too large. The request may be resubmitted after reducing the
338 /// size of the request header fields.
339 RequestHeaderFieldsTooLarge = 431,
340
341 /// 451 Unavailable For Legal Reasons
342 ///
343 /// The user-agent requested a resource that cannot legally be provided,
344 /// such as a web page censored by a government.
345 UnavailableForLegalReasons = 451,
346
347 /// 500 Internal Server Error
348 ///
349 /// The server has encountered a situation it doesn't know how to handle.
350 InternalServerError = 500,
351
352 /// 501 Not Implemented
353 ///
354 /// The request method is not supported by the server and cannot be handled.
355 /// The only methods that servers are required to support (and therefore
356 /// that must not return this code) are GET and HEAD.
357 NotImplemented = 501,
358
359 /// 502 Bad Gateway
360 ///
361 /// This error response means that the server, while working as a gateway to
362 /// get a response needed to handle the request, got an invalid
363 /// response.
364 BadGateway = 502,
365
366 /// 503 Service Unavailable
367 ///
368 /// The server is not ready to handle the request. Common causes are a
369 /// server that is down for maintenance or that is overloaded. Note that
370 /// together with this response, a user-friendly page explaining the
371 /// problem should be sent. This responses should be used for temporary
372 /// conditions and the Retry-After: HTTP header should, if possible, contain
373 /// the estimated time before the recovery of the service. The webmaster
374 /// must also take care about the caching-related headers that are sent
375 /// along with this response, as these temporary condition responses
376 /// should usually not be cached.
377 ServiceUnavailable = 503,
378
379 /// 504 Gateway Timeout
380 ///
381 /// This error response is given when the server is acting as a gateway and
382 /// cannot get a response in time.
383 GatewayTimeout = 504,
384
385 /// 505 HTTP Version Not Supported
386 ///
387 /// The HTTP version used in the request is not supported by the server.
388 HttpVersionNotSupported = 505,
389
390 /// 506 Variant Also Negotiates
391 ///
392 /// The server has an internal configuration error: the chosen variant
393 /// resource is configured to engage in transparent content negotiation
394 /// itself, and is therefore not a proper end point in the negotiation
395 /// process.
396 VariantAlsoNegotiates = 506,
397
398 /// 507 Insufficient Storage
399 ///
400 /// The server is unable to store the representation needed to complete the
401 /// request.
402 InsufficientStorage = 507,
403
404 /// 508 Loop Detected
405 ///
406 /// The server detected an infinite loop while processing the request.
407 LoopDetected = 508,
408
409 /// 510 Not Extended
410 ///
411 /// Further extensions to the request are required for the server to fulfil
412 /// it.
413 NotExtended = 510,
414
415 /// 511 Network Authentication Required
416 ///
417 /// The 511 status code indicates that the client needs to authenticate to
418 /// gain network access.
419 NetworkAuthenticationRequired = 511,
420}
421
422impl StatusCode {
423 /// Returns `true` if the status code is `1xx` range.
424 ///
425 /// If this returns `true` it indicates that the request was received,
426 /// continuing process.
427 pub fn is_informational(&self) -> bool {
428 let num: u16 = (*self).into();
429 (100..200).contains(&num)
430 }
431
432 /// Returns `true` if the status code is the `2xx` range.
433 ///
434 /// If this returns `true` it indicates that the request was successfully
435 /// received, understood, and accepted.
436 pub fn is_success(&self) -> bool {
437 let num: u16 = (*self).into();
438 (200..300).contains(&num)
439 }
440
441 /// Returns `true` if the status code is the `3xx` range.
442 ///
443 /// If this returns `true` it indicates that further action needs to be
444 /// taken in order to complete the request.
445 pub fn is_redirection(&self) -> bool {
446 let num: u16 = (*self).into();
447 (300..400).contains(&num)
448 }
449
450 /// Returns `true` if the status code is the `4xx` range.
451 ///
452 /// If this returns `true` it indicates that the request contains bad syntax
453 /// or cannot be fulfilled.
454 pub fn is_client_error(&self) -> bool {
455 let num: u16 = (*self).into();
456 (400..500).contains(&num)
457 }
458
459 /// Returns `true` if the status code is the `5xx` range.
460 ///
461 /// If this returns `true` it indicates that the server failed to fulfill an
462 /// apparently valid request.
463 pub fn is_server_error(&self) -> bool {
464 let num: u16 = (*self).into();
465 (500..600).contains(&num)
466 }
467
468 /// The canonical reason for a given status code
469 pub fn canonical_reason(&self) -> &'static str {
470 match self {
471 StatusCode::Continue => "Continue",
472 StatusCode::SwitchingProtocols => "Switching Protocols",
473 StatusCode::EarlyHints => "Early Hints",
474 StatusCode::Ok => "OK",
475 StatusCode::Created => "Created",
476 StatusCode::Accepted => "Accepted",
477 StatusCode::NonAuthoritativeInformation => "Non Authoritative Information",
478 StatusCode::NoContent => "No Content",
479 StatusCode::ResetContent => "Reset Content",
480 StatusCode::PartialContent => "Partial Content",
481 StatusCode::MultiStatus => "Multi-Status",
482 StatusCode::ImUsed => "Im Used",
483 StatusCode::MultipleChoice => "Multiple Choice",
484 StatusCode::MovedPermanently => "Moved Permanently",
485 StatusCode::Found => "Found",
486 StatusCode::SeeOther => "See Other",
487 StatusCode::NotModified => "Not Modified",
488 StatusCode::TemporaryRedirect => "Temporary Redirect",
489 StatusCode::PermanentRedirect => "Permanent Redirect",
490 StatusCode::BadRequest => "Bad Request",
491 StatusCode::Unauthorized => "Unauthorized",
492 StatusCode::PaymentRequired => "Payment Required",
493 StatusCode::Forbidden => "Forbidden",
494 StatusCode::NotFound => "Not Found",
495 StatusCode::MethodNotAllowed => "Method Not Allowed",
496 StatusCode::NotAcceptable => "Not Acceptable",
497 StatusCode::ProxyAuthenticationRequired => "Proxy Authentication Required",
498 StatusCode::RequestTimeout => "Request Timeout",
499 StatusCode::Conflict => "Conflict",
500 StatusCode::Gone => "Gone",
501 StatusCode::LengthRequired => "Length Required",
502 StatusCode::PreconditionFailed => "Precondition Failed",
503 StatusCode::PayloadTooLarge => "Payload Too Large",
504 StatusCode::UriTooLong => "URI Too Long",
505 StatusCode::UnsupportedMediaType => "Unsupported Media Type",
506 StatusCode::RequestedRangeNotSatisfiable => "Requested Range Not Satisfiable",
507 StatusCode::ExpectationFailed => "Expectation Failed",
508 StatusCode::ImATeapot => "I'm a teapot",
509 StatusCode::MisdirectedRequest => "Misdirected Request",
510 StatusCode::UnprocessableEntity => "Unprocessable Entity",
511 StatusCode::Locked => "Locked",
512 StatusCode::FailedDependency => "Failed Dependency",
513 StatusCode::TooEarly => "Too Early",
514 StatusCode::UpgradeRequired => "Upgrade Required",
515 StatusCode::PreconditionRequired => "Precondition Required",
516 StatusCode::TooManyRequests => "Too Many Requests",
517 StatusCode::RequestHeaderFieldsTooLarge => "Request Header Fields Too Large",
518 StatusCode::UnavailableForLegalReasons => "Unavailable For Legal Reasons",
519 StatusCode::InternalServerError => "Internal Server Error",
520 StatusCode::NotImplemented => "Not Implemented",
521 StatusCode::BadGateway => "Bad Gateway",
522 StatusCode::ServiceUnavailable => "Service Unavailable",
523 StatusCode::GatewayTimeout => "Gateway Timeout",
524 StatusCode::HttpVersionNotSupported => "HTTP Version Not Supported",
525 StatusCode::VariantAlsoNegotiates => "Variant Also Negotiates",
526 StatusCode::InsufficientStorage => "Insufficient Storage",
527 StatusCode::LoopDetected => "Loop Detected",
528 StatusCode::NotExtended => "Not Extended",
529 StatusCode::NetworkAuthenticationRequired => "Network Authentication Required",
530 }
531 }
532}
533
534#[cfg(feature = "serde")]
535mod serde {
536 use super::StatusCode;
537 use serde::de::{Error as DeError, Unexpected, Visitor};
538 use serde::{Deserialize, Deserializer, Serialize, Serializer};
539 use std::fmt;
540
541 impl Serialize for StatusCode {
542 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
543 where
544 S: Serializer,
545 {
546 let value: u16 = *self as u16;
547 serializer.serialize_u16(value)
548 }
549 }
550
551 struct StatusCodeU16Visitor;
552
553 impl<'de> Visitor<'de> for StatusCodeU16Visitor {
554 type Value = StatusCode;
555
556 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
557 write!(formatter, "a u16 representing the status code")
558 }
559
560 fn visit_i16<E>(self, v: i16) -> Result<Self::Value, E>
561 where
562 E: DeError,
563 {
564 self.visit_u16(v as u16)
565 }
566
567 fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
568 where
569 E: DeError,
570 {
571 self.visit_u16(v as u16)
572 }
573
574 fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
575 where
576 E: DeError,
577 {
578 self.visit_u16(v as u16)
579 }
580
581 fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
582 where
583 E: DeError,
584 {
585 match StatusCode::try_from(v) {
586 Ok(status_code) => Ok(status_code),
587 Err(_) => Err(DeError::invalid_value(Unexpected::Unsigned(v as u64), &self)),
588 }
589 }
590
591 fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
592 where
593 E: DeError,
594 {
595 self.visit_u16(v as u16)
596 }
597
598 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
599 where
600 E: DeError,
601 {
602 self.visit_u16(v as u16)
603 }
604 }
605
606 impl<'de> Deserialize<'de> for StatusCode {
607 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
608 where
609 D: Deserializer<'de>,
610 {
611 deserializer.deserialize_any(StatusCodeU16Visitor)
612 }
613 }
614}
615
616impl From<StatusCode> for u16 {
617 fn from(code: StatusCode) -> u16 {
618 code as u16
619 }
620}
621
622impl std::convert::TryFrom<u16> for StatusCode {
623 type Error = crate::Error;
624
625 fn try_from(num: u16) -> Result<Self, Self::Error> {
626 match num {
627 100 => Ok(StatusCode::Continue),
628 101 => Ok(StatusCode::SwitchingProtocols),
629 103 => Ok(StatusCode::EarlyHints),
630 200 => Ok(StatusCode::Ok),
631 201 => Ok(StatusCode::Created),
632 202 => Ok(StatusCode::Accepted),
633 203 => Ok(StatusCode::NonAuthoritativeInformation),
634 204 => Ok(StatusCode::NoContent),
635 205 => Ok(StatusCode::ResetContent),
636 206 => Ok(StatusCode::PartialContent),
637 207 => Ok(StatusCode::MultiStatus),
638 226 => Ok(StatusCode::ImUsed),
639 300 => Ok(StatusCode::MultipleChoice),
640 301 => Ok(StatusCode::MovedPermanently),
641 302 => Ok(StatusCode::Found),
642 303 => Ok(StatusCode::SeeOther),
643 304 => Ok(StatusCode::NotModified),
644 307 => Ok(StatusCode::TemporaryRedirect),
645 308 => Ok(StatusCode::PermanentRedirect),
646 400 => Ok(StatusCode::BadRequest),
647 401 => Ok(StatusCode::Unauthorized),
648 402 => Ok(StatusCode::PaymentRequired),
649 403 => Ok(StatusCode::Forbidden),
650 404 => Ok(StatusCode::NotFound),
651 405 => Ok(StatusCode::MethodNotAllowed),
652 406 => Ok(StatusCode::NotAcceptable),
653 407 => Ok(StatusCode::ProxyAuthenticationRequired),
654 408 => Ok(StatusCode::RequestTimeout),
655 409 => Ok(StatusCode::Conflict),
656 410 => Ok(StatusCode::Gone),
657 411 => Ok(StatusCode::LengthRequired),
658 412 => Ok(StatusCode::PreconditionFailed),
659 413 => Ok(StatusCode::PayloadTooLarge),
660 414 => Ok(StatusCode::UriTooLong),
661 415 => Ok(StatusCode::UnsupportedMediaType),
662 416 => Ok(StatusCode::RequestedRangeNotSatisfiable),
663 417 => Ok(StatusCode::ExpectationFailed),
664 418 => Ok(StatusCode::ImATeapot),
665 421 => Ok(StatusCode::MisdirectedRequest),
666 422 => Ok(StatusCode::UnprocessableEntity),
667 423 => Ok(StatusCode::Locked),
668 424 => Ok(StatusCode::FailedDependency),
669 425 => Ok(StatusCode::TooEarly),
670 426 => Ok(StatusCode::UpgradeRequired),
671 428 => Ok(StatusCode::PreconditionRequired),
672 429 => Ok(StatusCode::TooManyRequests),
673 431 => Ok(StatusCode::RequestHeaderFieldsTooLarge),
674 451 => Ok(StatusCode::UnavailableForLegalReasons),
675 500 => Ok(StatusCode::InternalServerError),
676 501 => Ok(StatusCode::NotImplemented),
677 502 => Ok(StatusCode::BadGateway),
678 503 => Ok(StatusCode::ServiceUnavailable),
679 504 => Ok(StatusCode::GatewayTimeout),
680 505 => Ok(StatusCode::HttpVersionNotSupported),
681 506 => Ok(StatusCode::VariantAlsoNegotiates),
682 507 => Ok(StatusCode::InsufficientStorage),
683 508 => Ok(StatusCode::LoopDetected),
684 510 => Ok(StatusCode::NotExtended),
685 511 => Ok(StatusCode::NetworkAuthenticationRequired),
686 _ => crate::bail!("Invalid status code"),
687 }
688 }
689}
690
691impl PartialEq<StatusCode> for u16 {
692 fn eq(&self, other: &StatusCode) -> bool {
693 *self == *other as u16
694 }
695}
696
697impl PartialEq<u16> for StatusCode {
698 fn eq(&self, other: &u16) -> bool {
699 *self as u16 == *other
700 }
701}
702
703impl Debug for StatusCode {
704 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
705 write!(f, "{}: {}", *self as u16, self.canonical_reason())
706 }
707}
708
709impl Display for StatusCode {
710 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
711 write!(f, "{}: {}", *self as u16, self.canonical_reason())
712 }
713}
714
715#[cfg(test)]
716mod test {
717 use super::StatusCode;
718 #[test]
719 fn serde_as_u16() -> Result<(), serde_json::Error> {
720 let status_code: StatusCode = serde_json::from_str("202")?;
721 assert_eq!(StatusCode::Accepted, status_code);
722 assert_eq!(Some(202), serde_json::to_value(StatusCode::Accepted)?.as_u64());
723 Ok(())
724 }
725}