ngx/http/
status.rs

1use core::fmt;
2
3use crate::core::Status;
4use crate::ffi::*;
5
6/// Represents an HTTP status code.
7#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
8pub struct HTTPStatus(pub ngx_uint_t);
9
10/// A possible error value when converting a `HTTPStatus` from a `u16` or `&str`
11///
12/// This error indicates that the supplied input was not a valid number, was less
13/// than 100, or was greater than 599.
14#[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
31#[cfg(feature = "std")]
32impl std::error::Error for InvalidHTTPStatusCode {}
33
34impl From<HTTPStatus> for Status {
35    fn from(val: HTTPStatus) -> Self {
36        Status(val.0 as ngx_int_t)
37    }
38}
39
40impl From<HTTPStatus> for ngx_uint_t {
41    fn from(val: HTTPStatus) -> Self {
42        val.0
43    }
44}
45
46impl fmt::Debug for HTTPStatus {
47    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
48        fmt::Debug::fmt(&self.0, f)
49    }
50}
51
52impl HTTPStatus {
53    /// Convets a u16 to a status code.
54    #[inline]
55    pub fn from_u16(src: u16) -> Result<HTTPStatus, InvalidHTTPStatusCode> {
56        if !(100..600).contains(&src) {
57            return Err(InvalidHTTPStatusCode::new());
58        }
59
60        Ok(HTTPStatus(src.into()))
61    }
62
63    /// Converts a &[u8] to a status code.
64    pub fn from_bytes(src: &[u8]) -> Result<HTTPStatus, InvalidHTTPStatusCode> {
65        if src.len() != 3 {
66            return Err(InvalidHTTPStatusCode::new());
67        }
68
69        let a = src[0].wrapping_sub(b'0') as u16;
70        let b = src[1].wrapping_sub(b'0') as u16;
71        let c = src[2].wrapping_sub(b'0') as u16;
72
73        if a == 0 || a > 5 || b > 9 || c > 9 {
74            return Err(InvalidHTTPStatusCode::new());
75        }
76
77        let status = (a * 100) + (b * 10) + c;
78        Ok(HTTPStatus(status.into()))
79    }
80}
81
82macro_rules! http_status_codes {
83    (
84        $(
85            $(#[$docs:meta])*
86            ($num:expr, $konst:ident, $phrase:expr);
87        )+
88    ) => {
89        impl HTTPStatus {
90        $(
91            $(#[$docs])*
92            pub const $konst: HTTPStatus = HTTPStatus($num);
93        )+
94
95        }
96    }
97}
98
99http_status_codes! {
100    /// 100 CONTINUE
101    (100, CONTINUE, "Continue");
102    /// 101 SWITCHING_PROTOCOLS
103    (101, SWITCHING_PROTOCOLS, "Switching Protocols");
104    /// 102 PROCESSING
105    (102, PROCESSING, "Processing");
106    /// 200 OK
107    (200, OK, "OK");
108    /// 201 Created
109    (201, CREATED, "Created");
110    /// 202 Accepted
111    (202, ACCEPTED, "Accepted");
112    /// 204 No Content
113    (204, NO_CONTENT, "No Content");
114    /// 206 Partial Content
115    (206, PARTIAL_CONTENT, "Partial Content");
116
117    /// 300 SPECIAL_RESPONSE
118    (300, SPECIAL_RESPONSE, "SPECIAL_RESPONSE");
119    /// 301 Moved Permanently
120    (301, MOVED_PERMANENTLY, "Moved Permanently");
121    /// 302 Moved Temporarily
122    (302, MOVED_TEMPORARILY, "Moved Temporarily");
123    /// 303 See Other
124    (303, SEE_OTHER, "See Other");
125    /// 304 Not Modified
126    (304, NOT_MODIFIED, "Not Modified");
127    /// 307 Temporary Redirect
128    (307, TEMPORARY_REDIRECT, "Temporary Redirect");
129    /// 308 Permanent Redirect
130    (308, PERMANENT_REDIRECT, "Permanent Redirect");
131
132    /// 400 Bad Request
133    (400, BAD_REQUEST, "Bad Request");
134    /// 401 Unauthorized
135    (401, UNAUTHORIZED, "Unauthorized");
136    /// 403 Forbidden
137    (403, FORBIDDEN, "Forbidden");
138    /// 404 Not Found
139    (404, NOT_FOUND, "Not Found");
140    /// 405 Method Not Allowed
141    (405, NOT_ALLOWED, "Method Not Allowed");
142    /// 408 Request Time Out
143    (408, REQUEST_TIME_OUT, "Request Time Out");
144    /// 409 Conflict
145    (409, CONFLICT, "Conflict");
146    /// 411 Length Required
147    (411, LENGTH_REQUIRED, "Length Required");
148    /// 412 Precondition Failed
149    (412, PRECONDITION_FAILED, "Precondition Failed");
150    /// 413 Payload Too Large
151    (413, REQUEST_ENTITY_TOO_LARGE, "Payload Too Large");
152    /// 414 Request Uri Too Large
153    (414, REQUEST_URI_TOO_LARGE, "Request Uri Too Large");
154    /// 415 Unsupported Media Type
155    (415, UNSUPPORTED_MEDIA_TYPE, "Unsupported Media Type");
156    /// 416 Range Not Satisfiable
157    (416, RANGE_NOT_SATISFIABLE, "Range Not Satisfiable");
158    /// 421 Misdirected Request
159    (421, MISDIRECTED_REQUEST, "Misdirected Request");
160    /// 429 Too Many Requests
161    (429, TOO_MANY_REQUESTS, "Too Many Requests");
162
163    // /* Our own HTTP codes */
164    // /* The special code to close connection without any response */
165    /// 444 CLOSE
166    (444, CLOSE, "CLOSE");
167
168    /// 494 NGINX_CODES
169    (494, NGINX_CODES, "NGINX_CODES");
170
171    /// 494 REQUEST_HEADER_TOO_LARGE
172    (494, REQUEST_HEADER_TOO_LARGE, "REQUEST_HEADER_TOO_LARGE");
173
174    /// 495 NGX_HTTPS_CERT_ERROR
175    (495, HTTPS_CERT_ERROR, "NGX_HTTPS_CERT_ERROR");
176    /// 496 NGX_HTTPS_NO_CERT
177    (496, HTTPS_NO_CERT, "NGX_HTTPS_NO_CERT");
178
179    // /*
180    //  * We use the special code for the plain HTTP requests that are sent to
181    //  * HTTPS port to distinguish it from 4XX in an error page redirection
182    //  */
183    /// 497 TO_HTTPS
184    (497, TO_HTTPS, "TO_HTTPS");
185
186    /// 499 CLIENT_CLOSED_REQUEST
187    (499, CLIENT_CLOSED_REQUEST, "CLIENT_CLOSED_REQUEST");
188
189    /// 500 INTERNAL_SERVER_ERROR
190    (500, INTERNAL_SERVER_ERROR, "INTERNAL_SERVER_ERROR");
191    /// 501 NOT_IMPLEMENTED
192    (501, NOT_IMPLEMENTED, "NOT_IMPLEMENTED");
193    /// 502 BAD_GATEWAY
194    (502, BAD_GATEWAY, "BAD_GATEWAY");
195    /// 503 SERVICE_UNAVAILABLE
196    (503, SERVICE_UNAVAILABLE, "SERVICE_UNAVAILABLE");
197    /// 504 GATEWAY_TIME_OUT
198    (504, GATEWAY_TIME_OUT, "GATEWAY_TIME_OUT");
199    /// 505 VERSION_NOT_SUPPORTED
200    (505, VERSION_NOT_SUPPORTED, "VERSION_NOT_SUPPORTED");
201    /// 507 INSUFFICIENT_STORAGE
202    (507, INSUFFICIENT_STORAGE, "INSUFFICIENT_STORAGE");
203}