mirror of https://github.com/rwf2/Rocket.git
Use 'AsyncSeek' for sized bodies in 'Response's.
In order to avoid making 'ResponseBuilder::sized_body' an asynchronous function, the seeking is deferred until finalization. 'finalize()' is replaced with '.await', and 'ResponseBuilder::ok()' is an 'async fn'.
This commit is contained in:
parent
dcd4068ca0
commit
c9d0af09d6
|
@ -28,5 +28,5 @@ version_check = "0.9.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rocket = { version = "0.5.0-dev", path = "../lib" }
|
rocket = { version = "0.5.0-dev", path = "../lib" }
|
||||||
tokio = { version = "0.2.0", features = ["io-util"] }
|
tokio = { version = "0.2.9", features = ["io-util"] }
|
||||||
compiletest_rs = { version = "0.3", features = ["stable"] }
|
compiletest_rs = { version = "0.3", features = ["stable"] }
|
||||||
|
|
|
@ -103,6 +103,7 @@ pub fn _catch(args: TokenStream, input: TokenStream) -> Result<TokenStream> {
|
||||||
.status(#status)
|
.status(#status)
|
||||||
.merge(__response)
|
.merge(__response)
|
||||||
.ok()
|
.ok()
|
||||||
|
.await
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ time = "0.2.11"
|
||||||
indexmap = "1.0"
|
indexmap = "1.0"
|
||||||
state = "0.4"
|
state = "0.4"
|
||||||
tokio-rustls = { version = "0.12.0", optional = true }
|
tokio-rustls = { version = "0.12.0", optional = true }
|
||||||
tokio = { version = "0.2.0", features = ["sync", "tcp", "time"] }
|
tokio = { version = "0.2.9", features = ["sync", "tcp", "time"] }
|
||||||
cookie = { version = "0.14.0", features = ["percent-encode"] }
|
cookie = { version = "0.14.0", features = ["percent-encode"] }
|
||||||
pear = "0.1"
|
pear = "0.1"
|
||||||
unicode-xid = "0.2"
|
unicode-xid = "0.2"
|
||||||
|
|
|
@ -159,7 +159,9 @@ impl PartialEq for AcceptParams {
|
||||||
/// use rocket::response::Response;
|
/// use rocket::response::Response;
|
||||||
///
|
///
|
||||||
/// # #[allow(unused_variables)]
|
/// # #[allow(unused_variables)]
|
||||||
/// let response = Response::build().header(Accept::JSON).finalize();
|
/// # rocket::async_test(async {
|
||||||
|
/// let response = Response::build().header(Accept::JSON).await;
|
||||||
|
/// # })
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Accept(pub(crate) AcceptParams);
|
pub struct Accept(pub(crate) AcceptParams);
|
||||||
|
|
|
@ -39,7 +39,9 @@ use crate::ext::IntoCollection;
|
||||||
/// use rocket::response::Response;
|
/// use rocket::response::Response;
|
||||||
///
|
///
|
||||||
/// # #[allow(unused_variables)]
|
/// # #[allow(unused_variables)]
|
||||||
/// let response = Response::build().header(ContentType::HTML).finalize();
|
/// # rocket::async_test(async {
|
||||||
|
/// let response = Response::build().header(ContentType::HTML).await;
|
||||||
|
/// # })
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||||
pub struct ContentType(pub MediaType);
|
pub struct ContentType(pub MediaType);
|
||||||
|
|
|
@ -28,7 +28,7 @@ ctrl_c_shutdown = ["tokio/signal"]
|
||||||
rocket_codegen = { version = "0.5.0-dev", path = "../codegen" }
|
rocket_codegen = { version = "0.5.0-dev", path = "../codegen" }
|
||||||
rocket_http = { version = "0.5.0-dev", path = "../http" }
|
rocket_http = { version = "0.5.0-dev", path = "../http" }
|
||||||
futures-util = "0.3.0"
|
futures-util = "0.3.0"
|
||||||
tokio = { version = "0.2.0", features = ["fs", "io-std", "io-util", "rt-threaded", "sync"] }
|
tokio = { version = "0.2.9", features = ["fs", "io-std", "io-util", "rt-threaded", "sync"] }
|
||||||
yansi = "0.5"
|
yansi = "0.5"
|
||||||
log = { version = "0.4", features = ["std"] }
|
log = { version = "0.4", features = ["std"] }
|
||||||
toml = "0.4.7"
|
toml = "0.4.7"
|
||||||
|
@ -47,4 +47,4 @@ version_check = "0.9.1"
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
# TODO: Find a way to not depend on this.
|
# TODO: Find a way to not depend on this.
|
||||||
lazy_static = "1.0"
|
lazy_static = "1.0"
|
||||||
tokio = { version = "0.2.0", features = ["macros"] }
|
tokio = { version = "0.2.9", features = ["macros"] }
|
||||||
|
|
|
@ -54,6 +54,7 @@ impl<'r, R: Responder<'r> + Send + 'r> Responder<'r> for Content<R> {
|
||||||
.merge(self.1.respond_to(req).await?)
|
.merge(self.1.respond_to(req).await?)
|
||||||
.header(self.0)
|
.header(self.0)
|
||||||
.ok()
|
.ok()
|
||||||
|
.await
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ impl<'r, E: std::fmt::Debug + Send + 'r> Responder<'r> for Debug<E> {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
warn_!("Debug: {:?}", Paint::default(self.0));
|
warn_!("Debug: {:?}", Paint::default(self.0));
|
||||||
warn_!("Debug always responds with {}.", Status::InternalServerError);
|
warn_!("Debug always responds with {}.", Status::InternalServerError);
|
||||||
Response::build().status(Status::InternalServerError).ok()
|
Response::build().status(Status::InternalServerError).ok().await
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,6 +155,7 @@ impl<'r> Responder<'r> for Redirect {
|
||||||
.status(self.0)
|
.status(self.0)
|
||||||
.raw_header("Location", uri.to_string())
|
.raw_header("Location", uri.to_string())
|
||||||
.ok()
|
.ok()
|
||||||
|
.await
|
||||||
} else {
|
} else {
|
||||||
error!("Invalid URI used for redirect.");
|
error!("Invalid URI used for redirect.");
|
||||||
Err(Status::InternalServerError)
|
Err(Status::InternalServerError)
|
||||||
|
|
|
@ -163,6 +163,7 @@ use crate::request::Request;
|
||||||
/// .raw_header("X-Person-Age", self.age.to_string())
|
/// .raw_header("X-Person-Age", self.age.to_string())
|
||||||
/// .header(ContentType::new("application", "x-person"))
|
/// .header(ContentType::new("application", "x-person"))
|
||||||
/// .ok()
|
/// .ok()
|
||||||
|
/// .await
|
||||||
/// })
|
/// })
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
|
@ -195,6 +196,7 @@ impl<'r> Responder<'r> for &'r str {
|
||||||
.header(ContentType::Plain)
|
.header(ContentType::Plain)
|
||||||
.sized_body(Cursor::new(self))
|
.sized_body(Cursor::new(self))
|
||||||
.ok()
|
.ok()
|
||||||
|
.await
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -208,6 +210,7 @@ impl Responder<'_> for String {
|
||||||
.header(ContentType::Plain)
|
.header(ContentType::Plain)
|
||||||
.sized_body(Cursor::new(self))
|
.sized_body(Cursor::new(self))
|
||||||
.ok()
|
.ok()
|
||||||
|
.await
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -221,6 +224,7 @@ impl<'r> Responder<'r> for &'r [u8] {
|
||||||
.header(ContentType::Binary)
|
.header(ContentType::Binary)
|
||||||
.sized_body(Cursor::new(self))
|
.sized_body(Cursor::new(self))
|
||||||
.ok()
|
.ok()
|
||||||
|
.await
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -234,6 +238,7 @@ impl Responder<'_> for Vec<u8> {
|
||||||
.header(ContentType::Binary)
|
.header(ContentType::Binary)
|
||||||
.sized_body(Cursor::new(self))
|
.sized_body(Cursor::new(self))
|
||||||
.ok()
|
.ok()
|
||||||
|
.await
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -246,8 +251,8 @@ impl Responder<'_> for File {
|
||||||
let metadata = file.metadata().await;
|
let metadata = file.metadata().await;
|
||||||
let stream = BufReader::new(file);
|
let stream = BufReader::new(file);
|
||||||
match metadata {
|
match metadata {
|
||||||
Ok(md) => Response::build().raw_body(Body::Sized(stream, md.len())).ok(),
|
Ok(md) => Response::build().raw_body(Body::Sized(stream, md.len())).ok().await,
|
||||||
Err(_) => Response::build().streamed_body(stream).ok()
|
Err(_) => Response::build().streamed_body(stream).ok().await
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -307,10 +312,10 @@ impl<'r> Responder<'r> for Status {
|
||||||
match self.class() {
|
match self.class() {
|
||||||
StatusClass::ClientError | StatusClass::ServerError => Err(self),
|
StatusClass::ClientError | StatusClass::ServerError => Err(self),
|
||||||
StatusClass::Success if self.code < 206 => {
|
StatusClass::Success if self.code < 206 => {
|
||||||
Response::build().status(self).ok()
|
Response::build().status(self).ok().await
|
||||||
}
|
}
|
||||||
StatusClass::Informational if self.code == 100 => {
|
StatusClass::Informational if self.code == 100 => {
|
||||||
Response::build().status(self).ok()
|
Response::build().status(self).ok().await
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
error_!("Invalid status used as responder: {}.", self);
|
error_!("Invalid status used as responder: {}.", self);
|
||||||
|
|
|
@ -2,8 +2,9 @@ use std::{io, fmt, str};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
use tokio::io::{AsyncRead, AsyncReadExt};
|
use tokio::io::{AsyncRead, AsyncReadExt, AsyncSeek, AsyncSeekExt};
|
||||||
use futures_util::future::FutureExt;
|
use futures_util::future::FutureExt;
|
||||||
|
|
||||||
use crate::response::{Responder, ResultFuture};
|
use crate::response::{Responder, ResultFuture};
|
||||||
|
@ -104,6 +105,12 @@ impl<T> fmt::Debug for Body<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Internal workaround for `Box<dyn AsyncRead + AsyncSeek>` not being allowed.
|
||||||
|
///
|
||||||
|
/// https://github.com/rust-lang/rfcs/issues/2035
|
||||||
|
trait AsyncReadAsyncSeek: AsyncRead + AsyncSeek + Unpin + Send {}
|
||||||
|
impl<T: AsyncRead + AsyncSeek + Unpin + Send> AsyncReadAsyncSeek for T {}
|
||||||
|
|
||||||
/// Type for easily building `Response`s.
|
/// Type for easily building `Response`s.
|
||||||
///
|
///
|
||||||
/// Building a [`Response`] can be a low-level ordeal; this structure presents a
|
/// Building a [`Response`] can be a low-level ordeal; this structure presents a
|
||||||
|
@ -117,8 +124,9 @@ impl<T> fmt::Debug for Body<T> {
|
||||||
/// with field(s) modified in the `Responder` being built. These method calls
|
/// with field(s) modified in the `Responder` being built. These method calls
|
||||||
/// can be chained: `build.a().b()`.
|
/// can be chained: `build.a().b()`.
|
||||||
///
|
///
|
||||||
/// To finish building and retrieve the built `Response`, use the
|
/// To finish building and retrieve the built `Response`, `.await` the builder.
|
||||||
/// [`finalize()`](#method.finalize) or [`ok()`](#method.ok) methods.
|
/// The [`ok()` method](#method.ok) is also provided as a convenience
|
||||||
|
/// for `Responder` implementations.
|
||||||
///
|
///
|
||||||
/// ## Headers
|
/// ## Headers
|
||||||
///
|
///
|
||||||
|
@ -153,6 +161,8 @@ impl<T> fmt::Debug for Body<T> {
|
||||||
/// use rocket::response::Response;
|
/// use rocket::response::Response;
|
||||||
/// use rocket::http::{Status, ContentType};
|
/// use rocket::http::{Status, ContentType};
|
||||||
///
|
///
|
||||||
|
/// # rocket::async_test(async {
|
||||||
|
///
|
||||||
/// # #[allow(unused_variables)]
|
/// # #[allow(unused_variables)]
|
||||||
/// let response = Response::build()
|
/// let response = Response::build()
|
||||||
/// .status(Status::ImATeapot)
|
/// .status(Status::ImATeapot)
|
||||||
|
@ -161,10 +171,14 @@ impl<T> fmt::Debug for Body<T> {
|
||||||
/// .raw_header("X-Teapot-Model", "Utopia")
|
/// .raw_header("X-Teapot-Model", "Utopia")
|
||||||
/// .raw_header_adjoin("X-Teapot-Model", "Series 1")
|
/// .raw_header_adjoin("X-Teapot-Model", "Series 1")
|
||||||
/// .sized_body(Cursor::new("Brewing the best coffee!"))
|
/// .sized_body(Cursor::new("Brewing the best coffee!"))
|
||||||
/// .finalize();
|
/// .await;
|
||||||
|
///
|
||||||
|
/// # })
|
||||||
/// ```
|
/// ```
|
||||||
pub struct ResponseBuilder<'r> {
|
pub struct ResponseBuilder<'r> {
|
||||||
response: Response<'r>
|
response: Response<'r>,
|
||||||
|
pending_sized_body: Option<Box<dyn AsyncReadAsyncSeek + 'r>>,
|
||||||
|
fut: Option<Pin<Box<dyn Future<Output=Response<'r>> + Send + 'r>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'r> ResponseBuilder<'r> {
|
impl<'r> ResponseBuilder<'r> {
|
||||||
|
@ -182,7 +196,9 @@ impl<'r> ResponseBuilder<'r> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn new(base: Response<'r>) -> ResponseBuilder<'r> {
|
pub fn new(base: Response<'r>) -> ResponseBuilder<'r> {
|
||||||
ResponseBuilder {
|
ResponseBuilder {
|
||||||
response: base
|
response: base,
|
||||||
|
pending_sized_body: None,
|
||||||
|
fut: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,10 +210,14 @@ impl<'r> ResponseBuilder<'r> {
|
||||||
/// use rocket::Response;
|
/// use rocket::Response;
|
||||||
/// use rocket::http::Status;
|
/// use rocket::http::Status;
|
||||||
///
|
///
|
||||||
|
/// # rocket::async_test(async {
|
||||||
|
///
|
||||||
/// # #[allow(unused_variables)]
|
/// # #[allow(unused_variables)]
|
||||||
/// let response = Response::build()
|
/// let response = Response::build()
|
||||||
/// .status(Status::NotFound)
|
/// .status(Status::NotFound)
|
||||||
/// .finalize();
|
/// .await;
|
||||||
|
///
|
||||||
|
/// # })
|
||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn status(&mut self, status: Status) -> &mut ResponseBuilder<'r> {
|
pub fn status(&mut self, status: Status) -> &mut ResponseBuilder<'r> {
|
||||||
|
@ -213,10 +233,13 @@ impl<'r> ResponseBuilder<'r> {
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use rocket::Response;
|
/// use rocket::Response;
|
||||||
///
|
///
|
||||||
|
/// # rocket::async_test(async {
|
||||||
|
///
|
||||||
/// # #[allow(unused_variables)]
|
/// # #[allow(unused_variables)]
|
||||||
/// let response = Response::build()
|
/// let response = Response::build()
|
||||||
/// .raw_status(699, "Alien Encounter")
|
/// .raw_status(699, "Alien Encounter")
|
||||||
/// .finalize();
|
/// .await;
|
||||||
|
/// # })
|
||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn raw_status(&mut self, code: u16, reason: &'static str)
|
pub fn raw_status(&mut self, code: u16, reason: &'static str)
|
||||||
|
@ -240,12 +263,16 @@ impl<'r> ResponseBuilder<'r> {
|
||||||
/// use rocket::Response;
|
/// use rocket::Response;
|
||||||
/// use rocket::http::ContentType;
|
/// use rocket::http::ContentType;
|
||||||
///
|
///
|
||||||
|
/// # rocket::async_test(async {
|
||||||
|
///
|
||||||
/// let response = Response::build()
|
/// let response = Response::build()
|
||||||
/// .header(ContentType::JSON)
|
/// .header(ContentType::JSON)
|
||||||
/// .header(ContentType::HTML)
|
/// .header(ContentType::HTML)
|
||||||
/// .finalize();
|
/// .await;
|
||||||
///
|
///
|
||||||
/// assert_eq!(response.headers().get("Content-Type").count(), 1);
|
/// assert_eq!(response.headers().get("Content-Type").count(), 1);
|
||||||
|
///
|
||||||
|
/// # })
|
||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn header<'h: 'r, H>(&mut self, header: H) -> &mut ResponseBuilder<'r>
|
pub fn header<'h: 'r, H>(&mut self, header: H) -> &mut ResponseBuilder<'r>
|
||||||
|
@ -271,12 +298,16 @@ impl<'r> ResponseBuilder<'r> {
|
||||||
/// use rocket::http::Header;
|
/// use rocket::http::Header;
|
||||||
/// use rocket::http::hyper::header::ACCEPT;
|
/// use rocket::http::hyper::header::ACCEPT;
|
||||||
///
|
///
|
||||||
|
/// # rocket::async_test(async {
|
||||||
|
///
|
||||||
/// let response = Response::build()
|
/// let response = Response::build()
|
||||||
/// .header_adjoin(Header::new(ACCEPT.as_str(), "application/json"))
|
/// .header_adjoin(Header::new(ACCEPT.as_str(), "application/json"))
|
||||||
/// .header_adjoin(Header::new(ACCEPT.as_str(), "text/plain"))
|
/// .header_adjoin(Header::new(ACCEPT.as_str(), "text/plain"))
|
||||||
/// .finalize();
|
/// .await;
|
||||||
///
|
///
|
||||||
/// assert_eq!(response.headers().get("Accept").count(), 2);
|
/// assert_eq!(response.headers().get("Accept").count(), 2);
|
||||||
|
///
|
||||||
|
/// # })
|
||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn header_adjoin<'h: 'r, H>(&mut self, header: H) -> &mut ResponseBuilder<'r>
|
pub fn header_adjoin<'h: 'r, H>(&mut self, header: H) -> &mut ResponseBuilder<'r>
|
||||||
|
@ -296,12 +327,16 @@ impl<'r> ResponseBuilder<'r> {
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use rocket::Response;
|
/// use rocket::Response;
|
||||||
///
|
///
|
||||||
|
/// # rocket::async_test(async {
|
||||||
|
///
|
||||||
/// let response = Response::build()
|
/// let response = Response::build()
|
||||||
/// .raw_header("X-Custom", "first")
|
/// .raw_header("X-Custom", "first")
|
||||||
/// .raw_header("X-Custom", "second")
|
/// .raw_header("X-Custom", "second")
|
||||||
/// .finalize();
|
/// .await;
|
||||||
///
|
///
|
||||||
/// assert_eq!(response.headers().get("X-Custom").count(), 1);
|
/// assert_eq!(response.headers().get("X-Custom").count(), 1);
|
||||||
|
///
|
||||||
|
/// # })
|
||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn raw_header<'a: 'r, 'b: 'r, N, V>(&mut self, name: N, value: V)
|
pub fn raw_header<'a: 'r, 'b: 'r, N, V>(&mut self, name: N, value: V)
|
||||||
|
@ -323,12 +358,16 @@ impl<'r> ResponseBuilder<'r> {
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use rocket::Response;
|
/// use rocket::Response;
|
||||||
///
|
///
|
||||||
|
/// # rocket::async_test(async {
|
||||||
|
///
|
||||||
/// let response = Response::build()
|
/// let response = Response::build()
|
||||||
/// .raw_header_adjoin("X-Custom", "first")
|
/// .raw_header_adjoin("X-Custom", "first")
|
||||||
/// .raw_header_adjoin("X-Custom", "second")
|
/// .raw_header_adjoin("X-Custom", "second")
|
||||||
/// .finalize();
|
/// .await;
|
||||||
///
|
///
|
||||||
/// assert_eq!(response.headers().get("X-Custom").count(), 2);
|
/// assert_eq!(response.headers().get("X-Custom").count(), 2);
|
||||||
|
///
|
||||||
|
/// # })
|
||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn raw_header_adjoin<'a: 'r, 'b: 'r, N, V>(&mut self, name: N, value: V)
|
pub fn raw_header_adjoin<'a: 'r, 'b: 'r, N, V>(&mut self, name: N, value: V)
|
||||||
|
@ -339,12 +378,11 @@ impl<'r> ResponseBuilder<'r> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO.async: un-ignore this test once Seek/AsyncSeek situation has been resolved.
|
|
||||||
/// Sets the body of the `Response` to be the fixed-sized `body`.
|
/// Sets the body of the `Response` to be the fixed-sized `body`.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```rust,ignore
|
/// ```rust
|
||||||
/// use rocket::Response;
|
/// use rocket::Response;
|
||||||
/// use tokio::fs::File;
|
/// use tokio::fs::File;
|
||||||
/// # use std::io;
|
/// # use std::io;
|
||||||
|
@ -354,15 +392,15 @@ impl<'r> ResponseBuilder<'r> {
|
||||||
/// # #[allow(unused_variables)]
|
/// # #[allow(unused_variables)]
|
||||||
/// let response = Response::build()
|
/// let response = Response::build()
|
||||||
/// .sized_body(File::open("body.txt").await?)
|
/// .sized_body(File::open("body.txt").await?)
|
||||||
/// .finalize();
|
/// .await;
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn sized_body<B>(&mut self, body: B) -> &mut ResponseBuilder<'r>
|
pub fn sized_body<B>(&mut self, body: B) -> &mut ResponseBuilder<'r>
|
||||||
where B: AsyncRead + io::Seek + Send + Unpin + 'r
|
where B: AsyncRead + AsyncSeek + Send + Unpin + 'r
|
||||||
{
|
{
|
||||||
self.response.set_sized_body(body);
|
self.pending_sized_body = Some(Box::new(body));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,7 +418,7 @@ impl<'r> ResponseBuilder<'r> {
|
||||||
/// # #[allow(unused_variables)]
|
/// # #[allow(unused_variables)]
|
||||||
/// let response = Response::build()
|
/// let response = Response::build()
|
||||||
/// .streamed_body(File::open("body.txt").await?)
|
/// .streamed_body(File::open("body.txt").await?)
|
||||||
/// .finalize();
|
/// .await;
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -389,6 +427,7 @@ impl<'r> ResponseBuilder<'r> {
|
||||||
where B: AsyncRead + Send + 'r
|
where B: AsyncRead + Send + 'r
|
||||||
{
|
{
|
||||||
self.response.set_streamed_body(body);
|
self.response.set_streamed_body(body);
|
||||||
|
self.pending_sized_body = None;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,7 +446,7 @@ impl<'r> ResponseBuilder<'r> {
|
||||||
/// # #[allow(unused_variables)]
|
/// # #[allow(unused_variables)]
|
||||||
/// let response = Response::build()
|
/// let response = Response::build()
|
||||||
/// .chunked_body(File::open("body.txt").await?, 8096)
|
/// .chunked_body(File::open("body.txt").await?, 8096)
|
||||||
/// .finalize();
|
/// .await;
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -416,6 +455,7 @@ impl<'r> ResponseBuilder<'r> {
|
||||||
-> &mut ResponseBuilder<'r>
|
-> &mut ResponseBuilder<'r>
|
||||||
{
|
{
|
||||||
self.response.set_chunked_body(body, chunk_size);
|
self.response.set_chunked_body(body, chunk_size);
|
||||||
|
self.pending_sized_body = None;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,16 +469,21 @@ impl<'r> ResponseBuilder<'r> {
|
||||||
/// use std::io::Cursor;
|
/// use std::io::Cursor;
|
||||||
/// use rocket::response::{Response, Body};
|
/// use rocket::response::{Response, Body};
|
||||||
///
|
///
|
||||||
|
/// # rocket::async_test(async {
|
||||||
|
///
|
||||||
/// # #[allow(unused_variables)]
|
/// # #[allow(unused_variables)]
|
||||||
/// let response = Response::build()
|
/// let response = Response::build()
|
||||||
/// .raw_body(Body::Sized(Cursor::new("Hello!"), 6))
|
/// .raw_body(Body::Sized(Cursor::new("Hello!"), 6))
|
||||||
/// .finalize();
|
/// .await;
|
||||||
|
///
|
||||||
|
/// # })
|
||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn raw_body<T: AsyncRead + Send + Unpin + 'r>(&mut self, body: Body<T>)
|
pub fn raw_body<T: AsyncRead + Send + Unpin + 'r>(&mut self, body: Body<T>)
|
||||||
-> &mut ResponseBuilder<'r>
|
-> &mut ResponseBuilder<'r>
|
||||||
{
|
{
|
||||||
self.response.set_raw_body(body);
|
self.response.set_raw_body(body);
|
||||||
|
self.pending_sized_body = None;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,18 +499,20 @@ impl<'r> ResponseBuilder<'r> {
|
||||||
/// use rocket::Response;
|
/// use rocket::Response;
|
||||||
/// use rocket::http::{Status, ContentType};
|
/// use rocket::http::{Status, ContentType};
|
||||||
///
|
///
|
||||||
|
/// # rocket::async_test(async {
|
||||||
|
///
|
||||||
/// let base = Response::build()
|
/// let base = Response::build()
|
||||||
/// .status(Status::NotFound)
|
/// .status(Status::NotFound)
|
||||||
/// .header(ContentType::HTML)
|
/// .header(ContentType::HTML)
|
||||||
/// .raw_header("X-Custom", "value 1")
|
/// .raw_header("X-Custom", "value 1")
|
||||||
/// .finalize();
|
/// .await;
|
||||||
///
|
///
|
||||||
/// let response = Response::build()
|
/// let response = Response::build()
|
||||||
/// .status(Status::ImATeapot)
|
/// .status(Status::ImATeapot)
|
||||||
/// .raw_header("X-Custom", "value 2")
|
/// .raw_header("X-Custom", "value 2")
|
||||||
/// .raw_header_adjoin("X-Custom", "value 3")
|
/// .raw_header_adjoin("X-Custom", "value 3")
|
||||||
/// .merge(base)
|
/// .merge(base)
|
||||||
/// .finalize();
|
/// .await;
|
||||||
///
|
///
|
||||||
/// assert_eq!(response.status(), Status::NotFound);
|
/// assert_eq!(response.status(), Status::NotFound);
|
||||||
///
|
///
|
||||||
|
@ -478,9 +525,14 @@ impl<'r> ResponseBuilder<'r> {
|
||||||
/// let custom_values: Vec<_> = response.headers().get("X-Custom").collect();
|
/// let custom_values: Vec<_> = response.headers().get("X-Custom").collect();
|
||||||
/// assert_eq!(custom_values, vec!["value 1"]);
|
/// assert_eq!(custom_values, vec!["value 1"]);
|
||||||
/// # }
|
/// # }
|
||||||
|
///
|
||||||
|
/// # });
|
||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn merge(&mut self, other: Response<'r>) -> &mut ResponseBuilder<'r> {
|
pub fn merge(&mut self, mut other: Response<'r>) -> &mut ResponseBuilder<'r> {
|
||||||
|
if other.body().is_some() {
|
||||||
|
self.pending_sized_body = None;
|
||||||
|
}
|
||||||
self.response.merge(other);
|
self.response.merge(other);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -498,18 +550,20 @@ impl<'r> ResponseBuilder<'r> {
|
||||||
/// use rocket::Response;
|
/// use rocket::Response;
|
||||||
/// use rocket::http::{Status, ContentType};
|
/// use rocket::http::{Status, ContentType};
|
||||||
///
|
///
|
||||||
|
/// # rocket::async_test(async {
|
||||||
|
///
|
||||||
/// let other = Response::build()
|
/// let other = Response::build()
|
||||||
/// .status(Status::NotFound)
|
/// .status(Status::NotFound)
|
||||||
/// .header(ContentType::HTML)
|
/// .header(ContentType::HTML)
|
||||||
/// .raw_header("X-Custom", "value 1")
|
/// .raw_header("X-Custom", "value 1")
|
||||||
/// .finalize();
|
/// .await;
|
||||||
///
|
///
|
||||||
/// let response = Response::build()
|
/// let response = Response::build()
|
||||||
/// .status(Status::ImATeapot)
|
/// .status(Status::ImATeapot)
|
||||||
/// .raw_header("X-Custom", "value 2")
|
/// .raw_header("X-Custom", "value 2")
|
||||||
/// .raw_header_adjoin("X-Custom", "value 3")
|
/// .raw_header_adjoin("X-Custom", "value 3")
|
||||||
/// .join(other)
|
/// .join(other)
|
||||||
/// .finalize();
|
/// .await;
|
||||||
///
|
///
|
||||||
/// assert_eq!(response.status(), Status::ImATeapot);
|
/// assert_eq!(response.status(), Status::ImATeapot);
|
||||||
///
|
///
|
||||||
|
@ -522,6 +576,8 @@ impl<'r> ResponseBuilder<'r> {
|
||||||
/// let custom_values: Vec<_> = response.headers().get("X-Custom").collect();
|
/// let custom_values: Vec<_> = response.headers().get("X-Custom").collect();
|
||||||
/// assert_eq!(custom_values, vec!["value 2", "value 3", "value 1"]);
|
/// assert_eq!(custom_values, vec!["value 2", "value 3", "value 1"]);
|
||||||
/// # }
|
/// # }
|
||||||
|
///
|
||||||
|
/// # })
|
||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn join(&mut self, other: Response<'r>) -> &mut ResponseBuilder<'r> {
|
pub fn join(&mut self, other: Response<'r>) -> &mut ResponseBuilder<'r> {
|
||||||
|
@ -529,23 +585,6 @@ impl<'r> ResponseBuilder<'r> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve the built `Response`.
|
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// use rocket::Response;
|
|
||||||
///
|
|
||||||
/// # #[allow(unused_variables)]
|
|
||||||
/// let response = Response::build()
|
|
||||||
/// // build the response
|
|
||||||
/// .finalize();
|
|
||||||
/// ```
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn finalize(&mut self) -> Response<'r> {
|
|
||||||
std::mem::replace(&mut self.response, Response::new())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Retrieve the built `Response` wrapped in `Ok`.
|
/// Retrieve the built `Response` wrapped in `Ok`.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
|
@ -553,15 +592,39 @@ impl<'r> ResponseBuilder<'r> {
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use rocket::Response;
|
/// use rocket::Response;
|
||||||
///
|
///
|
||||||
|
/// # rocket::async_test(async {
|
||||||
|
///
|
||||||
/// let response: Result<Response, ()> = Response::build()
|
/// let response: Result<Response, ()> = Response::build()
|
||||||
/// // build the response
|
/// // build the response
|
||||||
/// .ok();
|
/// .ok()
|
||||||
|
/// .await;
|
||||||
///
|
///
|
||||||
/// assert!(response.is_ok());
|
/// assert!(response.is_ok());
|
||||||
|
///
|
||||||
|
/// # })
|
||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn ok<T>(&mut self) -> Result<Response<'r>, T> {
|
pub async fn ok<E>(&mut self) -> Result<Response<'r>, E> {
|
||||||
Ok(self.finalize())
|
Ok(self.await)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'r> Future for ResponseBuilder<'r> {
|
||||||
|
type Output = Response<'r>;
|
||||||
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
|
let this = self.get_mut();
|
||||||
|
if this.fut.is_none() {
|
||||||
|
let mut response = std::mem::replace(&mut this.response, Response::new());
|
||||||
|
let pending_sized_body = this.pending_sized_body.take();
|
||||||
|
this.fut = Some(Box::pin(async {
|
||||||
|
if let Some(sb) = pending_sized_body {
|
||||||
|
// TODO: Avoid double boxing (Pin<Box<Take<Pin<Box<dyn AsyncReadAsyncSeek>>>>>)
|
||||||
|
response.set_sized_body(sb).await;
|
||||||
|
}
|
||||||
|
response
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
this.fut.as_mut().expect("this.fut.is_none() checked and assigned Some").as_mut().poll(cx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -897,7 +960,7 @@ impl<'r> Response<'r> {
|
||||||
/// let mut response = Response::new();
|
/// let mut response = Response::new();
|
||||||
/// assert!(response.body().is_none());
|
/// assert!(response.body().is_none());
|
||||||
///
|
///
|
||||||
/// response.set_sized_body(Cursor::new("Hello, world!"));
|
/// response.set_sized_body(Cursor::new("Hello, world!")).await;
|
||||||
/// assert_eq!(response.body_string().await, Some("Hello, world!".to_string()));
|
/// assert_eq!(response.body_string().await, Some("Hello, world!".to_string()));
|
||||||
/// # })
|
/// # })
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -928,7 +991,7 @@ impl<'r> Response<'r> {
|
||||||
/// let mut response = Response::new();
|
/// let mut response = Response::new();
|
||||||
/// assert!(response.body().is_none());
|
/// assert!(response.body().is_none());
|
||||||
///
|
///
|
||||||
/// response.set_sized_body(Cursor::new("Hello, world!"));
|
/// response.set_sized_body(Cursor::new("Hello, world!")).await;
|
||||||
/// assert_eq!(response.body_string().await, Some("Hello, world!".to_string()));
|
/// assert_eq!(response.body_string().await, Some("Hello, world!".to_string()));
|
||||||
/// assert!(response.body().is_none());
|
/// assert!(response.body().is_none());
|
||||||
/// # })
|
/// # })
|
||||||
|
@ -958,7 +1021,7 @@ impl<'r> Response<'r> {
|
||||||
/// let mut response = Response::new();
|
/// let mut response = Response::new();
|
||||||
/// assert!(response.body().is_none());
|
/// assert!(response.body().is_none());
|
||||||
///
|
///
|
||||||
/// response.set_sized_body(Cursor::new("hi!"));
|
/// response.set_sized_body(Cursor::new("hi!")).await;
|
||||||
/// assert_eq!(response.body_bytes().await, Some(vec![0x68, 0x69, 0x21]));
|
/// assert_eq!(response.body_bytes().await, Some(vec![0x68, 0x69, 0x21]));
|
||||||
/// assert!(response.body().is_none());
|
/// assert!(response.body().is_none());
|
||||||
/// # })
|
/// # })
|
||||||
|
@ -987,7 +1050,7 @@ impl<'r> Response<'r> {
|
||||||
/// let mut response = Response::new();
|
/// let mut response = Response::new();
|
||||||
/// assert!(response.body().is_none());
|
/// assert!(response.body().is_none());
|
||||||
///
|
///
|
||||||
/// response.set_sized_body(Cursor::new("Hello, world!"));
|
/// response.set_sized_body(Cursor::new("Hello, world!")).await;
|
||||||
/// assert!(response.body().is_some());
|
/// assert!(response.body().is_some());
|
||||||
///
|
///
|
||||||
/// let body = response.take_body();
|
/// let body = response.take_body();
|
||||||
|
@ -1018,7 +1081,8 @@ impl<'r> Response<'r> {
|
||||||
|
|
||||||
/// Sets the body of `self` to be the fixed-sized `body`. The size of the
|
/// Sets the body of `self` to be the fixed-sized `body`. The size of the
|
||||||
/// body is obtained by `seek`ing to the end and then `seek`ing back to the
|
/// body is obtained by `seek`ing to the end and then `seek`ing back to the
|
||||||
/// start.
|
/// start. Since this is an asynchronous operation, it returns a future
|
||||||
|
/// and should be `await`-ed on.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
|
@ -1034,17 +1098,16 @@ impl<'r> Response<'r> {
|
||||||
///
|
///
|
||||||
/// # rocket::async_test(async {
|
/// # rocket::async_test(async {
|
||||||
/// let mut response = Response::new();
|
/// let mut response = Response::new();
|
||||||
/// response.set_sized_body(Cursor::new("Hello, world!"));
|
/// response.set_sized_body(Cursor::new("Hello, world!")).await;
|
||||||
/// assert_eq!(response.body_string().await, Some("Hello, world!".to_string()));
|
/// assert_eq!(response.body_string().await, Some("Hello, world!".to_string()));
|
||||||
/// # })
|
/// # })
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
pub async fn set_sized_body<B>(&mut self, mut body: B)
|
||||||
pub fn set_sized_body<B>(&mut self, mut body: B)
|
where B: AsyncRead + AsyncSeek + Send + Unpin + 'r
|
||||||
where B: AsyncRead + io::Seek + Send + Unpin + 'r
|
|
||||||
{
|
{
|
||||||
let size = body.seek(io::SeekFrom::End(0))
|
let size = body.seek(io::SeekFrom::End(0)).await
|
||||||
.expect("Attempted to retrieve size by seeking, but failed.");
|
.expect("Attempted to retrieve size by seeking, but failed.");
|
||||||
body.seek(io::SeekFrom::Start(0))
|
body.seek(io::SeekFrom::Start(0)).await
|
||||||
.expect("Attempted to reset body by seeking after getting size.");
|
.expect("Attempted to reset body by seeking after getting size.");
|
||||||
self.body = Some(Body::Sized(Box::pin(body.take(size)), size));
|
self.body = Some(Body::Sized(Box::pin(body.take(size)), size));
|
||||||
}
|
}
|
||||||
|
@ -1130,18 +1193,20 @@ impl<'r> Response<'r> {
|
||||||
/// use rocket::Response;
|
/// use rocket::Response;
|
||||||
/// use rocket::http::{Status, ContentType};
|
/// use rocket::http::{Status, ContentType};
|
||||||
///
|
///
|
||||||
|
/// # rocket::async_test(async {
|
||||||
|
///
|
||||||
/// let base = Response::build()
|
/// let base = Response::build()
|
||||||
/// .status(Status::NotFound)
|
/// .status(Status::NotFound)
|
||||||
/// .header(ContentType::HTML)
|
/// .header(ContentType::HTML)
|
||||||
/// .raw_header("X-Custom", "value 1")
|
/// .raw_header("X-Custom", "value 1")
|
||||||
/// .finalize();
|
/// .await;
|
||||||
///
|
///
|
||||||
/// let response = Response::build()
|
/// let response = Response::build()
|
||||||
/// .status(Status::ImATeapot)
|
/// .status(Status::ImATeapot)
|
||||||
/// .raw_header("X-Custom", "value 2")
|
/// .raw_header("X-Custom", "value 2")
|
||||||
/// .raw_header_adjoin("X-Custom", "value 3")
|
/// .raw_header_adjoin("X-Custom", "value 3")
|
||||||
/// .merge(base)
|
/// .merge(base)
|
||||||
/// .finalize();
|
/// .await;
|
||||||
///
|
///
|
||||||
/// assert_eq!(response.status(), Status::NotFound);
|
/// assert_eq!(response.status(), Status::NotFound);
|
||||||
///
|
///
|
||||||
|
@ -1154,6 +1219,8 @@ impl<'r> Response<'r> {
|
||||||
/// let custom_values: Vec<_> = response.headers().get("X-Custom").collect();
|
/// let custom_values: Vec<_> = response.headers().get("X-Custom").collect();
|
||||||
/// assert_eq!(custom_values, vec!["value 1"]);
|
/// assert_eq!(custom_values, vec!["value 1"]);
|
||||||
/// # }
|
/// # }
|
||||||
|
///
|
||||||
|
/// # })
|
||||||
/// ```
|
/// ```
|
||||||
pub fn merge(&mut self, other: Response<'r>) {
|
pub fn merge(&mut self, other: Response<'r>) {
|
||||||
if let Some(status) = other.status {
|
if let Some(status) = other.status {
|
||||||
|
@ -1179,18 +1246,20 @@ impl<'r> Response<'r> {
|
||||||
/// use rocket::Response;
|
/// use rocket::Response;
|
||||||
/// use rocket::http::{Status, ContentType};
|
/// use rocket::http::{Status, ContentType};
|
||||||
///
|
///
|
||||||
|
/// # rocket::async_test(async {
|
||||||
|
///
|
||||||
/// let other = Response::build()
|
/// let other = Response::build()
|
||||||
/// .status(Status::NotFound)
|
/// .status(Status::NotFound)
|
||||||
/// .header(ContentType::HTML)
|
/// .header(ContentType::HTML)
|
||||||
/// .raw_header("X-Custom", "value 1")
|
/// .raw_header("X-Custom", "value 1")
|
||||||
/// .finalize();
|
/// .await;
|
||||||
///
|
///
|
||||||
/// let response = Response::build()
|
/// let response = Response::build()
|
||||||
/// .status(Status::ImATeapot)
|
/// .status(Status::ImATeapot)
|
||||||
/// .raw_header("X-Custom", "value 2")
|
/// .raw_header("X-Custom", "value 2")
|
||||||
/// .raw_header_adjoin("X-Custom", "value 3")
|
/// .raw_header_adjoin("X-Custom", "value 3")
|
||||||
/// .join(other)
|
/// .join(other)
|
||||||
/// .finalize();
|
/// .await;
|
||||||
///
|
///
|
||||||
/// assert_eq!(response.status(), Status::ImATeapot);
|
/// assert_eq!(response.status(), Status::ImATeapot);
|
||||||
///
|
///
|
||||||
|
@ -1203,6 +1272,8 @@ impl<'r> Response<'r> {
|
||||||
/// let custom_values: Vec<_> = response.headers().get("X-Custom").collect();
|
/// let custom_values: Vec<_> = response.headers().get("X-Custom").collect();
|
||||||
/// assert_eq!(custom_values, vec!["value 2", "value 3", "value 1"]);
|
/// assert_eq!(custom_values, vec!["value 2", "value 3", "value 1"]);
|
||||||
/// # }
|
/// # }
|
||||||
|
///
|
||||||
|
/// # })
|
||||||
/// ```
|
/// ```
|
||||||
pub fn join(&mut self, other: Response<'r>) {
|
pub fn join(&mut self, other: Response<'r>) {
|
||||||
if self.status.is_none() {
|
if self.status.is_none() {
|
||||||
|
|
|
@ -175,6 +175,7 @@ impl<'r, R: Responder<'r> + Send + 'r> Responder<'r> for Created<R> {
|
||||||
response.status(Status::Created)
|
response.status(Status::Created)
|
||||||
.raw_header("Location", self.0)
|
.raw_header("Location", self.0)
|
||||||
.ok()
|
.ok()
|
||||||
|
.await
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -216,7 +217,7 @@ impl<'r, R: Responder<'r> + Send + 'r> Responder<'r> for Accepted<R> {
|
||||||
build.merge(responder.respond_to(req).await?);
|
build.merge(responder.respond_to(req).await?);
|
||||||
}
|
}
|
||||||
|
|
||||||
build.status(Status::Accepted).ok()
|
build.status(Status::Accepted).ok().await
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -283,7 +284,7 @@ impl<'r, R: Responder<'r> + Send + 'r> Responder<'r> for BadRequest<R> {
|
||||||
build.merge(responder.respond_to(req).await?);
|
build.merge(responder.respond_to(req).await?);
|
||||||
}
|
}
|
||||||
|
|
||||||
build.status(Status::BadRequest).ok()
|
build.status(Status::BadRequest).ok().await
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -390,6 +391,7 @@ impl<'r, R: Responder<'r> + Send + 'r> Responder<'r> for NotFound<R> {
|
||||||
Response::build_from(self.0.respond_to(req).await?)
|
Response::build_from(self.0.respond_to(req).await?)
|
||||||
.status(Status::NotFound)
|
.status(Status::NotFound)
|
||||||
.ok()
|
.ok()
|
||||||
|
.await
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -457,6 +459,7 @@ impl<'r, R: Responder<'r> + Send + 'r> Responder<'r> for Custom<R> {
|
||||||
Response::build_from(self.1.respond_to(req).await?)
|
Response::build_from(self.1.respond_to(req).await?)
|
||||||
.status(self.0)
|
.status(self.0)
|
||||||
.ok()
|
.ok()
|
||||||
|
.await
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ impl<T: AsyncRead> From<T> for Stream<T> {
|
||||||
impl<'r, T: AsyncRead + Send + 'r> Responder<'r> for Stream<T> {
|
impl<'r, T: AsyncRead + Send + 'r> Responder<'r> for Stream<T> {
|
||||||
fn respond_to(self, _: &'r Request<'_>) -> ResultFuture<'r> {
|
fn respond_to(self, _: &'r Request<'_>) -> ResultFuture<'r> {
|
||||||
Box::pin(async {
|
Box::pin(async {
|
||||||
Response::build().chunked_body(self.0, self.1).ok()
|
Response::build().chunked_body(self.0, self.1).ok().await
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,10 @@ use rocket::Response;
|
||||||
use rocket::http::Header;
|
use rocket::http::Header;
|
||||||
|
|
||||||
#[get("/do_not_overwrite")]
|
#[get("/do_not_overwrite")]
|
||||||
fn do_not_overwrite() -> Response<'static> {
|
async fn do_not_overwrite() -> Response<'static> {
|
||||||
Response::build()
|
Response::build()
|
||||||
.header(Header::new("Server", "Test"))
|
.header(Header::new("Server", "Test"))
|
||||||
.finalize()
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/use_default")]
|
#[get("/use_default")]
|
||||||
|
|
|
@ -54,7 +54,7 @@ impl Fairing for Counter {
|
||||||
let body = format!("Get: {}\nPost: {}", get_count, post_count);
|
let body = format!("Get: {}\nPost: {}", get_count, post_count);
|
||||||
response.set_status(Status::Ok);
|
response.set_status(Status::Ok);
|
||||||
response.set_header(ContentType::Plain);
|
response.set_header(ContentType::Plain);
|
||||||
response.set_sized_body(Cursor::new(body));
|
response.set_sized_body(Cursor::new(body)).await;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ fn rocket() -> rocket::Rocket {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
if req.uri().path() == "/" {
|
if req.uri().path() == "/" {
|
||||||
println!(" => Rewriting response body.");
|
println!(" => Rewriting response body.");
|
||||||
res.set_sized_body(Cursor::new("Hello, fairings!"));
|
res.set_sized_body(Cursor::new("Hello, fairings!")).await;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}))
|
}))
|
||||||
|
|
Loading…
Reference in New Issue