1use std::error::Error;
8use std::fmt::{self, Display, Formatter};
9use std::str::FromStr;
10
11#[derive(Clone, Debug, PartialEq, Eq)]
13pub(crate) enum Version {
14 Http1_0,
15 Http1_1,
16}
17
18impl FromStr for Version {
19 type Err = ();
20
21 fn from_str(s: &str) -> Result<Self, Self::Err> {
22 match s {
23 "HTTP/1.0" => Ok(Version::Http1_0),
24 _ => Ok(Version::Http1_1),
25 }
26 }
27}
28
29impl Display for Version {
30 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
31 write!(
32 f,
33 "{}",
34 match self {
35 Version::Http1_0 => "HTTP/1.0",
36 Version::Http1_1 => "HTTP/1.1",
37 }
38 )
39 }
40}
41
42#[derive(Clone, Copy, Debug, Eq, PartialEq)]
45pub enum Method {
46 Get,
48 Head,
50 Post,
52 Put,
54 Delete,
56 Connect,
58 Options,
60 Trace,
62 Patch,
64}
65
66impl FromStr for Method {
67 type Err = InvalidMethodError;
68
69 fn from_str(s: &str) -> Result<Self, Self::Err> {
70 match s {
71 "GET" => Ok(Method::Get),
72 "HEAD" => Ok(Method::Head),
73 "POST" => Ok(Method::Post),
74 "PUT" => Ok(Method::Put),
75 "DELETE" => Ok(Method::Delete),
76 "CONNECT" => Ok(Method::Connect),
77 "OPTIONS" => Ok(Method::Options),
78 "TRACE" => Ok(Method::Trace),
79 "PATCH" => Ok(Method::Patch),
80 _ => Err(InvalidMethodError),
81 }
82 }
83}
84
85impl Display for Method {
86 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
87 write!(
88 f,
89 "{}",
90 match self {
91 Method::Get => "GET",
92 Method::Head => "HEAD",
93 Method::Post => "POST",
94 Method::Put => "PUT",
95 Method::Delete => "DELETE",
96 Method::Connect => "CONNECT",
97 Method::Options => "OPTIONS",
98 Method::Trace => "TRACE",
99 Method::Patch => "PATCH",
100 }
101 )
102 }
103}
104
105#[derive(Debug)]
107pub struct InvalidMethodError;
108
109impl Display for InvalidMethodError {
110 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
111 write!(f, "Invalid HTTP method")
112 }
113}
114
115impl Error for InvalidMethodError {}
116
117#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
120pub enum Status {
121 Continue = 100,
123 SwitchingProtocols = 101,
125 Processing = 102,
127 #[default]
129 Ok = 200,
130 Created = 201,
132 Accepted = 202,
134 NonAuthoritativeInformation = 203,
136 NoContent = 204,
138 ResetContent = 205,
140 PartialContent = 206,
142 MultiStatus = 207,
144 AlreadyReported = 208,
146 IMUsed = 226,
148 MultipleChoices = 300,
150 MovedPermanently = 301,
152 Found = 302,
154 SeeOther = 303,
156 NotModified = 304,
158 UseProxy = 305,
160 TemporaryRedirect = 307,
162 PermanentRedirect = 308,
164 BadRequest = 400,
166 Unauthorized = 401,
168 PaymentRequired = 402,
170 Forbidden = 403,
172 NotFound = 404,
174 MethodNotAllowed = 405,
176 NotAcceptable = 406,
178 ProxyAuthenticationRequired = 407,
180 RequestTimeout = 408,
182 Conflict = 409,
184 Gone = 410,
186 LengthRequired = 411,
188 PreconditionFailed = 412,
190 PayloadTooLarge = 413,
192 URITooLong = 414,
194 UnsupportedMediaType = 415,
196 RangeNotSatisfiable = 416,
198 ExpectationFailed = 417,
200 ImATeapot = 418,
202 MisdirectedRequest = 421,
204 UnprocessableEntity = 422,
206 Locked = 423,
208 FailedDependency = 424,
210 TooEarly = 425,
212 UpgradeRequired = 426,
214 PreconditionRequired = 428,
216 TooManyRequests = 429,
218 RequestHeaderFieldsTooLarge = 431,
220 UnavailableForLegalReasons = 451,
222 InternalServerError = 500,
224 NotImplemented = 501,
226 BadGateway = 502,
228 ServiceUnavailable = 503,
230 GatewayTimeout = 504,
232 HTTPVersionNotSupported = 505,
234 VariantAlsoNegotiates = 506,
236 InsufficientStorage = 507,
238 LoopDetected = 508,
240 NotExtended = 510,
242 NetworkAuthenticationRequired = 511,
244}
245
246impl TryFrom<i32> for Status {
247 type Error = InvalidStatusError;
248
249 fn try_from(value: i32) -> Result<Self, Self::Error> {
250 match value {
251 100 => Ok(Status::Continue),
252 101 => Ok(Status::SwitchingProtocols),
253 102 => Ok(Status::Processing),
254 200 => Ok(Status::Ok),
255 201 => Ok(Status::Created),
256 202 => Ok(Status::Accepted),
257 203 => Ok(Status::NonAuthoritativeInformation),
258 204 => Ok(Status::NoContent),
259 205 => Ok(Status::ResetContent),
260 206 => Ok(Status::PartialContent),
261 207 => Ok(Status::MultiStatus),
262 208 => Ok(Status::AlreadyReported),
263 226 => Ok(Status::IMUsed),
264 300 => Ok(Status::MultipleChoices),
265 301 => Ok(Status::MovedPermanently),
266 302 => Ok(Status::Found),
267 303 => Ok(Status::SeeOther),
268 304 => Ok(Status::NotModified),
269 305 => Ok(Status::UseProxy),
270 307 => Ok(Status::TemporaryRedirect),
271 308 => Ok(Status::PermanentRedirect),
272 400 => Ok(Status::BadRequest),
273 401 => Ok(Status::Unauthorized),
274 402 => Ok(Status::PaymentRequired),
275 403 => Ok(Status::Forbidden),
276 404 => Ok(Status::NotFound),
277 405 => Ok(Status::MethodNotAllowed),
278 406 => Ok(Status::NotAcceptable),
279 407 => Ok(Status::ProxyAuthenticationRequired),
280 408 => Ok(Status::RequestTimeout),
281 409 => Ok(Status::Conflict),
282 410 => Ok(Status::Gone),
283 411 => Ok(Status::LengthRequired),
284 412 => Ok(Status::PreconditionFailed),
285 413 => Ok(Status::PayloadTooLarge),
286 414 => Ok(Status::URITooLong),
287 415 => Ok(Status::UnsupportedMediaType),
288 416 => Ok(Status::RangeNotSatisfiable),
289 417 => Ok(Status::ExpectationFailed),
290 418 => Ok(Status::ImATeapot),
291 421 => Ok(Status::MisdirectedRequest),
292 422 => Ok(Status::UnprocessableEntity),
293 423 => Ok(Status::Locked),
294 424 => Ok(Status::FailedDependency),
295 425 => Ok(Status::TooEarly),
296 426 => Ok(Status::UpgradeRequired),
297 428 => Ok(Status::PreconditionRequired),
298 429 => Ok(Status::TooManyRequests),
299 431 => Ok(Status::RequestHeaderFieldsTooLarge),
300 451 => Ok(Status::UnavailableForLegalReasons),
301 500 => Ok(Status::InternalServerError),
302 501 => Ok(Status::NotImplemented),
303 502 => Ok(Status::BadGateway),
304 503 => Ok(Status::ServiceUnavailable),
305 504 => Ok(Status::GatewayTimeout),
306 505 => Ok(Status::HTTPVersionNotSupported),
307 506 => Ok(Status::VariantAlsoNegotiates),
308 507 => Ok(Status::InsufficientStorage),
309 508 => Ok(Status::LoopDetected),
310 510 => Ok(Status::NotExtended),
311 511 => Ok(Status::NetworkAuthenticationRequired),
312 _ => Err(InvalidStatusError),
313 }
314 }
315}
316
317impl Display for Status {
318 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
319 write!(
320 f,
321 "{}",
322 match self {
323 Status::Continue => "100 Continue",
324 Status::SwitchingProtocols => "101 Switching Protocols",
325 Status::Processing => "102 Processing",
326 Status::Ok => "200 OK",
327 Status::Created => "201 Created",
328 Status::Accepted => "202 Accepted",
329 Status::NonAuthoritativeInformation => "203 Non-Authoritative Information",
330 Status::NoContent => "204 No Content",
331 Status::ResetContent => "205 Reset Content",
332 Status::PartialContent => "206 Partial Content",
333 Status::MultiStatus => "207 Multi-Status",
334 Status::AlreadyReported => "208 Already Reported",
335 Status::IMUsed => "226 IM Used",
336 Status::MultipleChoices => "300 Multiple Choices",
337 Status::MovedPermanently => "301 Moved Permanently",
338 Status::Found => "302 Found",
339 Status::SeeOther => "303 See Other",
340 Status::NotModified => "304 Not Modified",
341 Status::UseProxy => "305 Use Proxy",
342 Status::TemporaryRedirect => "307 Temporary Redirect",
343 Status::PermanentRedirect => "308 Permanent Redirect",
344 Status::BadRequest => "400 Bad Request",
345 Status::Unauthorized => "401 Unauthorized",
346 Status::PaymentRequired => "402 Payment Required",
347 Status::Forbidden => "403 Forbidden",
348 Status::NotFound => "404 Not Found",
349 Status::MethodNotAllowed => "405 Method Not Allowed",
350 Status::NotAcceptable => "406 Not Acceptable",
351 Status::ProxyAuthenticationRequired => "407 Proxy Authentication Required",
352 Status::RequestTimeout => "408 Request Timeout",
353 Status::Conflict => "409 Conflict",
354 Status::Gone => "410 Gone",
355 Status::LengthRequired => "411 Length Required",
356 Status::PreconditionFailed => "412 Precondition Failed",
357 Status::PayloadTooLarge => "413 Payload Too Large",
358 Status::URITooLong => "414 URI Too Long",
359 Status::UnsupportedMediaType => "415 Unsupported Media Type",
360 Status::RangeNotSatisfiable => "416 Range Not Satisfiable",
361 Status::ExpectationFailed => "417 Expectation Failed",
362 Status::ImATeapot => "418 I'm a teapot",
363 Status::MisdirectedRequest => "421 Misdirected Request",
364 Status::UnprocessableEntity => "422 Unprocessable Entity",
365 Status::Locked => "423 Locked",
366 Status::FailedDependency => "424 Failed Dependency",
367 Status::TooEarly => "425 Too Early",
368 Status::UpgradeRequired => "426 Upgrade Required",
369 Status::PreconditionRequired => "428 Precondition Required",
370 Status::TooManyRequests => "429 Too Many Requests",
371 Status::RequestHeaderFieldsTooLarge => "431 Request Header Fields Too Large",
372 Status::UnavailableForLegalReasons => "451 Unavailable For Legal Reasons",
373 Status::InternalServerError => "500 Internal Server Error",
374 Status::NotImplemented => "501 Not Implemented",
375 Status::BadGateway => "502 Bad Gateway",
376 Status::ServiceUnavailable => "503 Service Unavailable",
377 Status::GatewayTimeout => "504 Gateway Timeout",
378 Status::HTTPVersionNotSupported => "505 HTTP Version Not Supported",
379 Status::VariantAlsoNegotiates => "506 Variant Also Negotiates",
380 Status::InsufficientStorage => "507 Insufficient Storage",
381 Status::LoopDetected => "508 Loop Detected",
382 Status::NotExtended => "510 Not Extended",
383 Status::NetworkAuthenticationRequired => "511 Network Authentication Required",
384 }
385 )
386 }
387}
388
389#[derive(Debug)]
391pub struct InvalidStatusError;
392
393impl Display for InvalidStatusError {
394 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
395 write!(f, "Invalid HTTP status")
396 }
397}
398
399impl Error for InvalidStatusError {}