1use core::{error, fmt};
2
3use crate::core::Status;
4use crate::ffi::*;
5
6#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
8pub struct HTTPStatus(pub ngx_uint_t);
9
10#[derive(Debug)]
15pub struct InvalidHTTPStatusCode {
16 _priv: (),
17}
18
19impl InvalidHTTPStatusCode {
20 fn new() -> InvalidHTTPStatusCode {
21 InvalidHTTPStatusCode { _priv: () }
22 }
23}
24
25impl fmt::Display for InvalidHTTPStatusCode {
26 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
27 f.write_str("invalid status code")
28 }
29}
30
31impl error::Error for InvalidHTTPStatusCode {}
32
33impl From<HTTPStatus> for Status {
34 fn from(val: HTTPStatus) -> Self {
35 Status(val.0 as ngx_int_t)
36 }
37}
38
39impl From<HTTPStatus> for ngx_uint_t {
40 fn from(val: HTTPStatus) -> Self {
41 val.0
42 }
43}
44
45impl fmt::Debug for HTTPStatus {
46 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
47 fmt::Debug::fmt(&self.0, f)
48 }
49}
50
51impl HTTPStatus {
52 #[inline]
54 pub fn from_u16(src: u16) -> Result<HTTPStatus, InvalidHTTPStatusCode> {
55 if !(100..600).contains(&src) {
56 return Err(InvalidHTTPStatusCode::new());
57 }
58
59 Ok(HTTPStatus(src.into()))
60 }
61
62 pub fn from_bytes(src: &[u8]) -> Result<HTTPStatus, InvalidHTTPStatusCode> {
64 if src.len() != 3 {
65 return Err(InvalidHTTPStatusCode::new());
66 }
67
68 let a = src[0].wrapping_sub(b'0') as u16;
69 let b = src[1].wrapping_sub(b'0') as u16;
70 let c = src[2].wrapping_sub(b'0') as u16;
71
72 if a == 0 || a > 5 || b > 9 || c > 9 {
73 return Err(InvalidHTTPStatusCode::new());
74 }
75
76 let status = (a * 100) + (b * 10) + c;
77 Ok(HTTPStatus(status.into()))
78 }
79}
80
81macro_rules! http_status_codes {
82 (
83 $(
84 $(#[$docs:meta])*
85 ($num:expr, $konst:ident, $phrase:expr);
86 )+
87 ) => {
88 impl HTTPStatus {
89 $(
90 $(#[$docs])*
91 pub const $konst: HTTPStatus = HTTPStatus($num);
92 )+
93
94 }
95 }
96}
97
98http_status_codes! {
99 (100, CONTINUE, "Continue");
101 (101, SWITCHING_PROTOCOLS, "Switching Protocols");
103 (102, PROCESSING, "Processing");
105 (200, OK, "OK");
107 (201, CREATED, "Created");
109 (202, ACCEPTED, "Accepted");
111 (204, NO_CONTENT, "No Content");
113 (206, PARTIAL_CONTENT, "Partial Content");
115
116 (300, SPECIAL_RESPONSE, "SPECIAL_RESPONSE");
118 (301, MOVED_PERMANENTLY, "Moved Permanently");
120 (302, MOVED_TEMPORARILY, "Moved Temporarily");
122 (303, SEE_OTHER, "See Other");
124 (304, NOT_MODIFIED, "Not Modified");
126 (307, TEMPORARY_REDIRECT, "Temporary Redirect");
128 (308, PERMANENT_REDIRECT, "Permanent Redirect");
130
131 (400, BAD_REQUEST, "Bad Request");
133 (401, UNAUTHORIZED, "Unauthorized");
135 (403, FORBIDDEN, "Forbidden");
137 (404, NOT_FOUND, "Not Found");
139 (405, NOT_ALLOWED, "Method Not Allowed");
141 (408, REQUEST_TIME_OUT, "Request Time Out");
143 (409, CONFLICT, "Conflict");
145 (411, LENGTH_REQUIRED, "Length Required");
147 (412, PRECONDITION_FAILED, "Precondition Failed");
149 (413, REQUEST_ENTITY_TOO_LARGE, "Payload Too Large");
151 (414, REQUEST_URI_TOO_LARGE, "Request Uri Too Large");
153 (415, UNSUPPORTED_MEDIA_TYPE, "Unsupported Media Type");
155 (416, RANGE_NOT_SATISFIABLE, "Range Not Satisfiable");
157 (421, MISDIRECTED_REQUEST, "Misdirected Request");
159 (429, TOO_MANY_REQUESTS, "Too Many Requests");
161
162 (444, CLOSE, "CLOSE");
166
167 (494, NGINX_CODES, "NGINX_CODES");
169
170 (494, REQUEST_HEADER_TOO_LARGE, "REQUEST_HEADER_TOO_LARGE");
172
173 (495, HTTPS_CERT_ERROR, "NGX_HTTPS_CERT_ERROR");
175 (496, HTTPS_NO_CERT, "NGX_HTTPS_NO_CERT");
177
178 (497, TO_HTTPS, "TO_HTTPS");
184
185 (499, CLIENT_CLOSED_REQUEST, "CLIENT_CLOSED_REQUEST");
187
188 (500, INTERNAL_SERVER_ERROR, "INTERNAL_SERVER_ERROR");
190 (501, NOT_IMPLEMENTED, "NOT_IMPLEMENTED");
192 (502, BAD_GATEWAY, "BAD_GATEWAY");
194 (503, SERVICE_UNAVAILABLE, "SERVICE_UNAVAILABLE");
196 (504, GATEWAY_TIME_OUT, "GATEWAY_TIME_OUT");
198 (505, VERSION_NOT_SUPPORTED, "VERSION_NOT_SUPPORTED");
200 (507, INSUFFICIENT_STORAGE, "INSUFFICIENT_STORAGE");
202}