ngx/http/
status.rs

1use core::{error, 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
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    /// Convets a u16 to a status code.
53    #[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    /// Converts a &[u8] to a status code.
63    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
100    (100, CONTINUE, "Continue");
101    /// 101 SWITCHING_PROTOCOLS
102    (101, SWITCHING_PROTOCOLS, "Switching Protocols");
103    /// 102 PROCESSING
104    (102, PROCESSING, "Processing");
105    /// 200 OK
106    (200, OK, "OK");
107    /// 201 Created
108    (201, CREATED, "Created");
109    /// 202 Accepted
110    (202, ACCEPTED, "Accepted");
111    /// 204 No Content
112    (204, NO_CONTENT, "No Content");
113    /// 206 Partial Content
114    (206, PARTIAL_CONTENT, "Partial Content");
115
116    /// 300 SPECIAL_RESPONSE
117    (300, SPECIAL_RESPONSE, "SPECIAL_RESPONSE");
118    /// 301 Moved Permanently
119    (301, MOVED_PERMANENTLY, "Moved Permanently");
120    /// 302 Moved Temporarily
121    (302, MOVED_TEMPORARILY, "Moved Temporarily");
122    /// 303 See Other
123    (303, SEE_OTHER, "See Other");
124    /// 304 Not Modified
125    (304, NOT_MODIFIED, "Not Modified");
126    /// 307 Temporary Redirect
127    (307, TEMPORARY_REDIRECT, "Temporary Redirect");
128    /// 308 Permanent Redirect
129    (308, PERMANENT_REDIRECT, "Permanent Redirect");
130
131    /// 400 Bad Request
132    (400, BAD_REQUEST, "Bad Request");
133    /// 401 Unauthorized
134    (401, UNAUTHORIZED, "Unauthorized");
135    /// 403 Forbidden
136    (403, FORBIDDEN, "Forbidden");
137    /// 404 Not Found
138    (404, NOT_FOUND, "Not Found");
139    /// 405 Method Not Allowed
140    (405, NOT_ALLOWED, "Method Not Allowed");
141    /// 408 Request Time Out
142    (408, REQUEST_TIME_OUT, "Request Time Out");
143    /// 409 Conflict
144    (409, CONFLICT, "Conflict");
145    /// 411 Length Required
146    (411, LENGTH_REQUIRED, "Length Required");
147    /// 412 Precondition Failed
148    (412, PRECONDITION_FAILED, "Precondition Failed");
149    /// 413 Payload Too Large
150    (413, REQUEST_ENTITY_TOO_LARGE, "Payload Too Large");
151    /// 414 Request Uri Too Large
152    (414, REQUEST_URI_TOO_LARGE, "Request Uri Too Large");
153    /// 415 Unsupported Media Type
154    (415, UNSUPPORTED_MEDIA_TYPE, "Unsupported Media Type");
155    /// 416 Range Not Satisfiable
156    (416, RANGE_NOT_SATISFIABLE, "Range Not Satisfiable");
157    /// 421 Misdirected Request
158    (421, MISDIRECTED_REQUEST, "Misdirected Request");
159    /// 429 Too Many Requests
160    (429, TOO_MANY_REQUESTS, "Too Many Requests");
161
162    // /* Our own HTTP codes */
163    // /* The special code to close connection without any response */
164    /// 444 CLOSE
165    (444, CLOSE, "CLOSE");
166
167    /// 494 NGINX_CODES
168    (494, NGINX_CODES, "NGINX_CODES");
169
170    /// 494 REQUEST_HEADER_TOO_LARGE
171    (494, REQUEST_HEADER_TOO_LARGE, "REQUEST_HEADER_TOO_LARGE");
172
173    /// 495 NGX_HTTPS_CERT_ERROR
174    (495, HTTPS_CERT_ERROR, "NGX_HTTPS_CERT_ERROR");
175    /// 496 NGX_HTTPS_NO_CERT
176    (496, HTTPS_NO_CERT, "NGX_HTTPS_NO_CERT");
177
178    // /*
179    //  * We use the special code for the plain HTTP requests that are sent to
180    //  * HTTPS port to distinguish it from 4XX in an error page redirection
181    //  */
182    /// 497 TO_HTTPS
183    (497, TO_HTTPS, "TO_HTTPS");
184
185    /// 499 CLIENT_CLOSED_REQUEST
186    (499, CLIENT_CLOSED_REQUEST, "CLIENT_CLOSED_REQUEST");
187
188    /// 500 INTERNAL_SERVER_ERROR
189    (500, INTERNAL_SERVER_ERROR, "INTERNAL_SERVER_ERROR");
190    /// 501 NOT_IMPLEMENTED
191    (501, NOT_IMPLEMENTED, "NOT_IMPLEMENTED");
192    /// 502 BAD_GATEWAY
193    (502, BAD_GATEWAY, "BAD_GATEWAY");
194    /// 503 SERVICE_UNAVAILABLE
195    (503, SERVICE_UNAVAILABLE, "SERVICE_UNAVAILABLE");
196    /// 504 GATEWAY_TIME_OUT
197    (504, GATEWAY_TIME_OUT, "GATEWAY_TIME_OUT");
198    /// 505 VERSION_NOT_SUPPORTED
199    (505, VERSION_NOT_SUPPORTED, "VERSION_NOT_SUPPORTED");
200    /// 507 INSUFFICIENT_STORAGE
201    (507, INSUFFICIENT_STORAGE, "INSUFFICIENT_STORAGE");
202}