diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 145fa13a..b7410b5e 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -77,6 +77,7 @@ actix-web-codegen = { version = "0.5.0-rc.2", optional = true } ahash = "0.7" bytes = "1" +bytestring = "1" cfg-if = "1" cookie = { version = "0.16", features = ["percent-encode"], optional = true } derive_more = "0.99.5" diff --git a/actix-web/src/response/responder.rs b/actix-web/src/response/responder.rs index c88faec8..da809198 100644 --- a/actix-web/src/response/responder.rs +++ b/actix-web/src/response/responder.rs @@ -7,14 +7,35 @@ use actix_http::{ }; use bytes::{Bytes, BytesMut}; -use crate::{Error, HttpRequest, HttpResponse}; - use super::CustomizeResponder; +use crate::{Error, HttpRequest, HttpResponse}; /// Trait implemented by types that can be converted to an HTTP response. /// -/// Any types that implement this trait can be used in the return type of a handler. -// # TODO: more about implementation notes and foreign impls +/// Any types that implement this trait can be used in the return type of a handler. Since handlers +/// will only have one return type, it is idiomatic to use opaque return types `-> impl Responder`. +/// +/// # Implementations +/// It is often not required to implement `Responder` for your own types due to a broad base of +/// built-in implementations: +/// - `HttpResponse` and `HttpResponseBuilder` +/// - `Option` where `R: Responder` +/// - `Result` where `R: Responder` and [`E: ResponseError`](crate::ResponseError) +/// - `(R, StatusCode) where `R: Responder` +/// - `&'static str`, `String`, `&'_ String`, `Cow<'_, str>`, [`ByteString`](bytestring::ByteString) +/// - `&'static [u8]`, `Vec`, `Bytes`, `BytesMut` +/// - [`Json`](crate::web::Json) and [`Form`](crate::web::Form) where `T: Serialize` +/// - [`Either`](crate::web::Either) where `L: Serialize` and `R: Serialize` +/// - [`CustomizeResponder`] +/// - [`actix_files::NamedFile`](https://docs.rs/actix-files/latest/actix_files/struct.NamedFile.html) +/// - [Experimental responders from `actix-web-lab`](https://docs.rs/actix-web-lab/latest/actix_web_lab/respond/index.html) +/// - Third party integrations may also have implemented `Responder` where appropriate. For example, +/// HTML templating engines. +/// +/// # Customizing Responder Output +/// Calling [`.customize()`](Responder::customize) on any responder type will wrap it in a +/// [`CustomizeResponder`] capable of overriding various parts of the response such as the status +/// code and header map. pub trait Responder { type Body: MessageBody + 'static; @@ -23,7 +44,7 @@ pub trait Responder { /// Wraps responder to allow alteration of its response. /// - /// See [`CustomizeResponder`] docs for its capabilities. + /// See [`CustomizeResponder`] docs for more details on its capabilities. /// /// # Examples /// ``` @@ -84,11 +105,8 @@ impl Responder for actix_http::ResponseBuilder { } } -impl Responder for Option -where - T: Responder, -{ - type Body = EitherBody; +impl Responder for Option { + type Body = EitherBody; fn respond_to(self, req: &HttpRequest) -> HttpResponse { match self { @@ -98,12 +116,12 @@ where } } -impl Responder for Result +impl Responder for Result where - T: Responder, + R: Responder, E: Into, { - type Body = EitherBody; + type Body = EitherBody; fn respond_to(self, req: &HttpRequest) -> HttpResponse { match self { @@ -113,8 +131,8 @@ where } } -impl Responder for (T, StatusCode) { - type Body = T::Body; +impl Responder for (R, StatusCode) { + type Body = R::Body; fn respond_to(self, req: &HttpRequest) -> HttpResponse { let mut res = self.0.respond_to(req); @@ -147,6 +165,7 @@ impl_responder_by_forward_into_base_response!(BytesMut); impl_responder_by_forward_into_base_response!(&'static str); impl_responder_by_forward_into_base_response!(String); +impl_responder_by_forward_into_base_response!(bytestring::ByteString); macro_rules! impl_into_string_responder { ($res:ty) => {