| 1 | //! HTTP status codes |
| 2 | //! |
| 3 | //! This module contains HTTP-status code related structs an errors. The main |
| 4 | //! type in this module is `StatusCode` which is not intended to be used through |
| 5 | //! this module but rather the `http::StatusCode` type. |
| 6 | //! |
| 7 | //! # Examples |
| 8 | //! |
| 9 | //! ``` |
| 10 | //! use http::StatusCode; |
| 11 | //! |
| 12 | //! assert_eq!(StatusCode::from_u16(200).unwrap(), StatusCode::OK); |
| 13 | //! assert_eq!(StatusCode::NOT_FOUND, 404); |
| 14 | //! assert!(StatusCode::OK.is_success()); |
| 15 | //! ``` |
| 16 | |
| 17 | use std::convert::TryFrom; |
| 18 | use std::error::Error; |
| 19 | use std::fmt; |
| 20 | use std::num::NonZeroU16; |
| 21 | use std::str::FromStr; |
| 22 | |
| 23 | /// An HTTP status code (`status-code` in RFC 9110 et al.). |
| 24 | /// |
| 25 | /// Constants are provided for known status codes, including those in the IANA |
| 26 | /// [HTTP Status Code Registry]( |
| 27 | /// https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml). |
| 28 | /// |
| 29 | /// Status code values in the range 100-999 (inclusive) are supported by this |
| 30 | /// type. Values in the range 100-599 are semantically classified by the most |
| 31 | /// significant digit. See [`StatusCode::is_success`], etc. Values above 599 |
| 32 | /// are unclassified but allowed for legacy compatibility, though their use is |
| 33 | /// discouraged. Applications may interpret such values as protocol errors. |
| 34 | /// |
| 35 | /// # Examples |
| 36 | /// |
| 37 | /// ``` |
| 38 | /// use http::StatusCode; |
| 39 | /// |
| 40 | /// assert_eq!(StatusCode::from_u16(200).unwrap(), StatusCode::OK); |
| 41 | /// assert_eq!(StatusCode::NOT_FOUND.as_u16(), 404); |
| 42 | /// assert!(StatusCode::OK.is_success()); |
| 43 | /// ``` |
| 44 | #[derive (Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
| 45 | pub struct StatusCode(NonZeroU16); |
| 46 | |
| 47 | /// A possible error value when converting a `StatusCode` from a `u16` or `&str`. |
| 48 | /// |
| 49 | /// This error indicates that the supplied input was not a valid number, was less |
| 50 | /// than 100, or was greater than 999. |
| 51 | pub struct InvalidStatusCode { |
| 52 | _priv: (), |
| 53 | } |
| 54 | |
| 55 | impl StatusCode { |
| 56 | /// Converts a u16 to a status code. |
| 57 | /// |
| 58 | /// The function validates the correctness of the supplied u16. It must be |
| 59 | /// greater or equal to 100 and less than 1000. |
| 60 | /// |
| 61 | /// # Example |
| 62 | /// |
| 63 | /// ``` |
| 64 | /// use http::StatusCode; |
| 65 | /// |
| 66 | /// let ok = StatusCode::from_u16(200).unwrap(); |
| 67 | /// assert_eq!(ok, StatusCode::OK); |
| 68 | /// |
| 69 | /// let err = StatusCode::from_u16(99); |
| 70 | /// assert!(err.is_err()); |
| 71 | /// ``` |
| 72 | #[inline ] |
| 73 | pub fn from_u16(src: u16) -> Result<StatusCode, InvalidStatusCode> { |
| 74 | if !(100..1000).contains(&src) { |
| 75 | return Err(InvalidStatusCode::new()); |
| 76 | } |
| 77 | |
| 78 | NonZeroU16::new(src) |
| 79 | .map(StatusCode) |
| 80 | .ok_or_else(InvalidStatusCode::new) |
| 81 | } |
| 82 | |
| 83 | /// Converts a `&[u8]` to a status code. |
| 84 | pub fn from_bytes(src: &[u8]) -> Result<StatusCode, InvalidStatusCode> { |
| 85 | if src.len() != 3 { |
| 86 | return Err(InvalidStatusCode::new()); |
| 87 | } |
| 88 | |
| 89 | let a = src[0].wrapping_sub(b'0' ) as u16; |
| 90 | let b = src[1].wrapping_sub(b'0' ) as u16; |
| 91 | let c = src[2].wrapping_sub(b'0' ) as u16; |
| 92 | |
| 93 | if a == 0 || a > 9 || b > 9 || c > 9 { |
| 94 | return Err(InvalidStatusCode::new()); |
| 95 | } |
| 96 | |
| 97 | let status = (a * 100) + (b * 10) + c; |
| 98 | NonZeroU16::new(status) |
| 99 | .map(StatusCode) |
| 100 | .ok_or_else(InvalidStatusCode::new) |
| 101 | } |
| 102 | |
| 103 | /// Returns the `u16` corresponding to this `StatusCode`. |
| 104 | /// |
| 105 | /// # Note |
| 106 | /// |
| 107 | /// This is the same as the `From<StatusCode>` implementation, but |
| 108 | /// included as an inherent method because that implementation doesn't |
| 109 | /// appear in rustdocs, as well as a way to force the type instead of |
| 110 | /// relying on inference. |
| 111 | /// |
| 112 | /// # Example |
| 113 | /// |
| 114 | /// ``` |
| 115 | /// let status = http::StatusCode::OK; |
| 116 | /// assert_eq!(status.as_u16(), 200); |
| 117 | /// ``` |
| 118 | #[inline ] |
| 119 | pub const fn as_u16(&self) -> u16 { |
| 120 | self.0.get() |
| 121 | } |
| 122 | |
| 123 | /// Returns a &str representation of the `StatusCode` |
| 124 | /// |
| 125 | /// The return value only includes a numerical representation of the |
| 126 | /// status code. The canonical reason is not included. |
| 127 | /// |
| 128 | /// # Example |
| 129 | /// |
| 130 | /// ``` |
| 131 | /// let status = http::StatusCode::OK; |
| 132 | /// assert_eq!(status.as_str(), "200" ); |
| 133 | /// ``` |
| 134 | #[inline ] |
| 135 | pub fn as_str(&self) -> &str { |
| 136 | let offset = (self.0.get() - 100) as usize; |
| 137 | let offset = offset * 3; |
| 138 | |
| 139 | // Invariant: self has checked range [100, 999] and CODE_DIGITS is |
| 140 | // ASCII-only, of length 900 * 3 = 2700 bytes |
| 141 | |
| 142 | #[cfg (debug_assertions)] |
| 143 | { |
| 144 | &CODE_DIGITS[offset..offset + 3] |
| 145 | } |
| 146 | |
| 147 | #[cfg (not(debug_assertions))] |
| 148 | unsafe { |
| 149 | CODE_DIGITS.get_unchecked(offset..offset + 3) |
| 150 | } |
| 151 | } |
| 152 | |
| 153 | /// Get the standardised `reason-phrase` for this status code. |
| 154 | /// |
| 155 | /// This is mostly here for servers writing responses, but could potentially have application |
| 156 | /// at other times. |
| 157 | /// |
| 158 | /// The reason phrase is defined as being exclusively for human readers. You should avoid |
| 159 | /// deriving any meaning from it at all costs. |
| 160 | /// |
| 161 | /// Bear in mind also that in HTTP/2.0 and HTTP/3.0 the reason phrase is abolished from |
| 162 | /// transmission, and so this canonical reason phrase really is the only reason phrase you’ll |
| 163 | /// find. |
| 164 | /// |
| 165 | /// # Example |
| 166 | /// |
| 167 | /// ``` |
| 168 | /// let status = http::StatusCode::OK; |
| 169 | /// assert_eq!(status.canonical_reason(), Some("OK" )); |
| 170 | /// ``` |
| 171 | pub fn canonical_reason(&self) -> Option<&'static str> { |
| 172 | canonical_reason(self.0.get()) |
| 173 | } |
| 174 | |
| 175 | /// Check if status is within 100-199. |
| 176 | #[inline ] |
| 177 | pub fn is_informational(&self) -> bool { |
| 178 | (100..200).contains(&self.0.get()) |
| 179 | } |
| 180 | |
| 181 | /// Check if status is within 200-299. |
| 182 | #[inline ] |
| 183 | pub fn is_success(&self) -> bool { |
| 184 | (200..300).contains(&self.0.get()) |
| 185 | } |
| 186 | |
| 187 | /// Check if status is within 300-399. |
| 188 | #[inline ] |
| 189 | pub fn is_redirection(&self) -> bool { |
| 190 | (300..400).contains(&self.0.get()) |
| 191 | } |
| 192 | |
| 193 | /// Check if status is within 400-499. |
| 194 | #[inline ] |
| 195 | pub fn is_client_error(&self) -> bool { |
| 196 | (400..500).contains(&self.0.get()) |
| 197 | } |
| 198 | |
| 199 | /// Check if status is within 500-599. |
| 200 | #[inline ] |
| 201 | pub fn is_server_error(&self) -> bool { |
| 202 | (500..600).contains(&self.0.get()) |
| 203 | } |
| 204 | } |
| 205 | |
| 206 | impl fmt::Debug for StatusCode { |
| 207 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 208 | fmt::Debug::fmt(&self.0, f) |
| 209 | } |
| 210 | } |
| 211 | |
| 212 | /// Formats the status code, *including* the canonical reason. |
| 213 | /// |
| 214 | /// # Example |
| 215 | /// |
| 216 | /// ``` |
| 217 | /// # use http::StatusCode; |
| 218 | /// assert_eq!(format!("{}" , StatusCode::OK), "200 OK" ); |
| 219 | /// ``` |
| 220 | impl fmt::Display for StatusCode { |
| 221 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 222 | write!( |
| 223 | f, |
| 224 | " {} {}" , |
| 225 | u16::from(*self), |
| 226 | self.canonical_reason().unwrap_or("<unknown status code>" ) |
| 227 | ) |
| 228 | } |
| 229 | } |
| 230 | |
| 231 | impl Default for StatusCode { |
| 232 | #[inline ] |
| 233 | fn default() -> StatusCode { |
| 234 | StatusCode::OK |
| 235 | } |
| 236 | } |
| 237 | |
| 238 | impl PartialEq<u16> for StatusCode { |
| 239 | #[inline ] |
| 240 | fn eq(&self, other: &u16) -> bool { |
| 241 | self.as_u16() == *other |
| 242 | } |
| 243 | } |
| 244 | |
| 245 | impl PartialEq<StatusCode> for u16 { |
| 246 | #[inline ] |
| 247 | fn eq(&self, other: &StatusCode) -> bool { |
| 248 | *self == other.as_u16() |
| 249 | } |
| 250 | } |
| 251 | |
| 252 | impl From<StatusCode> for u16 { |
| 253 | #[inline ] |
| 254 | fn from(status: StatusCode) -> u16 { |
| 255 | status.0.get() |
| 256 | } |
| 257 | } |
| 258 | |
| 259 | impl FromStr for StatusCode { |
| 260 | type Err = InvalidStatusCode; |
| 261 | |
| 262 | fn from_str(s: &str) -> Result<StatusCode, InvalidStatusCode> { |
| 263 | StatusCode::from_bytes(src:s.as_ref()) |
| 264 | } |
| 265 | } |
| 266 | |
| 267 | impl<'a> From<&'a StatusCode> for StatusCode { |
| 268 | #[inline ] |
| 269 | fn from(t: &'a StatusCode) -> Self { |
| 270 | t.to_owned() |
| 271 | } |
| 272 | } |
| 273 | |
| 274 | impl<'a> TryFrom<&'a [u8]> for StatusCode { |
| 275 | type Error = InvalidStatusCode; |
| 276 | |
| 277 | #[inline ] |
| 278 | fn try_from(t: &'a [u8]) -> Result<Self, Self::Error> { |
| 279 | StatusCode::from_bytes(src:t) |
| 280 | } |
| 281 | } |
| 282 | |
| 283 | impl<'a> TryFrom<&'a str> for StatusCode { |
| 284 | type Error = InvalidStatusCode; |
| 285 | |
| 286 | #[inline ] |
| 287 | fn try_from(t: &'a str) -> Result<Self, Self::Error> { |
| 288 | t.parse() |
| 289 | } |
| 290 | } |
| 291 | |
| 292 | impl TryFrom<u16> for StatusCode { |
| 293 | type Error = InvalidStatusCode; |
| 294 | |
| 295 | #[inline ] |
| 296 | fn try_from(t: u16) -> Result<Self, Self::Error> { |
| 297 | StatusCode::from_u16(src:t) |
| 298 | } |
| 299 | } |
| 300 | |
| 301 | macro_rules! status_codes { |
| 302 | ( |
| 303 | $( |
| 304 | $(#[$docs:meta])* |
| 305 | ($num:expr, $konst:ident, $phrase:expr); |
| 306 | )+ |
| 307 | ) => { |
| 308 | impl StatusCode { |
| 309 | $( |
| 310 | $(#[$docs])* |
| 311 | pub const $konst: StatusCode = StatusCode(unsafe { NonZeroU16::new_unchecked($num) }); |
| 312 | )+ |
| 313 | |
| 314 | } |
| 315 | |
| 316 | fn canonical_reason(num: u16) -> Option<&'static str> { |
| 317 | match num { |
| 318 | $( |
| 319 | $num => Some($phrase), |
| 320 | )+ |
| 321 | _ => None |
| 322 | } |
| 323 | } |
| 324 | } |
| 325 | } |
| 326 | |
| 327 | status_codes! { |
| 328 | /// 100 Continue |
| 329 | /// [[RFC9110, Section 15.2.1](https://datatracker.ietf.org/doc/html/rfc9110#section-15.2.1)] |
| 330 | (100, CONTINUE, "Continue" ); |
| 331 | /// 101 Switching Protocols |
| 332 | /// [[RFC9110, Section 15.2.2](https://datatracker.ietf.org/doc/html/rfc9110#section-15.2.2)] |
| 333 | (101, SWITCHING_PROTOCOLS, "Switching Protocols" ); |
| 334 | /// 102 Processing |
| 335 | /// [[RFC2518, Section 10.1](https://datatracker.ietf.org/doc/html/rfc2518#section-10.1)] |
| 336 | (102, PROCESSING, "Processing" ); |
| 337 | |
| 338 | /// 200 OK |
| 339 | /// [[RFC9110, Section 15.3.1](https://datatracker.ietf.org/doc/html/rfc9110#section-15.3.1)] |
| 340 | (200, OK, "OK" ); |
| 341 | /// 201 Created |
| 342 | /// [[RFC9110, Section 15.3.2](https://datatracker.ietf.org/doc/html/rfc9110#section-15.3.2)] |
| 343 | (201, CREATED, "Created" ); |
| 344 | /// 202 Accepted |
| 345 | /// [[RFC9110, Section 15.3.3](https://datatracker.ietf.org/doc/html/rfc9110#section-15.3.3)] |
| 346 | (202, ACCEPTED, "Accepted" ); |
| 347 | /// 203 Non-Authoritative Information |
| 348 | /// [[RFC9110, Section 15.3.4](https://datatracker.ietf.org/doc/html/rfc9110#section-15.3.4)] |
| 349 | (203, NON_AUTHORITATIVE_INFORMATION, "Non Authoritative Information" ); |
| 350 | /// 204 No Content |
| 351 | /// [[RFC9110, Section 15.3.5](https://datatracker.ietf.org/doc/html/rfc9110#section-15.3.5)] |
| 352 | (204, NO_CONTENT, "No Content" ); |
| 353 | /// 205 Reset Content |
| 354 | /// [[RFC9110, Section 15.3.6](https://datatracker.ietf.org/doc/html/rfc9110#section-15.3.6)] |
| 355 | (205, RESET_CONTENT, "Reset Content" ); |
| 356 | /// 206 Partial Content |
| 357 | /// [[RFC9110, Section 15.3.7](https://datatracker.ietf.org/doc/html/rfc9110#section-15.3.7)] |
| 358 | (206, PARTIAL_CONTENT, "Partial Content" ); |
| 359 | /// 207 Multi-Status |
| 360 | /// [[RFC4918, Section 11.1](https://datatracker.ietf.org/doc/html/rfc4918#section-11.1)] |
| 361 | (207, MULTI_STATUS, "Multi-Status" ); |
| 362 | /// 208 Already Reported |
| 363 | /// [[RFC5842, Section 7.1](https://datatracker.ietf.org/doc/html/rfc5842#section-7.1)] |
| 364 | (208, ALREADY_REPORTED, "Already Reported" ); |
| 365 | |
| 366 | /// 226 IM Used |
| 367 | /// [[RFC3229, Section 10.4.1](https://datatracker.ietf.org/doc/html/rfc3229#section-10.4.1)] |
| 368 | (226, IM_USED, "IM Used" ); |
| 369 | |
| 370 | /// 300 Multiple Choices |
| 371 | /// [[RFC9110, Section 15.4.1](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.1)] |
| 372 | (300, MULTIPLE_CHOICES, "Multiple Choices" ); |
| 373 | /// 301 Moved Permanently |
| 374 | /// [[RFC9110, Section 15.4.2](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.2)] |
| 375 | (301, MOVED_PERMANENTLY, "Moved Permanently" ); |
| 376 | /// 302 Found |
| 377 | /// [[RFC9110, Section 15.4.3](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.3)] |
| 378 | (302, FOUND, "Found" ); |
| 379 | /// 303 See Other |
| 380 | /// [[RFC9110, Section 15.4.4](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.4)] |
| 381 | (303, SEE_OTHER, "See Other" ); |
| 382 | /// 304 Not Modified |
| 383 | /// [[RFC9110, Section 15.4.5](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.5)] |
| 384 | (304, NOT_MODIFIED, "Not Modified" ); |
| 385 | /// 305 Use Proxy |
| 386 | /// [[RFC9110, Section 15.4.6](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.6)] |
| 387 | (305, USE_PROXY, "Use Proxy" ); |
| 388 | /// 307 Temporary Redirect |
| 389 | /// [[RFC9110, Section 15.4.7](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.7)] |
| 390 | (307, TEMPORARY_REDIRECT, "Temporary Redirect" ); |
| 391 | /// 308 Permanent Redirect |
| 392 | /// [[RFC9110, Section 15.4.8](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.8)] |
| 393 | (308, PERMANENT_REDIRECT, "Permanent Redirect" ); |
| 394 | |
| 395 | /// 400 Bad Request |
| 396 | /// [[RFC9110, Section 15.5.1](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.1)] |
| 397 | (400, BAD_REQUEST, "Bad Request" ); |
| 398 | /// 401 Unauthorized |
| 399 | /// [[RFC9110, Section 15.5.2](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.2)] |
| 400 | (401, UNAUTHORIZED, "Unauthorized" ); |
| 401 | /// 402 Payment Required |
| 402 | /// [[RFC9110, Section 15.5.3](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.3)] |
| 403 | (402, PAYMENT_REQUIRED, "Payment Required" ); |
| 404 | /// 403 Forbidden |
| 405 | /// [[RFC9110, Section 15.5.4](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.4)] |
| 406 | (403, FORBIDDEN, "Forbidden" ); |
| 407 | /// 404 Not Found |
| 408 | /// [[RFC9110, Section 15.5.5](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.5)] |
| 409 | (404, NOT_FOUND, "Not Found" ); |
| 410 | /// 405 Method Not Allowed |
| 411 | /// [[RFC9110, Section 15.5.6](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.6)] |
| 412 | (405, METHOD_NOT_ALLOWED, "Method Not Allowed" ); |
| 413 | /// 406 Not Acceptable |
| 414 | /// [[RFC9110, Section 15.5.7](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.7)] |
| 415 | (406, NOT_ACCEPTABLE, "Not Acceptable" ); |
| 416 | /// 407 Proxy Authentication Required |
| 417 | /// [[RFC9110, Section 15.5.8](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.8)] |
| 418 | (407, PROXY_AUTHENTICATION_REQUIRED, "Proxy Authentication Required" ); |
| 419 | /// 408 Request Timeout |
| 420 | /// [[RFC9110, Section 15.5.9](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.9)] |
| 421 | (408, REQUEST_TIMEOUT, "Request Timeout" ); |
| 422 | /// 409 Conflict |
| 423 | /// [[RFC9110, Section 15.5.10](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.10)] |
| 424 | (409, CONFLICT, "Conflict" ); |
| 425 | /// 410 Gone |
| 426 | /// [[RFC9110, Section 15.5.11](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.11)] |
| 427 | (410, GONE, "Gone" ); |
| 428 | /// 411 Length Required |
| 429 | /// [[RFC9110, Section 15.5.12](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.12)] |
| 430 | (411, LENGTH_REQUIRED, "Length Required" ); |
| 431 | /// 412 Precondition Failed |
| 432 | /// [[RFC9110, Section 15.5.13](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.13)] |
| 433 | (412, PRECONDITION_FAILED, "Precondition Failed" ); |
| 434 | /// 413 Payload Too Large |
| 435 | /// [[RFC9110, Section 15.5.14](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.14)] |
| 436 | (413, PAYLOAD_TOO_LARGE, "Payload Too Large" ); |
| 437 | /// 414 URI Too Long |
| 438 | /// [[RFC9110, Section 15.5.15](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.15)] |
| 439 | (414, URI_TOO_LONG, "URI Too Long" ); |
| 440 | /// 415 Unsupported Media Type |
| 441 | /// [[RFC9110, Section 15.5.16](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.16)] |
| 442 | (415, UNSUPPORTED_MEDIA_TYPE, "Unsupported Media Type" ); |
| 443 | /// 416 Range Not Satisfiable |
| 444 | /// [[RFC9110, Section 15.5.17](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.17)] |
| 445 | (416, RANGE_NOT_SATISFIABLE, "Range Not Satisfiable" ); |
| 446 | /// 417 Expectation Failed |
| 447 | /// [[RFC9110, Section 15.5.18](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.18)] |
| 448 | (417, EXPECTATION_FAILED, "Expectation Failed" ); |
| 449 | /// 418 I'm a teapot |
| 450 | /// [curiously not registered by IANA but [RFC2324, Section 2.3.2](https://datatracker.ietf.org/doc/html/rfc2324#section-2.3.2)] |
| 451 | (418, IM_A_TEAPOT, "I'm a teapot" ); |
| 452 | |
| 453 | /// 421 Misdirected Request |
| 454 | /// [[RFC9110, Section 15.5.20](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.20)] |
| 455 | (421, MISDIRECTED_REQUEST, "Misdirected Request" ); |
| 456 | /// 422 Unprocessable Entity |
| 457 | /// [[RFC9110, Section 15.5.21](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.21)] |
| 458 | (422, UNPROCESSABLE_ENTITY, "Unprocessable Entity" ); |
| 459 | /// 423 Locked |
| 460 | /// [[RFC4918, Section 11.3](https://datatracker.ietf.org/doc/html/rfc4918#section-11.3)] |
| 461 | (423, LOCKED, "Locked" ); |
| 462 | /// 424 Failed Dependency |
| 463 | /// [[RFC4918, Section 11.4](https://tools.ietf.org/html/rfc4918#section-11.4)] |
| 464 | (424, FAILED_DEPENDENCY, "Failed Dependency" ); |
| 465 | |
| 466 | /// 425 Too early |
| 467 | /// [[RFC8470, Section 5.2](https://httpwg.org/specs/rfc8470.html#status)] |
| 468 | (425, TOO_EARLY, "Too Early" ); |
| 469 | |
| 470 | /// 426 Upgrade Required |
| 471 | /// [[RFC9110, Section 15.5.22](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.22)] |
| 472 | (426, UPGRADE_REQUIRED, "Upgrade Required" ); |
| 473 | |
| 474 | /// 428 Precondition Required |
| 475 | /// [[RFC6585, Section 3](https://datatracker.ietf.org/doc/html/rfc6585#section-3)] |
| 476 | (428, PRECONDITION_REQUIRED, "Precondition Required" ); |
| 477 | /// 429 Too Many Requests |
| 478 | /// [[RFC6585, Section 4](https://datatracker.ietf.org/doc/html/rfc6585#section-4)] |
| 479 | (429, TOO_MANY_REQUESTS, "Too Many Requests" ); |
| 480 | |
| 481 | /// 431 Request Header Fields Too Large |
| 482 | /// [[RFC6585, Section 5](https://datatracker.ietf.org/doc/html/rfc6585#section-5)] |
| 483 | (431, REQUEST_HEADER_FIELDS_TOO_LARGE, "Request Header Fields Too Large" ); |
| 484 | |
| 485 | /// 451 Unavailable For Legal Reasons |
| 486 | /// [[RFC7725, Section 3](https://tools.ietf.org/html/rfc7725#section-3)] |
| 487 | (451, UNAVAILABLE_FOR_LEGAL_REASONS, "Unavailable For Legal Reasons" ); |
| 488 | |
| 489 | /// 500 Internal Server Error |
| 490 | /// [[RFC9110, Section 15.6.1](https://datatracker.ietf.org/doc/html/rfc9110#section-15.6.1)] |
| 491 | (500, INTERNAL_SERVER_ERROR, "Internal Server Error" ); |
| 492 | /// 501 Not Implemented |
| 493 | /// [[RFC9110, Section 15.6.2](https://datatracker.ietf.org/doc/html/rfc9110#section-15.6.2)] |
| 494 | (501, NOT_IMPLEMENTED, "Not Implemented" ); |
| 495 | /// 502 Bad Gateway |
| 496 | /// [[RFC9110, Section 15.6.3](https://datatracker.ietf.org/doc/html/rfc9110#section-15.6.3)] |
| 497 | (502, BAD_GATEWAY, "Bad Gateway" ); |
| 498 | /// 503 Service Unavailable |
| 499 | /// [[RFC9110, Section 15.6.4](https://datatracker.ietf.org/doc/html/rfc9110#section-15.6.4)] |
| 500 | (503, SERVICE_UNAVAILABLE, "Service Unavailable" ); |
| 501 | /// 504 Gateway Timeout |
| 502 | /// [[RFC9110, Section 15.6.5](https://datatracker.ietf.org/doc/html/rfc9110#section-15.6.5)] |
| 503 | (504, GATEWAY_TIMEOUT, "Gateway Timeout" ); |
| 504 | /// 505 HTTP Version Not Supported |
| 505 | /// [[RFC9110, Section 15.6.6](https://datatracker.ietf.org/doc/html/rfc9110#section-15.6.6)] |
| 506 | (505, HTTP_VERSION_NOT_SUPPORTED, "HTTP Version Not Supported" ); |
| 507 | /// 506 Variant Also Negotiates |
| 508 | /// [[RFC2295, Section 8.1](https://datatracker.ietf.org/doc/html/rfc2295#section-8.1)] |
| 509 | (506, VARIANT_ALSO_NEGOTIATES, "Variant Also Negotiates" ); |
| 510 | /// 507 Insufficient Storage |
| 511 | /// [[RFC4918, Section 11.5](https://datatracker.ietf.org/doc/html/rfc4918#section-11.5)] |
| 512 | (507, INSUFFICIENT_STORAGE, "Insufficient Storage" ); |
| 513 | /// 508 Loop Detected |
| 514 | /// [[RFC5842, Section 7.2](https://datatracker.ietf.org/doc/html/rfc5842#section-7.2)] |
| 515 | (508, LOOP_DETECTED, "Loop Detected" ); |
| 516 | |
| 517 | /// 510 Not Extended |
| 518 | /// [[RFC2774, Section 7](https://datatracker.ietf.org/doc/html/rfc2774#section-7)] |
| 519 | (510, NOT_EXTENDED, "Not Extended" ); |
| 520 | /// 511 Network Authentication Required |
| 521 | /// [[RFC6585, Section 6](https://datatracker.ietf.org/doc/html/rfc6585#section-6)] |
| 522 | (511, NETWORK_AUTHENTICATION_REQUIRED, "Network Authentication Required" ); |
| 523 | } |
| 524 | |
| 525 | impl InvalidStatusCode { |
| 526 | fn new() -> InvalidStatusCode { |
| 527 | InvalidStatusCode { _priv: () } |
| 528 | } |
| 529 | } |
| 530 | |
| 531 | impl fmt::Debug for InvalidStatusCode { |
| 532 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| 533 | fDebugStruct<'_, '_>.debug_struct(name:"InvalidStatusCode" ) |
| 534 | // skip _priv noise |
| 535 | .finish() |
| 536 | } |
| 537 | } |
| 538 | |
| 539 | impl fmt::Display for InvalidStatusCode { |
| 540 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 541 | f.write_str(data:"invalid status code" ) |
| 542 | } |
| 543 | } |
| 544 | |
| 545 | impl Error for InvalidStatusCode {} |
| 546 | |
| 547 | // A string of packed 3-ASCII-digit status code values for the supported range |
| 548 | // of [100, 999] (900 codes, 2700 bytes). |
| 549 | const CODE_DIGITS: &str = "\ |
| 550 | 100101102103104105106107108109110111112113114115116117118119\ |
| 551 | 120121122123124125126127128129130131132133134135136137138139\ |
| 552 | 140141142143144145146147148149150151152153154155156157158159\ |
| 553 | 160161162163164165166167168169170171172173174175176177178179\ |
| 554 | 180181182183184185186187188189190191192193194195196197198199\ |
| 555 | 200201202203204205206207208209210211212213214215216217218219\ |
| 556 | 220221222223224225226227228229230231232233234235236237238239\ |
| 557 | 240241242243244245246247248249250251252253254255256257258259\ |
| 558 | 260261262263264265266267268269270271272273274275276277278279\ |
| 559 | 280281282283284285286287288289290291292293294295296297298299\ |
| 560 | 300301302303304305306307308309310311312313314315316317318319\ |
| 561 | 320321322323324325326327328329330331332333334335336337338339\ |
| 562 | 340341342343344345346347348349350351352353354355356357358359\ |
| 563 | 360361362363364365366367368369370371372373374375376377378379\ |
| 564 | 380381382383384385386387388389390391392393394395396397398399\ |
| 565 | 400401402403404405406407408409410411412413414415416417418419\ |
| 566 | 420421422423424425426427428429430431432433434435436437438439\ |
| 567 | 440441442443444445446447448449450451452453454455456457458459\ |
| 568 | 460461462463464465466467468469470471472473474475476477478479\ |
| 569 | 480481482483484485486487488489490491492493494495496497498499\ |
| 570 | 500501502503504505506507508509510511512513514515516517518519\ |
| 571 | 520521522523524525526527528529530531532533534535536537538539\ |
| 572 | 540541542543544545546547548549550551552553554555556557558559\ |
| 573 | 560561562563564565566567568569570571572573574575576577578579\ |
| 574 | 580581582583584585586587588589590591592593594595596597598599\ |
| 575 | 600601602603604605606607608609610611612613614615616617618619\ |
| 576 | 620621622623624625626627628629630631632633634635636637638639\ |
| 577 | 640641642643644645646647648649650651652653654655656657658659\ |
| 578 | 660661662663664665666667668669670671672673674675676677678679\ |
| 579 | 680681682683684685686687688689690691692693694695696697698699\ |
| 580 | 700701702703704705706707708709710711712713714715716717718719\ |
| 581 | 720721722723724725726727728729730731732733734735736737738739\ |
| 582 | 740741742743744745746747748749750751752753754755756757758759\ |
| 583 | 760761762763764765766767768769770771772773774775776777778779\ |
| 584 | 780781782783784785786787788789790791792793794795796797798799\ |
| 585 | 800801802803804805806807808809810811812813814815816817818819\ |
| 586 | 820821822823824825826827828829830831832833834835836837838839\ |
| 587 | 840841842843844845846847848849850851852853854855856857858859\ |
| 588 | 860861862863864865866867868869870871872873874875876877878879\ |
| 589 | 880881882883884885886887888889890891892893894895896897898899\ |
| 590 | 900901902903904905906907908909910911912913914915916917918919\ |
| 591 | 920921922923924925926927928929930931932933934935936937938939\ |
| 592 | 940941942943944945946947948949950951952953954955956957958959\ |
| 593 | 960961962963964965966967968969970971972973974975976977978979\ |
| 594 | 980981982983984985986987988989990991992993994995996997998999" ; |
| 595 | |