diff --git a/core/lib/src/response/status.rs b/core/lib/src/response/status.rs index e995dbf7..f3abc50c 100644 --- a/core/lib/src/response/status.rs +++ b/core/lib/src/response/status.rs @@ -33,7 +33,7 @@ use crate::request::Request; use crate::response::{self, Responder, Response}; use crate::http::Status; -/// Sets the status of the response to 201 (Created). +/// Sets the status of the response to 201 Created. /// /// Sets the `Location` header and optionally the `ETag` header in the response. /// The body of the response, which identifies the created resource, can be set @@ -179,47 +179,7 @@ impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for Created { } } -/// Sets the status of the response to 202 (Accepted). -/// -/// If a responder is supplied, the remainder of the response is delegated to -/// it. If there is no responder, the body of the response will be empty. -/// -/// # Examples -/// -/// A 202 Accepted response without a body: -/// -/// ```rust -/// use rocket::response::status; -/// -/// # #[allow(unused_variables)] -/// let response = status::Accepted::<()>(None); -/// ``` -/// -/// A 202 Accepted response _with_ a body: -/// -/// ```rust -/// use rocket::response::status; -/// -/// # #[allow(unused_variables)] -/// let response = status::Accepted(Some("processing")); -/// ``` -#[derive(Debug, Clone, PartialEq)] -pub struct Accepted(pub Option); - -/// Sets the status code of the response to 202 Accepted. If the responder is -/// `Some`, it is used to finalize the response. -impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for Accepted { - fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> { - let mut build = Response::build(); - if let Some(responder) = self.0 { - build.merge(responder.respond_to(req)?); - } - - build.status(Status::Accepted).ok() - } -} - -/// Sets the status of the response to 204 (No Content). +/// Sets the status of the response to 204 No Content. /// /// The response body will be empty. /// @@ -228,10 +188,13 @@ impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for Accepted { /// A 204 No Content response: /// /// ```rust +/// # use rocket::get; /// use rocket::response::status; /// -/// # #[allow(unused_variables)] -/// let response = status::NoContent; +/// #[get("/")] +/// fn foo() -> status::NoContent { +/// status::NoContent +/// } /// ``` #[derive(Debug, Clone, PartialEq)] pub struct NoContent; @@ -243,192 +206,9 @@ impl<'r> Responder<'r, 'static> for NoContent { } } -/// Sets the status of the response to 400 (Bad Request). +/// Creates a response with a status code and underlying responder. /// -/// If a responder is supplied, the remainder of the response is delegated to -/// it. If there is no responder, the body of the response will be empty. -/// -/// # Examples -/// -/// A 400 Bad Request response without a body: -/// -/// ```rust -/// use rocket::response::status; -/// -/// # #[allow(unused_variables)] -/// let response = status::BadRequest::<()>(None); -/// ``` -/// -/// A 400 Bad Request response _with_ a body: -/// -/// ```rust -/// use rocket::response::status; -/// -/// # #[allow(unused_variables)] -/// let response = status::BadRequest(Some("error message")); -/// ``` -#[derive(Debug, Clone, PartialEq)] -pub struct BadRequest(pub Option); - -/// Sets the status code of the response to 400 Bad Request. If the responder is -/// `Some`, it is used to finalize the response. -impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for BadRequest { - fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> { - let mut build = Response::build(); - if let Some(responder) = self.0 { - build.merge(responder.respond_to(req)?); - } - - build.status(Status::BadRequest).ok() - } -} - -/// Sets the status of the response to 401 (Unauthorized). -/// -/// If a responder is supplied, the remainder of the response is delegated to -/// it. If there is no responder, the body of the response will be empty. -/// -/// # Examples -/// -/// A 401 Unauthorized response without a body: -/// -/// ```rust -/// use rocket::response::status; -/// -/// # #[allow(unused_variables)] -/// let response = status::Unauthorized::<()>(None); -/// ``` -/// -/// A 401 Unauthorized response _with_ a body: -/// -/// ```rust -/// use rocket::response::status; -/// -/// # #[allow(unused_variables)] -/// let response = status::Unauthorized(Some("error message")); -/// ``` -#[derive(Debug, Clone, PartialEq)] -pub struct Unauthorized(pub Option); - -/// Sets the status code of the response to 401 Unauthorized. If the responder is -/// `Some`, it is used to finalize the response. -impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for Unauthorized { - fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> { - let mut build = Response::build(); - if let Some(responder) = self.0 { - build.merge(responder.respond_to(req)?); - } - - build.status(Status::Unauthorized).ok() - } -} - -/// Sets the status of the response to 403 (Forbidden). -/// -/// If a responder is supplied, the remainder of the response is delegated to -/// it. If there is no responder, the body of the response will be empty. -/// -/// # Examples -/// -/// A 403 Forbidden response without a body: -/// -/// ```rust -/// use rocket::response::status; -/// -/// # #[allow(unused_variables)] -/// let response = status::Forbidden::<()>(None); -/// ``` -/// -/// A 403 Forbidden response _with_ a body: -/// -/// ```rust -/// use rocket::response::status; -/// -/// # #[allow(unused_variables)] -/// let response = status::Forbidden(Some("error message")); -/// ``` -#[derive(Debug, Clone, PartialEq)] -pub struct Forbidden(pub Option); - -/// Sets the status code of the response to 403 Forbidden. If the responder is -/// `Some`, it is used to finalize the response. -impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for Forbidden { - fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> { - let mut build = Response::build(); - if let Some(responder) = self.0 { - build.merge(responder.respond_to(req)?); - } - - build.status(Status::Forbidden).ok() - } -} - -/// Sets the status of the response to 404 (Not Found). -/// -/// The remainder of the response is delegated to the wrapped `Responder`. -/// -/// # Example -/// -/// ```rust -/// use rocket::response::status; -/// -/// # #[allow(unused_variables)] -/// let response = status::NotFound("Sorry, I couldn't find it!"); -/// ``` -#[derive(Debug, Clone, PartialEq)] -pub struct NotFound(pub R); - -/// Sets the status code of the response to 404 Not Found. -impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for NotFound { - fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> { - Response::build_from(self.0.respond_to(req)?) - .status(Status::NotFound) - .ok() - } -} - - -/// Sets the status of the response to 409 (Conflict). -/// -/// If a responder is supplied, the remainder of the response is delegated to -/// it. If there is no responder, the body of the response will be empty. -/// -/// # Examples -/// -/// A 409 Conflict response without a body: -/// -/// ```rust -/// use rocket::response::status; -/// -/// # #[allow(unused_variables)] -/// let response = status::Conflict::<()>(None); -/// ``` -/// -/// A 409 Conflict response _with_ a body: -/// -/// ```rust -/// use rocket::response::status; -/// -/// # #[allow(unused_variables)] -/// let response = status::Conflict(Some("error message")); -/// ``` -#[derive(Debug, Clone, PartialEq)] -pub struct Conflict(pub Option); - -/// Sets the status code of the response to 409 Conflict. If the responder is -/// `Some`, it is used to finalize the response. -impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for Conflict { - fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> { - let mut build = Response::build(); - if let Some(responder) = self.0 { - build.merge(responder.respond_to(req)?); - } - - build.status(Status::Conflict).ok() - } -} - -/// Creates a response with the given status code and underlying responder. +/// Note that this is equivalent to `(Status, R)`. /// /// # Example /// @@ -437,11 +217,16 @@ impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for Conflict { /// use rocket::response::status; /// use rocket::http::Status; /// -/// # #[allow(unused_variables)] /// #[get("/")] /// fn handler() -> status::Custom<&'static str> { /// status::Custom(Status::ImATeapot, "Hi!") /// } +/// +/// // This is equivalent to the above. +/// #[get("/")] +/// fn handler2() -> (Status, &'static str) { +/// (Status::ImATeapot, "Hi!") +/// } /// ``` #[derive(Debug, Clone, PartialEq)] pub struct Custom(pub Status, pub R); @@ -449,6 +234,7 @@ pub struct Custom(pub Status, pub R); /// Sets the status code of the response and then delegates the remainder of the /// response to the wrapped responder. impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for Custom { + #[inline] fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> { Response::build_from(self.1.respond_to(req)?) .status(self.0) @@ -463,5 +249,59 @@ impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for (Status, R) { } } +macro_rules! status_response { + ($T:ident $kind:expr) => { + /// Sets the status of the response to + #[doc = concat!($kind, concat!(" ([`Status::", stringify!($T), "`])."))] + /// + /// The remainder of the response is delegated to `self.0`. + /// # Examples + /// + /// A + #[doc = $kind] + /// response without a body: + /// + /// ```rust + /// # use rocket::get; + /// use rocket::response::status; + /// + /// #[get("/")] + #[doc = concat!("fn handler() -> status::", stringify!($T), "<()> {")] + #[doc = concat!(" status::", stringify!($T), "(())")] + /// } + /// ``` + /// + /// A + #[doc = $kind] + /// response _with_ a body: + /// + /// ```rust + /// # use rocket::get; + /// use rocket::response::status; + /// + /// #[get("/")] + #[doc = concat!("fn handler() -> status::", stringify!($T), "<&'static str> {")] + #[doc = concat!(" status::", stringify!($T), "(\"body\")")] + /// } + /// ``` + #[derive(Debug, Clone, PartialEq)] + pub struct $T(pub R); + + impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for $T { + #[inline(always)] + fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> { + Custom(Status::$T, self.0).respond_to(req) + } + } + } +} + +status_response!(Accepted "202 Accepted"); +status_response!(BadRequest "400 Bad Request"); +status_response!(Unauthorized "401 Unauthorized"); +status_response!(Forbidden "403 Forbidden"); +status_response!(NotFound "404 NotFound"); +status_response!(Conflict "409 Conflict"); + // The following are unimplemented. // 206 Partial Content (variant), 203 Non-Authoritative Information (headers). diff --git a/site/guide/5-responses.md b/site/guide/5-responses.md index 8fbe9e8d..c5bf662b 100644 --- a/site/guide/5-responses.md +++ b/site/guide/5-responses.md @@ -43,7 +43,7 @@ use rocket::response::status; #[post("/")] fn new(id: usize) -> status::Accepted { - status::Accepted(Some(format!("id: '{}'", id))) + status::Accepted(format!("id: '{}'", id)) } ```