Skip to content

Commit

Permalink
Remove unused reason phrase in 'Status'.
Browse files Browse the repository at this point in the history
Closes #534.

Co-authored-by: YetAnotherMinion <[email protected]>
  • Loading branch information
SergioBenitez and YetAnotherMinion committed Apr 29, 2021
1 parent 336a03e commit ad8d809
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 171 deletions.
6 changes: 3 additions & 3 deletions core/codegen/src/http_codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ impl FromMeta for Status {
return Err(meta.value_span().error("status must be in range [100, 599]"));
}

Ok(Status(http::Status::raw(num as u16)))
Ok(Status(http::Status::new(num as u16)))
}
}

impl ToTokens for Status {
fn to_tokens(&self, tokens: &mut TokenStream) {
let (code, reason) = (self.0.code, self.0.reason);
tokens.extend(quote!(rocket::http::Status { code: #code, reason: #reason }));
let code = self.0.code;
tokens.extend(quote!(rocket::http::Status { code: #code }));
}
}

Expand Down
2 changes: 1 addition & 1 deletion core/codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ route_attribute!(options => Method::Options);
///
/// #[catch(default)]
/// fn default(status: Status, req: &Request) -> String {
/// format!("{} - {} ({})", status.code, status.reason, req.uri())
/// format!("{} ({})", status, req.uri())
/// }
/// ```
///
Expand Down
2 changes: 1 addition & 1 deletion core/codegen/tests/responder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ async fn responder_foo() {
.respond_to(req)
.expect("response okay");

assert_eq!(r.status(), Status::raw(105));
assert_eq!(r.status().code, 105);
assert_eq!(r.content_type(), Some(ContentType::JSON));
assert_eq!(r.body_mut().to_string().await.unwrap(), "goodbye");
}
Expand Down
274 changes: 152 additions & 122 deletions core/http/src/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,43 @@ impl StatusClass {
class_check_fn!(is_unknown, "`Unknown`.", Unknown);
}

/// Structure representing an HTTP status: an integer code and a reason phrase.
/// Structure representing an HTTP status: an integer code.
///
/// # Usage
/// A `Status` should rarely be created directly. Instead, an associated
/// constant should be used; one is declared for every status defined in the
/// HTTP standard. If a custom status code _must_ be created, note that it is
/// not possible to set a custom reason phrase.
///
/// Status classes should rarely be created directly. Instead, an associated
/// constant should be used; one is declared for every status defined
/// in the HTTP standard.
/// ```rust
/// # extern crate rocket;
/// use rocket::http::Status;
///
/// // Create a status from a known constant.
/// let ok = Status::Ok;
/// assert_eq!(ok.code, 200);
/// assert_eq!(ok.reason(), Some("OK"));
///
/// let not_found = Status::NotFound;
/// assert_eq!(not_found.code, 404);
/// assert_eq!(not_found.reason(), Some("Not Found"));
///
/// // Or from a status code: `reason()` returns the phrase when known.
/// let gone = Status::new(410);
/// assert_eq!(gone.code, 410);
/// assert_eq!(gone.reason(), Some("Gone"));
///
/// // `reason()` returns `None` when unknown.
/// let custom = Status::new(599);
/// assert_eq!(custom.code, 599);
/// assert_eq!(custom.reason(), None);
/// ```
///
/// # Responding
///
/// To set a custom `Status` on a response, use a [`response::status`]
/// responder. Alternatively, respond with `(Status, T)` where `T: Responder`, but
/// note that the response may require additional headers to be valid as
/// enforced by the types in [`response::status`].
/// responder, which enforces correct status-based responses. Alternatively,
/// respond with `(Status, T)` where `T: Responder`, but beware that the
/// response may be invalid if it requires additional headers.
///
/// ```rust
/// # extern crate rocket;
Expand All @@ -69,47 +92,10 @@ impl StatusClass {
/// ```
///
/// [`response::status`]: ../response/status/index.html
///
/// ## Example
///
/// A status of `200 OK` can be instantiated via the `Ok` constant:
///
/// ```rust
/// # extern crate rocket;
/// use rocket::http::Status;
///
/// # #[allow(unused_variables)]
/// let ok = Status::Ok;
/// ```
///
/// A status of `404 Not Found` can be instantiated via the `NotFound` constant:
///
/// ```rust
/// # extern crate rocket;
/// use rocket::http::Status;
///
/// # #[allow(unused_variables)]
/// let not_found = Status::NotFound;
/// ```
///
/// The code and phrase can be retrieved directly:
///
/// ```rust
/// # extern crate rocket;
/// use rocket::http::Status;
///
/// let not_found = Status::NotFound;
///
/// assert_eq!(not_found.code, 404);
/// assert_eq!(not_found.reason, "Not Found");
/// assert_eq!(not_found.to_string(), "404 Not Found".to_string());
/// ```
#[derive(Debug, Clone, Copy)]
pub struct Status {
/// The HTTP status code associated with this status.
pub code: u16,
/// The HTTP reason phrase associated with this status.
pub reason: &'static str
}

impl Default for Status {
Expand All @@ -123,12 +109,66 @@ macro_rules! ctrs {
$(
#[doc="[`Status`] with code <b>"]
#[doc=$code_str]
#[doc="</b> and reason <i>"]
#[doc=$reason]
#[doc="</i>."]
#[doc="</b>."]
#[allow(non_upper_case_globals)]
pub const $name: Status = Status { code: $code, reason: $reason };
)+
pub const $name: Status = Status { code: $code };
)+

/// Creates a new `Status` with `code`. This should be used _only_ to
/// construct non-standard HTTP statuses. Use an associated constant for
/// standard statuses.
///
/// # Example
///
/// Create a custom `299` status:
///
/// ```rust
/// # extern crate rocket;
/// use rocket::http::Status;
///
/// let custom = Status::new(299);
/// assert_eq!(custom.code, 299);
/// ```
pub const fn new(code: u16) -> Status {
Status { code }
}

/// Returns the class of a given status.
///
/// # Example
///
/// ```rust
/// # extern crate rocket;
/// use rocket::http::{Status, StatusClass};
///
/// let processing = Status::Processing;
/// assert_eq!(processing.class(), StatusClass::Informational);
///
/// let ok = Status::Ok;
/// assert_eq!(ok.class(), StatusClass::Success);
///
/// let see_other = Status::SeeOther;
/// assert_eq!(see_other.class(), StatusClass::Redirection);
///
/// let not_found = Status::NotFound;
/// assert_eq!(not_found.class(), StatusClass::ClientError);
///
/// let internal_error = Status::InternalServerError;
/// assert_eq!(internal_error.class(), StatusClass::ServerError);
///
/// let custom = Status::new(600);
/// assert_eq!(custom.class(), StatusClass::Unknown);
/// ```
pub const fn class(self) -> StatusClass {
match self.code / 100 {
1 => StatusClass::Informational,
2 => StatusClass::Success,
3 => StatusClass::Redirection,
4 => StatusClass::ClientError,
5 => StatusClass::ServerError,
_ => StatusClass::Unknown
}
}

/// Returns a Status given a standard status code `code`. If `code` is
/// not a known status code, `None` is returned.
Expand All @@ -151,88 +191,78 @@ macro_rules! ctrs {
/// # extern crate rocket;
/// use rocket::http::Status;
///
/// let not_found = Status::from_code(600);
/// assert!(not_found.is_none());
/// let unknown = Status::from_code(600);
/// assert!(unknown.is_none());
/// ```
pub fn from_code(code: u16) -> Option<Status> {
pub const fn from_code(code: u16) -> Option<Status> {
match code {
$($code => Some(Status::$name),)+
_ => None
}
}
};
}

impl Status {
/// Creates a new `Status` with `code` and `reason`. This should be used _only_
/// to construct non-standard HTTP statuses. Use an associated constant for
/// standard statuses.
///
/// # Example
///
/// Create a custom `299 Somewhat Successful` status:
///
/// ```rust
/// # extern crate rocket;
/// use rocket::http::Status;
///
/// let custom = Status::new(299, "Somewhat Successful");
/// assert_eq!(custom.to_string(), "299 Somewhat Successful".to_string());
/// ```
#[inline(always)]
pub const fn new(code: u16, reason: &'static str) -> Status {
Status { code, reason }
}

/// Returns the class of a given status.
///
/// # Example
///
/// ```rust
/// # extern crate rocket;
/// use rocket::http::{Status, StatusClass};
///
/// let processing = Status::Processing;
/// assert_eq!(processing.class(), StatusClass::Informational);
///
/// let ok = Status::Ok;
/// assert_eq!(ok.class(), StatusClass::Success);
///
/// let see_other = Status::SeeOther;
/// assert_eq!(see_other.class(), StatusClass::Redirection);
///
/// let not_found = Status::NotFound;
/// assert_eq!(not_found.class(), StatusClass::ClientError);
///
/// let internal_error = Status::InternalServerError;
/// assert_eq!(internal_error.class(), StatusClass::ServerError);
///
/// let custom = Status::new(600, "Bizarre");
/// assert_eq!(custom.class(), StatusClass::Unknown);
/// ```
pub fn class(self) -> StatusClass {
match self.code / 100 {
1 => StatusClass::Informational,
2 => StatusClass::Success,
3 => StatusClass::Redirection,
4 => StatusClass::ClientError,
5 => StatusClass::ServerError,
_ => StatusClass::Unknown
/// Returns the canonical reason phrase if `self` corresponds to a
/// canonical, known status code. Otherwise, returns `None`.
///
/// # Example
///
/// Reason phrase from a known `code`:
///
/// ```rust
/// # extern crate rocket;
/// use rocket::http::Status;
///
/// assert_eq!(Status::Created.reason(), Some("Created"));
/// assert_eq!(Status::new(200).reason(), Some("OK"));
/// ```
///
/// Absent phrase from an unknown `code`:
///
/// ```rust
/// # extern crate rocket;
/// use rocket::http::Status;
///
/// assert_eq!(Status::new(499).reason(), None);
/// ```
pub const fn reason(&self) -> Option<&'static str> {
match self.code {
$($code => Some($reason),)+
_ => None
}
}
}

/// Returns a status from a given status code. If the status code is a
/// standard code, then the reason phrase is populated accordingly.
/// Otherwise the reason phrase is set to "<unknown code>".
#[inline]
#[doc(hidden)]
pub fn raw(code: u16) -> Status {
match Status::from_code(code) {
Some(status) => status,
None => Status::new(code, "<unknown code>")
/// Returns the canonical reason phrase if `self` corresponds to a
/// canonical, known status code, or an unspecified but relevant reason
/// phrase otherwise.
///
/// # Example
///
/// ```rust
/// # extern crate rocket;
/// use rocket::http::Status;
///
/// assert_eq!(Status::NotFound.reason_lossy(), "Not Found");
/// assert_eq!(Status::new(100).reason_lossy(), "Continue");
/// assert!(!Status::new(699).reason_lossy().is_empty());
/// ```
pub const fn reason_lossy(&self) -> &'static str {
if let Some(lossless) = self.reason() {
return lossless;
}

match self.class() {
StatusClass::Informational => "Informational",
StatusClass::Success => "Success",
StatusClass::Redirection => "Redirection",
StatusClass::ClientError => "Client Error",
StatusClass::ServerError => "Server Error",
StatusClass::Unknown => "Unknown"
}
}
}
};
}

impl Status {
ctrs! {
100, "100", Continue => "Continue",
101, "101", SwitchingProtocols => "Switching Protocols",
Expand Down Expand Up @@ -300,7 +330,7 @@ impl Status {
impl fmt::Display for Status {
#[inline(always)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} {}", self.code, self.reason)
write!(f, "{} {}", self.code, self.reason_lossy())
}
}

Expand Down
Loading

0 comments on commit ad8d809

Please sign in to comment.