mirror of https://github.com/fafhrd91/actix-web
trash
This commit is contained in:
parent
d29f208cba
commit
fa9691a2f8
|
@ -1,6 +1,6 @@
|
||||||
use std::{env, io};
|
use std::{env, io};
|
||||||
|
|
||||||
use actix_http::{http::StatusCode, Error, HttpService, Request, Response};
|
use actix_http::{http::StatusCode, HttpService, Request, Response};
|
||||||
use actix_server::Server;
|
use actix_server::Server;
|
||||||
use bytes::BytesMut;
|
use bytes::BytesMut;
|
||||||
use futures_util::StreamExt as _;
|
use futures_util::StreamExt as _;
|
||||||
|
@ -24,14 +24,14 @@ async fn main() -> io::Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("request body: {:?}", body);
|
info!("request body: {:?}", body);
|
||||||
Ok::<_, Error>(
|
|
||||||
Response::builder(StatusCode::OK)
|
Response::builder(StatusCode::OK)
|
||||||
.insert_header((
|
.insert_header((
|
||||||
"x-head",
|
"x-head",
|
||||||
HeaderValue::from_static("dummy value!"),
|
HeaderValue::from_static("dummy value!"),
|
||||||
))
|
))
|
||||||
.body(body),
|
.take()
|
||||||
)
|
.body(body)
|
||||||
})
|
})
|
||||||
.tcp()
|
.tcp()
|
||||||
})?
|
})?
|
||||||
|
|
|
@ -17,9 +17,10 @@ async fn handle_request(mut req: Request) -> Result<Response<Body>, Error> {
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("request body: {:?}", body);
|
info!("request body: {:?}", body);
|
||||||
Ok(Response::builder(StatusCode::OK)
|
Response::builder(StatusCode::OK)
|
||||||
.insert_header(("x-head", HeaderValue::from_static("dummy value!")))
|
.insert_header(("x-head", HeaderValue::from_static("dummy value!")))
|
||||||
.body(body))
|
.take()
|
||||||
|
.body(body)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_rt::main]
|
||||||
|
|
|
@ -23,7 +23,7 @@ async fn main() -> io::Result<()> {
|
||||||
"x-head",
|
"x-head",
|
||||||
HeaderValue::from_static("dummy value!"),
|
HeaderValue::from_static("dummy value!"),
|
||||||
));
|
));
|
||||||
future::ok::<_, ()>(res.body("Hello world!"))
|
future::ready(res.body("Hello world!"))
|
||||||
})
|
})
|
||||||
.tcp()
|
.tcp()
|
||||||
})?
|
})?
|
||||||
|
|
|
@ -36,12 +36,12 @@ async fn main() -> io::Result<()> {
|
||||||
|
|
||||||
async fn handler(req: Request) -> Result<Response<BodyStream<Heartbeat>>, Error> {
|
async fn handler(req: Request) -> Result<Response<BodyStream<Heartbeat>>, Error> {
|
||||||
log::info!("handshaking");
|
log::info!("handshaking");
|
||||||
let mut res = ws::handshake(req.head())?;
|
let res = ws::handshake(req.head())?;
|
||||||
|
|
||||||
// handshake will always fail under HTTP/2
|
// handshake will always fail under HTTP/2
|
||||||
|
|
||||||
log::info!("responding");
|
log::info!("responding");
|
||||||
Ok(res.message_body(BodyStream::new(Heartbeat::new(ws::Codec::new()))))
|
res.streaming(Heartbeat::new(ws::Codec::new()))
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Heartbeat {
|
struct Heartbeat {
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
//! Traits and structures to aid consuming and writing HTTP payloads.
|
//! Traits and structures to aid consuming and writing HTTP payloads.
|
||||||
|
|
||||||
|
use std::task::Poll;
|
||||||
|
|
||||||
|
use actix_rt::pin;
|
||||||
|
use actix_utils::future::poll_fn;
|
||||||
|
use bytes::{Bytes, BytesMut};
|
||||||
|
use futures_core::ready;
|
||||||
|
|
||||||
#[allow(clippy::module_inception)]
|
#[allow(clippy::module_inception)]
|
||||||
mod body;
|
mod body;
|
||||||
mod body_stream;
|
mod body_stream;
|
||||||
|
@ -15,6 +22,31 @@ pub use self::response_body::ResponseBody;
|
||||||
pub use self::size::BodySize;
|
pub use self::size::BodySize;
|
||||||
pub use self::sized_stream::SizedStream;
|
pub use self::sized_stream::SizedStream;
|
||||||
|
|
||||||
|
pub async fn to_bytes(body: impl MessageBody) -> Result<Bytes, crate::Error> {
|
||||||
|
let cap = match body.size() {
|
||||||
|
BodySize::None | BodySize::Empty | BodySize::Sized(0) => return Ok(Bytes::new()),
|
||||||
|
BodySize::Sized(size) => size as usize,
|
||||||
|
BodySize::Stream => 32_768,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut buf = BytesMut::with_capacity(cap);
|
||||||
|
|
||||||
|
pin!(body);
|
||||||
|
|
||||||
|
poll_fn(|cx| loop {
|
||||||
|
let body = body.as_mut();
|
||||||
|
|
||||||
|
match ready!(body.poll_next(cx)) {
|
||||||
|
Some(Ok(bytes)) => buf.extend(bytes),
|
||||||
|
None => return Poll::Ready(Ok(())),
|
||||||
|
Some(Err(err)) => return Poll::Ready(Err(err)),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(buf.freeze())
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
|
@ -44,6 +76,42 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ResponseBody<Bytes> {
|
||||||
|
pub(crate) fn get_ref(&self) -> &[u8] {
|
||||||
|
match *self {
|
||||||
|
ResponseBody::Body(ref b) => b.as_ref(),
|
||||||
|
ResponseBody::Other(ref b) => b.get_ref(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResponseBody<String> {
|
||||||
|
pub(crate) fn get_ref(&self) -> &[u8] {
|
||||||
|
match *self {
|
||||||
|
ResponseBody::Body(ref b) => b.as_ref(),
|
||||||
|
ResponseBody::Other(ref b) => b.get_ref(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResponseBody<&str> {
|
||||||
|
pub(crate) fn get_ref(&self) -> &[u8] {
|
||||||
|
match *self {
|
||||||
|
ResponseBody::Body(ref b) => b.as_ref(),
|
||||||
|
ResponseBody::Other(ref b) => b.get_ref(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResponseBody<&[u8]> {
|
||||||
|
pub(crate) fn get_ref(&self) -> &[u8] {
|
||||||
|
match *self {
|
||||||
|
ResponseBody::Body(ref b) => b.as_ref(),
|
||||||
|
ResponseBody::Other(ref b) => b.get_ref(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn test_static_str() {
|
async fn test_static_str() {
|
||||||
assert_eq!(Body::from("").size(), BodySize::Sized(0));
|
assert_eq!(Body::from("").size(), BodySize::Sized(0));
|
||||||
|
|
|
@ -135,8 +135,14 @@ impl From<Response<Body>> for Error {
|
||||||
|
|
||||||
/// Convert ResponseBuilder to a Error
|
/// Convert ResponseBuilder to a Error
|
||||||
impl From<ResponseBuilder> for Error {
|
impl From<ResponseBuilder> for Error {
|
||||||
fn from(mut res: ResponseBuilder) -> Error {
|
fn from(res: ResponseBuilder) -> Error {
|
||||||
InternalError::from_response("", res.finish()).into()
|
match res.finish() {
|
||||||
|
Ok(res) => InternalError::from_response("", res).into(),
|
||||||
|
Err(err) => {
|
||||||
|
let res = err.as_response_error().error_response();
|
||||||
|
InternalError::from_response(err, res).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,12 @@ impl Response<()> {
|
||||||
pub fn not_found() -> Response<()> {
|
pub fn not_found() -> Response<()> {
|
||||||
Response::new(StatusCode::NOT_FOUND)
|
Response::new(StatusCode::NOT_FOUND)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a new response with status 500 Internal Server Error.
|
||||||
|
#[inline]
|
||||||
|
pub fn internal_server_error() -> Response<()> {
|
||||||
|
Response::new(StatusCode::INTERNAL_SERVER_ERROR)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Response<Body> {
|
impl Response<Body> {
|
||||||
|
@ -204,7 +210,7 @@ impl<B> Response<B> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a body and return previous body value
|
/// Set a body and return previous body value.
|
||||||
pub(crate) fn replace_body<B2>(self, body: B2) -> (Response<B2>, ResponseBody<B>) {
|
pub(crate) fn replace_body<B2>(self, body: B2) -> (Response<B2>, ResponseBody<B>) {
|
||||||
(
|
(
|
||||||
Response {
|
Response {
|
||||||
|
@ -216,7 +222,9 @@ impl<B> Response<B> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a body and return previous body value
|
/// Consumes the response returning a new response with the body mapped by a function.
|
||||||
|
///
|
||||||
|
/// Given function also has mutable access to response head.
|
||||||
pub fn map_body<F, B2>(mut self, f: F) -> Response<B2>
|
pub fn map_body<F, B2>(mut self, f: F) -> Response<B2>
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut ResponseHead, ResponseBody<B>) -> ResponseBody<B2>,
|
F: FnOnce(&mut ResponseHead, ResponseBody<B>) -> ResponseBody<B2>,
|
||||||
|
@ -271,38 +279,44 @@ impl<I: Into<Response<Body>>, E: Into<Error>> From<Result<I, E>> for Response<Bo
|
||||||
fn from(res: Result<I, E>) -> Self {
|
fn from(res: Result<I, E>) -> Self {
|
||||||
match res {
|
match res {
|
||||||
Ok(val) => val.into(),
|
Ok(val) => val.into(),
|
||||||
Err(err) => err.into().into(),
|
Err(err) => Response::from_error(err.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ResponseBuilder> for Response<Body> {
|
impl From<ResponseBuilder> for Response<Body> {
|
||||||
fn from(mut builder: ResponseBuilder) -> Self {
|
fn from(builder: ResponseBuilder) -> Self {
|
||||||
builder.finish()
|
builder.finish().into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&'static str> for Response<Body> {
|
impl From<&'static str> for Response<&'static str> {
|
||||||
fn from(val: &'static str) -> Self {
|
fn from(val: &'static str) -> Self {
|
||||||
Response::builder(StatusCode::OK)
|
Response::builder(StatusCode::OK)
|
||||||
.content_type(mime::TEXT_PLAIN_UTF_8)
|
.content_type(mime::TEXT_PLAIN_UTF_8)
|
||||||
|
.take()
|
||||||
.body(val)
|
.body(val)
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&'static [u8]> for Response<Body> {
|
impl From<&'static [u8]> for Response<&'static [u8]> {
|
||||||
fn from(val: &'static [u8]) -> Self {
|
fn from(val: &'static [u8]) -> Self {
|
||||||
Response::builder(StatusCode::OK)
|
Response::builder(StatusCode::OK)
|
||||||
.content_type(mime::APPLICATION_OCTET_STREAM)
|
.content_type(mime::APPLICATION_OCTET_STREAM)
|
||||||
|
.take()
|
||||||
.body(val)
|
.body(val)
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<String> for Response<Body> {
|
impl From<String> for Response<String> {
|
||||||
fn from(val: String) -> Self {
|
fn from(val: String) -> Self {
|
||||||
Response::builder(StatusCode::OK)
|
Response::builder(StatusCode::OK)
|
||||||
.content_type(mime::TEXT_PLAIN_UTF_8)
|
.content_type(mime::TEXT_PLAIN_UTF_8)
|
||||||
|
.take()
|
||||||
.body(val)
|
.body(val)
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,23 +324,29 @@ impl<'a> From<&'a String> for Response<Body> {
|
||||||
fn from(val: &'a String) -> Self {
|
fn from(val: &'a String) -> Self {
|
||||||
Response::builder(StatusCode::OK)
|
Response::builder(StatusCode::OK)
|
||||||
.content_type(mime::TEXT_PLAIN_UTF_8)
|
.content_type(mime::TEXT_PLAIN_UTF_8)
|
||||||
.body(val)
|
.take()
|
||||||
|
.body(Body::from_slice(val.as_bytes()))
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Bytes> for Response<Body> {
|
impl From<Bytes> for Response<Bytes> {
|
||||||
fn from(val: Bytes) -> Self {
|
fn from(val: Bytes) -> Self {
|
||||||
Response::builder(StatusCode::OK)
|
Response::builder(StatusCode::OK)
|
||||||
.content_type(mime::APPLICATION_OCTET_STREAM)
|
.content_type(mime::APPLICATION_OCTET_STREAM)
|
||||||
|
.take()
|
||||||
.body(val)
|
.body(val)
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<BytesMut> for Response<Body> {
|
impl From<BytesMut> for Response<Bytes> {
|
||||||
fn from(val: BytesMut) -> Self {
|
fn from(val: BytesMut) -> Self {
|
||||||
Response::builder(StatusCode::OK)
|
Response::builder(StatusCode::OK)
|
||||||
.content_type(mime::APPLICATION_OCTET_STREAM)
|
.content_type(mime::APPLICATION_OCTET_STREAM)
|
||||||
.body(val)
|
.take()
|
||||||
|
.body(val.freeze())
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,7 +368,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_into_response() {
|
fn test_into_response() {
|
||||||
let resp: Response<Body> = "test".into();
|
let resp: Response<_> = "test".into();
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resp.headers().get(CONTENT_TYPE).unwrap(),
|
resp.headers().get(CONTENT_TYPE).unwrap(),
|
||||||
|
@ -357,7 +377,7 @@ mod tests {
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
assert_eq!(resp.body().get_ref(), b"test");
|
assert_eq!(resp.body().get_ref(), b"test");
|
||||||
|
|
||||||
let resp: Response<Body> = b"test".as_ref().into();
|
let resp: Response<_> = b"test".as_ref().into();
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resp.headers().get(CONTENT_TYPE).unwrap(),
|
resp.headers().get(CONTENT_TYPE).unwrap(),
|
||||||
|
@ -366,7 +386,7 @@ mod tests {
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
assert_eq!(resp.body().get_ref(), b"test");
|
assert_eq!(resp.body().get_ref(), b"test");
|
||||||
|
|
||||||
let resp: Response<Body> = "test".to_owned().into();
|
let resp: Response<_> = "test".to_owned().into();
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resp.headers().get(CONTENT_TYPE).unwrap(),
|
resp.headers().get(CONTENT_TYPE).unwrap(),
|
||||||
|
@ -385,7 +405,7 @@ mod tests {
|
||||||
assert_eq!(resp.body().get_ref(), b"test");
|
assert_eq!(resp.body().get_ref(), b"test");
|
||||||
|
|
||||||
let b = Bytes::from_static(b"test");
|
let b = Bytes::from_static(b"test");
|
||||||
let resp: Response<Body> = b.into();
|
let resp: Response<_> = b.into();
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resp.headers().get(CONTENT_TYPE).unwrap(),
|
resp.headers().get(CONTENT_TYPE).unwrap(),
|
||||||
|
@ -394,8 +414,7 @@ mod tests {
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
assert_eq!(resp.body().get_ref(), b"test");
|
assert_eq!(resp.body().get_ref(), b"test");
|
||||||
|
|
||||||
let b = Bytes::from_static(b"test");
|
let resp: Response<_> = Bytes::from_static(b"test").into();
|
||||||
let resp: Response<Body> = b.into();
|
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resp.headers().get(CONTENT_TYPE).unwrap(),
|
resp.headers().get(CONTENT_TYPE).unwrap(),
|
||||||
|
@ -405,7 +424,7 @@ mod tests {
|
||||||
assert_eq!(resp.body().get_ref(), b"test");
|
assert_eq!(resp.body().get_ref(), b"test");
|
||||||
|
|
||||||
let b = BytesMut::from("test");
|
let b = BytesMut::from("test");
|
||||||
let resp: Response<Body> = b.into();
|
let resp: Response<_> = b.into();
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resp.headers().get(CONTENT_TYPE).unwrap(),
|
resp.headers().get(CONTENT_TYPE).unwrap(),
|
||||||
|
|
|
@ -2,6 +2,7 @@ use std::{
|
||||||
cell::{Ref, RefMut},
|
cell::{Ref, RefMut},
|
||||||
fmt,
|
fmt,
|
||||||
future::Future,
|
future::Future,
|
||||||
|
mem,
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
str,
|
str,
|
||||||
task::{Context, Poll},
|
task::{Context, Poll},
|
||||||
|
@ -24,8 +25,7 @@ use crate::{
|
||||||
///
|
///
|
||||||
/// This type can be used to construct an instance of `Response` through a builder-like pattern.
|
/// This type can be used to construct an instance of `Response` through a builder-like pattern.
|
||||||
pub struct ResponseBuilder {
|
pub struct ResponseBuilder {
|
||||||
head: Option<BoxedResponseHead>,
|
inner: Result<BoxedResponseHead, HttpError>,
|
||||||
err: Option<HttpError>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ResponseBuilder {
|
impl ResponseBuilder {
|
||||||
|
@ -33,14 +33,13 @@ impl ResponseBuilder {
|
||||||
/// Create response builder
|
/// Create response builder
|
||||||
pub fn new(status: StatusCode) -> Self {
|
pub fn new(status: StatusCode) -> Self {
|
||||||
ResponseBuilder {
|
ResponseBuilder {
|
||||||
head: Some(BoxedResponseHead::new(status)),
|
inner: Ok(BoxedResponseHead::new(status)),
|
||||||
err: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set HTTP status code of this response.
|
/// Set HTTP status code of this response.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn status(&mut self, status: StatusCode) -> &mut Self {
|
pub fn status(mut self, status: StatusCode) -> Self {
|
||||||
if let Some(parts) = self.inner() {
|
if let Some(parts) = self.inner() {
|
||||||
parts.status = status;
|
parts.status = status;
|
||||||
}
|
}
|
||||||
|
@ -58,7 +57,7 @@ impl ResponseBuilder {
|
||||||
/// .insert_header(("X-TEST", "value"))
|
/// .insert_header(("X-TEST", "value"))
|
||||||
/// .finish();
|
/// .finish();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn insert_header<H>(&mut self, header: H) -> &mut Self
|
pub fn insert_header<H>(mut self, header: H) -> Self
|
||||||
where
|
where
|
||||||
H: IntoHeaderPair,
|
H: IntoHeaderPair,
|
||||||
{
|
{
|
||||||
|
@ -67,7 +66,7 @@ impl ResponseBuilder {
|
||||||
Ok((key, value)) => {
|
Ok((key, value)) => {
|
||||||
parts.headers.insert(key, value);
|
parts.headers.insert(key, value);
|
||||||
}
|
}
|
||||||
Err(e) => self.err = Some(e.into()),
|
Err(err) => self.inner = Err(err.into()),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,14 +85,14 @@ impl ResponseBuilder {
|
||||||
/// .append_header(("X-TEST", "value2"))
|
/// .append_header(("X-TEST", "value2"))
|
||||||
/// .finish();
|
/// .finish();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn append_header<H>(&mut self, header: H) -> &mut Self
|
pub fn append_header<H>(mut self, header: H) -> Self
|
||||||
where
|
where
|
||||||
H: IntoHeaderPair,
|
H: IntoHeaderPair,
|
||||||
{
|
{
|
||||||
if let Some(parts) = self.inner() {
|
if let Some(parts) = self.inner() {
|
||||||
match header.try_into_header_pair() {
|
match header.try_into_header_pair() {
|
||||||
Ok((key, value)) => parts.headers.append(key, value),
|
Ok((key, value)) => parts.headers.append(key, value),
|
||||||
Err(e) => self.err = Some(e.into()),
|
Err(err) => self.inner = Err(err.into()),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +101,7 @@ impl ResponseBuilder {
|
||||||
|
|
||||||
/// Set the custom reason for the response.
|
/// Set the custom reason for the response.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn reason(&mut self, reason: &'static str) -> &mut Self {
|
pub fn reason(mut self, reason: &'static str) -> Self {
|
||||||
if let Some(parts) = self.inner() {
|
if let Some(parts) = self.inner() {
|
||||||
parts.reason = Some(reason);
|
parts.reason = Some(reason);
|
||||||
}
|
}
|
||||||
|
@ -111,7 +110,7 @@ impl ResponseBuilder {
|
||||||
|
|
||||||
/// Set connection type to KeepAlive
|
/// Set connection type to KeepAlive
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn keep_alive(&mut self) -> &mut Self {
|
pub fn keep_alive(self) -> Self {
|
||||||
if let Some(parts) = self.inner() {
|
if let Some(parts) = self.inner() {
|
||||||
parts.set_connection_type(ConnectionType::KeepAlive);
|
parts.set_connection_type(ConnectionType::KeepAlive);
|
||||||
}
|
}
|
||||||
|
@ -120,7 +119,7 @@ impl ResponseBuilder {
|
||||||
|
|
||||||
/// Set connection type to Upgrade
|
/// Set connection type to Upgrade
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn upgrade<V>(&mut self, value: V) -> &mut Self
|
pub fn upgrade<V>(mut self, value: V) -> Self
|
||||||
where
|
where
|
||||||
V: IntoHeaderValue,
|
V: IntoHeaderValue,
|
||||||
{
|
{
|
||||||
|
@ -132,12 +131,12 @@ impl ResponseBuilder {
|
||||||
self.insert_header((header::UPGRADE, value));
|
self.insert_header((header::UPGRADE, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
self
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Force close connection, even if it is marked as keep-alive
|
/// Force close connection, even if it is marked as keep-alive
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn force_close(&mut self) -> &mut Self {
|
pub fn force_close(mut self) -> Self {
|
||||||
if let Some(parts) = self.inner() {
|
if let Some(parts) = self.inner() {
|
||||||
parts.set_connection_type(ConnectionType::Close);
|
parts.set_connection_type(ConnectionType::Close);
|
||||||
}
|
}
|
||||||
|
@ -146,28 +145,29 @@ impl ResponseBuilder {
|
||||||
|
|
||||||
/// Disable chunked transfer encoding for HTTP/1.1 streaming responses.
|
/// Disable chunked transfer encoding for HTTP/1.1 streaming responses.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn no_chunking(&mut self, len: u64) -> &mut Self {
|
pub fn no_chunking(self, len: u64) -> Self {
|
||||||
let mut buf = itoa::Buffer::new();
|
let mut buf = itoa::Buffer::new();
|
||||||
self.insert_header((header::CONTENT_LENGTH, buf.format(len)));
|
let mut res = self.insert_header((header::CONTENT_LENGTH, buf.format(len)));
|
||||||
|
|
||||||
if let Some(parts) = self.inner() {
|
if let Some(head) = res.inner() {
|
||||||
parts.no_chunking(true);
|
head.no_chunking(true);
|
||||||
}
|
}
|
||||||
self
|
|
||||||
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set response content type.
|
/// Set response content type.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn content_type<V>(&mut self, value: V) -> &mut Self
|
pub fn content_type<V>(mut self, value: V) -> Self
|
||||||
where
|
where
|
||||||
V: IntoHeaderValue,
|
V: IntoHeaderValue,
|
||||||
{
|
{
|
||||||
if let Some(parts) = self.inner() {
|
if let Some(head) = self.inner() {
|
||||||
match value.try_into_value() {
|
match value.try_into_value() {
|
||||||
Ok(value) => {
|
Ok(value) => {
|
||||||
parts.headers.insert(header::CONTENT_TYPE, value);
|
head.headers.insert(header::CONTENT_TYPE, value);
|
||||||
}
|
}
|
||||||
Err(e) => self.err = Some(e.into()),
|
Err(err) => self.inner = Err(err.into()),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
|
@ -176,77 +176,74 @@ impl ResponseBuilder {
|
||||||
/// Responses extensions
|
/// Responses extensions
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn extensions(&self) -> Ref<'_, Extensions> {
|
pub fn extensions(&self) -> Ref<'_, Extensions> {
|
||||||
let head = self.head.as_ref().expect("cannot reuse response builder");
|
let head = self.inner.as_ref().expect("cannot reuse response builder");
|
||||||
head.extensions.borrow()
|
head.extensions.borrow()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mutable reference to a the response's extensions
|
/// Mutable reference to a the response's extensions
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn extensions_mut(&mut self) -> RefMut<'_, Extensions> {
|
pub fn extensions_mut(&mut self) -> RefMut<'_, Extensions> {
|
||||||
let head = self.head.as_ref().expect("cannot reuse response builder");
|
let head = self.inner.as_ref().expect("cannot reuse response builder");
|
||||||
head.extensions.borrow_mut()
|
head.extensions.borrow_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a body and generate `Response`.
|
/// Creates an owned response builder, leaving a default-ish builder in it's place.
|
||||||
///
|
///
|
||||||
/// `ResponseBuilder` can not be used after this call.
|
/// Useful under the assumption the original builder will be dropped immediately.
|
||||||
#[inline]
|
///
|
||||||
pub fn body<B: Into<Body>>(&mut self, body: B) -> Response<Body> {
|
/// If the builder contains an error, it will be passed to the new, owned builder.
|
||||||
self.message_body(body.into())
|
pub fn take(&mut self) -> ResponseBuilder {
|
||||||
|
let res = BoxedResponseHead::new(StatusCode::INTERNAL_SERVER_ERROR);
|
||||||
|
let inner = mem::replace(&mut self.inner, Ok(res));
|
||||||
|
|
||||||
|
ResponseBuilder { inner }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a body and generate `Response`.
|
/// Set a body and generate `Response`.
|
||||||
///
|
///
|
||||||
/// `ResponseBuilder` can not be used after this call.
|
/// `ResponseBuilder` can not be used after this call.
|
||||||
pub fn message_body<B>(&mut self, body: B) -> Response<B> {
|
fn with_body<B>(self, body: B) -> Result<Response<B>, Error> {
|
||||||
if let Some(e) = self.err.take() {
|
match self.inner {
|
||||||
return Response::from(Error::from(e)).into_body();
|
Ok(head) => Ok(Response {
|
||||||
}
|
head,
|
||||||
|
body: ResponseBody::Body(body),
|
||||||
let response = self.head.take().expect("cannot reuse response builder");
|
error: None,
|
||||||
|
}),
|
||||||
Response {
|
Err(err) => Err(Error::from(err)),
|
||||||
head: response,
|
|
||||||
body: ResponseBody::Body(body),
|
|
||||||
error: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a streaming body and generate `Response`.
|
/// Consume builder and generate response with given body.
|
||||||
///
|
|
||||||
/// `ResponseBuilder` can not be used after this call.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn streaming<S, E>(&mut self, stream: S) -> Response<Body>
|
pub fn body<B>(self, body: B) -> Result<Response<B>, Error> {
|
||||||
|
self.with_body(body.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Consume builder and generate response with given stream as body.
|
||||||
|
#[inline]
|
||||||
|
pub fn streaming<S, E>(self, stream: S) -> Result<Response<BodyStream<S>>, Error>
|
||||||
where
|
where
|
||||||
S: Stream<Item = Result<Bytes, E>> + Unpin + 'static,
|
S: Stream<Item = Result<Bytes, E>> + 'static,
|
||||||
E: Into<Error> + 'static,
|
E: Into<Error> + 'static,
|
||||||
{
|
{
|
||||||
self.body(Body::from_message(BodyStream::new(stream)))
|
self.body(BodyStream::new(stream))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set an empty body and generate `Response`
|
/// Consume builder and generate response with empty body.
|
||||||
///
|
|
||||||
/// `ResponseBuilder` can not be used after this call.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn finish(&mut self) -> Response<Body> {
|
pub fn finish(self) -> Result<Response<Body>, Error> {
|
||||||
self.body(Body::Empty)
|
self.body(Body::Empty)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This method construct new `ResponseBuilder`
|
/// Consume builder and generate response with empty body, converting errors into responses.
|
||||||
pub fn take(&mut self) -> ResponseBuilder {
|
#[inline]
|
||||||
ResponseBuilder {
|
pub fn complete(self) -> Response<Body> {
|
||||||
head: self.head.take(),
|
self.body(Body::Empty).into()
|
||||||
err: self.err.take(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Access to contained response when there is no error.
|
/// Access to contained response when there is no error.
|
||||||
fn inner(&mut self) -> Option<&mut ResponseHead> {
|
fn inner(&mut self) -> Option<&mut ResponseHead> {
|
||||||
if self.err.is_some() {
|
self.inner.as_mut().ok().map(|head| &mut **head)
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.head.as_mut().map(|r| &mut **r)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,8 +251,7 @@ impl ResponseBuilder {
|
||||||
impl<B> From<Response<B>> for ResponseBuilder {
|
impl<B> From<Response<B>> for ResponseBuilder {
|
||||||
fn from(res: Response<B>) -> ResponseBuilder {
|
fn from(res: Response<B>) -> ResponseBuilder {
|
||||||
ResponseBuilder {
|
ResponseBuilder {
|
||||||
head: Some(res.head),
|
inner: Ok(res.head),
|
||||||
err: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -273,10 +269,7 @@ impl<'a> From<&'a ResponseHead> for ResponseBuilder {
|
||||||
|
|
||||||
msg.no_chunking(!head.chunked());
|
msg.no_chunking(!head.chunked());
|
||||||
|
|
||||||
ResponseBuilder {
|
ResponseBuilder { inner: Ok(msg) }
|
||||||
head: Some(msg),
|
|
||||||
err: None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,13 +277,13 @@ impl Future for ResponseBuilder {
|
||||||
type Output = Result<Response<Body>, Error>;
|
type Output = Result<Response<Body>, Error>;
|
||||||
|
|
||||||
fn poll(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
|
fn poll(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
Poll::Ready(Ok(self.finish()))
|
Poll::Ready(self.take().finish())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for ResponseBuilder {
|
impl fmt::Debug for ResponseBuilder {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let head = self.head.as_ref().unwrap();
|
let head = self.inner.as_ref().unwrap();
|
||||||
|
|
||||||
let res = writeln!(
|
let res = writeln!(
|
||||||
f,
|
f,
|
||||||
|
@ -317,7 +310,7 @@ mod tests {
|
||||||
fn test_basic_builder() {
|
fn test_basic_builder() {
|
||||||
let resp = Response::builder(StatusCode::OK)
|
let resp = Response::builder(StatusCode::OK)
|
||||||
.insert_header(("X-TEST", "value"))
|
.insert_header(("X-TEST", "value"))
|
||||||
.finish();
|
.complete();
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,7 +318,7 @@ mod tests {
|
||||||
fn test_upgrade() {
|
fn test_upgrade() {
|
||||||
let resp = Response::builder(StatusCode::OK)
|
let resp = Response::builder(StatusCode::OK)
|
||||||
.upgrade("websocket")
|
.upgrade("websocket")
|
||||||
.finish();
|
.complete();
|
||||||
assert!(resp.upgrade());
|
assert!(resp.upgrade());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resp.headers().get(header::UPGRADE).unwrap(),
|
resp.headers().get(header::UPGRADE).unwrap(),
|
||||||
|
@ -335,7 +328,10 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_force_close() {
|
fn test_force_close() {
|
||||||
let resp = Response::builder(StatusCode::OK).force_close().finish();
|
let resp = Response::builder(StatusCode::OK)
|
||||||
|
.force_close()
|
||||||
|
.finish()
|
||||||
|
.unwrap();
|
||||||
assert!(!resp.keep_alive())
|
assert!(!resp.keep_alive())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,13 +339,14 @@ mod tests {
|
||||||
fn test_content_type() {
|
fn test_content_type() {
|
||||||
let resp = Response::builder(StatusCode::OK)
|
let resp = Response::builder(StatusCode::OK)
|
||||||
.content_type("text/plain")
|
.content_type("text/plain")
|
||||||
.body(Body::Empty);
|
.body(Body::Empty)
|
||||||
|
.unwrap();
|
||||||
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "text/plain")
|
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "text/plain")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_into_builder() {
|
fn test_into_builder() {
|
||||||
let mut resp: Response<Body> = "test".into();
|
let mut resp: Response<_> = "test".into();
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
|
||||||
resp.headers_mut().insert(
|
resp.headers_mut().insert(
|
||||||
|
@ -358,7 +355,7 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut builder: ResponseBuilder = resp.into();
|
let mut builder: ResponseBuilder = resp.into();
|
||||||
let resp = builder.status(StatusCode::BAD_REQUEST).finish();
|
let resp = builder.status(StatusCode::BAD_REQUEST).finish().unwrap();
|
||||||
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
|
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
let cookie = resp.headers().get_all("Cookie").next().unwrap();
|
let cookie = resp.headers().get_all("Cookie").next().unwrap();
|
||||||
|
@ -367,9 +364,11 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn response_builder_header_insert_kv() {
|
fn response_builder_header_insert_kv() {
|
||||||
let mut res = Response::builder(StatusCode::OK);
|
let res = Response::builder(StatusCode::OK)
|
||||||
res.insert_header(("Content-Type", "application/octet-stream"));
|
.insert_header(("Content-Type", "application/octet-stream"))
|
||||||
let res = res.finish();
|
.take()
|
||||||
|
.finish()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
res.headers().get("Content-Type"),
|
res.headers().get("Content-Type"),
|
||||||
|
@ -379,9 +378,11 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn response_builder_header_insert_typed() {
|
fn response_builder_header_insert_typed() {
|
||||||
let mut res = Response::builder(StatusCode::OK);
|
let res = Response::builder(StatusCode::OK)
|
||||||
res.insert_header((header::CONTENT_TYPE, mime::APPLICATION_OCTET_STREAM));
|
.insert_header((header::CONTENT_TYPE, mime::APPLICATION_OCTET_STREAM))
|
||||||
let res = res.finish();
|
.take()
|
||||||
|
.finish()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
res.headers().get("Content-Type"),
|
res.headers().get("Content-Type"),
|
||||||
|
@ -391,10 +392,12 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn response_builder_header_append_kv() {
|
fn response_builder_header_append_kv() {
|
||||||
let mut res = Response::builder(StatusCode::OK);
|
let mut res = Response::builder(StatusCode::OK)
|
||||||
res.append_header(("Content-Type", "application/octet-stream"));
|
.append_header(("Content-Type", "application/octet-stream"))
|
||||||
res.append_header(("Content-Type", "application/json"));
|
.append_header(("Content-Type", "application/json"))
|
||||||
let res = res.finish();
|
.take()
|
||||||
|
.finish()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let headers: Vec<_> = res.headers().get_all("Content-Type").cloned().collect();
|
let headers: Vec<_> = res.headers().get_all("Content-Type").cloned().collect();
|
||||||
assert_eq!(headers.len(), 2);
|
assert_eq!(headers.len(), 2);
|
||||||
|
@ -407,7 +410,7 @@ mod tests {
|
||||||
let mut res = Response::builder(StatusCode::OK);
|
let mut res = Response::builder(StatusCode::OK);
|
||||||
res.append_header((header::CONTENT_TYPE, mime::APPLICATION_OCTET_STREAM));
|
res.append_header((header::CONTENT_TYPE, mime::APPLICATION_OCTET_STREAM));
|
||||||
res.append_header((header::CONTENT_TYPE, mime::APPLICATION_JSON));
|
res.append_header((header::CONTENT_TYPE, mime::APPLICATION_JSON));
|
||||||
let res = res.finish();
|
let res = res.finish().unwrap();
|
||||||
|
|
||||||
let headers: Vec<_> = res.headers().get_all("Content-Type").cloned().collect();
|
let headers: Vec<_> = res.headers().get_all("Content-Type").cloned().collect();
|
||||||
assert_eq!(headers.len(), 2);
|
assert_eq!(headers.len(), 2);
|
||||||
|
|
|
@ -103,38 +103,50 @@ impl ResponseError for HandshakeError {
|
||||||
match self {
|
match self {
|
||||||
HandshakeError::GetMethodRequired => {
|
HandshakeError::GetMethodRequired => {
|
||||||
Response::builder(StatusCode::METHOD_NOT_ALLOWED)
|
Response::builder(StatusCode::METHOD_NOT_ALLOWED)
|
||||||
.insert_header((header::ALLOW, "GET"))
|
.insert_header((header::ALLOW, "GET"))
|
||||||
.finish()
|
.take()
|
||||||
|
.body(Body::Empty)
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
HandshakeError::NoWebsocketUpgrade => {
|
HandshakeError::NoWebsocketUpgrade => {
|
||||||
Response::builder(StatusCode::BAD_REQUEST)
|
Response::builder(StatusCode::BAD_REQUEST)
|
||||||
.reason("No WebSocket Upgrade header found")
|
.reason("No WebSocket Upgrade header found")
|
||||||
.finish()
|
.take()
|
||||||
|
.body(Body::Empty)
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
HandshakeError::NoConnectionUpgrade => {
|
HandshakeError::NoConnectionUpgrade => {
|
||||||
Response::builder(StatusCode::BAD_REQUEST)
|
Response::builder(StatusCode::BAD_REQUEST)
|
||||||
.reason("No Connection upgrade")
|
.reason("No Connection upgrade")
|
||||||
.finish()
|
.take()
|
||||||
|
.body(Body::Empty)
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
HandshakeError::NoVersionHeader => {
|
HandshakeError::NoVersionHeader => {
|
||||||
Response::builder(StatusCode::BAD_REQUEST)
|
Response::builder(StatusCode::BAD_REQUEST)
|
||||||
.reason("WebSocket version header is required")
|
.reason("WebSocket version header is required")
|
||||||
.finish()
|
.take()
|
||||||
|
.body(Body::Empty)
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
HandshakeError::UnsupportedVersion => {
|
HandshakeError::UnsupportedVersion => {
|
||||||
Response::builder(StatusCode::BAD_REQUEST)
|
Response::builder(StatusCode::BAD_REQUEST)
|
||||||
.reason("Unsupported WebSocket version")
|
.reason("Unsupported WebSocket version")
|
||||||
.finish()
|
.take()
|
||||||
|
.body(Body::Empty)
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
HandshakeError::BadWebsocketKey => {
|
HandshakeError::BadWebsocketKey => {
|
||||||
Response::builder(StatusCode::BAD_REQUEST)
|
Response::builder(StatusCode::BAD_REQUEST)
|
||||||
.reason("Handshake error")
|
.reason("Handshake error")
|
||||||
.finish()
|
.take()
|
||||||
|
.body(Body::Empty)
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -326,7 +338,7 @@ mod tests {
|
||||||
.finish();
|
.finish();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
StatusCode::SWITCHING_PROTOCOLS,
|
StatusCode::SWITCHING_PROTOCOLS,
|
||||||
handshake_response(req.head()).finish().status()
|
handshake_response(req.head()).finish().unwrap().status()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -205,7 +205,7 @@ async fn test_h2_headers() {
|
||||||
TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST ",
|
TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST ",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
ok::<_, ()>(builder.body(data.clone()))
|
ready(builder.body(data.clone()))
|
||||||
})
|
})
|
||||||
.openssl(tls_config())
|
.openssl(tls_config())
|
||||||
.map_err(|_| ())
|
.map_err(|_| ())
|
||||||
|
@ -331,8 +331,9 @@ async fn test_h2_body_length() {
|
||||||
HttpService::build()
|
HttpService::build()
|
||||||
.h2(|_| {
|
.h2(|_| {
|
||||||
let body = once(ok(Bytes::from_static(STR.as_ref())));
|
let body = once(ok(Bytes::from_static(STR.as_ref())));
|
||||||
ok::<_, ()>(
|
ready(
|
||||||
Response::builder(StatusCode::OK)
|
Response::builder(StatusCode::OK)
|
||||||
|
.take()
|
||||||
.body(SizedStream::new(STR.len() as u64, body)),
|
.body(SizedStream::new(STR.len() as u64, body)),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -355,9 +356,10 @@ async fn test_h2_body_chunked_explicit() {
|
||||||
HttpService::build()
|
HttpService::build()
|
||||||
.h2(|_| {
|
.h2(|_| {
|
||||||
let body = once(ok::<_, Error>(Bytes::from_static(STR.as_ref())));
|
let body = once(ok::<_, Error>(Bytes::from_static(STR.as_ref())));
|
||||||
ok::<_, ()>(
|
ready(
|
||||||
Response::builder(StatusCode::OK)
|
Response::builder(StatusCode::OK)
|
||||||
.insert_header((header::TRANSFER_ENCODING, "chunked"))
|
.insert_header((header::TRANSFER_ENCODING, "chunked"))
|
||||||
|
.take()
|
||||||
.streaming(body),
|
.streaming(body),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -383,9 +385,10 @@ async fn test_h2_response_http_error_handling() {
|
||||||
HttpService::build()
|
HttpService::build()
|
||||||
.h2(fn_service(|_| {
|
.h2(fn_service(|_| {
|
||||||
let broken_header = Bytes::from_static(b"\0\0\0");
|
let broken_header = Bytes::from_static(b"\0\0\0");
|
||||||
ok::<_, ()>(
|
ready(
|
||||||
Response::builder(StatusCode::OK)
|
Response::builder(StatusCode::OK)
|
||||||
.insert_header((header::CONTENT_TYPE, broken_header))
|
.insert_header((header::CONTENT_TYPE, broken_header))
|
||||||
|
.take()
|
||||||
.body(STR),
|
.body(STR),
|
||||||
)
|
)
|
||||||
}))
|
}))
|
||||||
|
|
|
@ -13,7 +13,7 @@ use actix_http::{
|
||||||
};
|
};
|
||||||
use actix_http_test::test_server;
|
use actix_http_test::test_server;
|
||||||
use actix_service::{fn_factory_with_config, fn_service};
|
use actix_service::{fn_factory_with_config, fn_service};
|
||||||
use actix_utils::future::{err, ok};
|
use actix_utils::future::{err, ok, ready};
|
||||||
|
|
||||||
use bytes::{Bytes, BytesMut};
|
use bytes::{Bytes, BytesMut};
|
||||||
use futures_core::Stream;
|
use futures_core::Stream;
|
||||||
|
@ -218,9 +218,9 @@ async fn test_h2_headers() {
|
||||||
TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST ",
|
TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST ",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
ok::<_, ()>(config.body(data.clone()))
|
ready(config.body(data.clone()))
|
||||||
})
|
})
|
||||||
.rustls(tls_config())
|
.rustls(tls_config())
|
||||||
}).await;
|
}).await;
|
||||||
|
|
||||||
let response = srv.sget("/").send().await.unwrap();
|
let response = srv.sget("/").send().await.unwrap();
|
||||||
|
@ -370,9 +370,10 @@ async fn test_h2_body_chunked_explicit() {
|
||||||
HttpService::build()
|
HttpService::build()
|
||||||
.h2(|_| {
|
.h2(|_| {
|
||||||
let body = once(ok::<_, Error>(Bytes::from_static(STR.as_ref())));
|
let body = once(ok::<_, Error>(Bytes::from_static(STR.as_ref())));
|
||||||
ok::<_, ()>(
|
ready(
|
||||||
Response::builder(StatusCode::OK)
|
Response::builder(StatusCode::OK)
|
||||||
.insert_header((header::TRANSFER_ENCODING, "chunked"))
|
.insert_header((header::TRANSFER_ENCODING, "chunked"))
|
||||||
|
.take()
|
||||||
.streaming(body),
|
.streaming(body),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -398,9 +399,10 @@ async fn test_h2_response_http_error_handling() {
|
||||||
.h2(fn_factory_with_config(|_: ()| {
|
.h2(fn_factory_with_config(|_: ()| {
|
||||||
ok::<_, ()>(fn_service(|_| {
|
ok::<_, ()>(fn_service(|_| {
|
||||||
let broken_header = Bytes::from_static(b"\0\0\0");
|
let broken_header = Bytes::from_static(b"\0\0\0");
|
||||||
ok::<_, ()>(
|
ready(
|
||||||
Response::builder(StatusCode::OK)
|
Response::builder(StatusCode::OK)
|
||||||
.insert_header((http::header::CONTENT_TYPE, broken_header))
|
.insert_header((http::header::CONTENT_TYPE, broken_header))
|
||||||
|
.take()
|
||||||
.body(STR),
|
.body(STR),
|
||||||
)
|
)
|
||||||
}))
|
}))
|
||||||
|
|
|
@ -416,7 +416,7 @@ async fn test_h1_headers() {
|
||||||
TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST ",
|
TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST ",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
ok::<_, ()>(builder.body(data.clone()))
|
ok::<_, ()>(builder.body(data.clone()).unwrap())
|
||||||
}).tcp()
|
}).tcp()
|
||||||
}).await;
|
}).await;
|
||||||
|
|
||||||
|
@ -566,9 +566,10 @@ async fn test_h1_body_chunked_explicit() {
|
||||||
HttpService::build()
|
HttpService::build()
|
||||||
.h1(|_| {
|
.h1(|_| {
|
||||||
let body = once(ok::<_, Error>(Bytes::from_static(STR.as_ref())));
|
let body = once(ok::<_, Error>(Bytes::from_static(STR.as_ref())));
|
||||||
ok::<_, ()>(
|
ready(
|
||||||
Response::builder(StatusCode::OK)
|
Response::builder(StatusCode::OK)
|
||||||
.insert_header((header::TRANSFER_ENCODING, "chunked"))
|
.insert_header((header::TRANSFER_ENCODING, "chunked"))
|
||||||
|
.take()
|
||||||
.streaming(body),
|
.streaming(body),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -601,7 +602,7 @@ async fn test_h1_body_chunked_implicit() {
|
||||||
HttpService::build()
|
HttpService::build()
|
||||||
.h1(|_| {
|
.h1(|_| {
|
||||||
let body = once(ok::<_, Error>(Bytes::from_static(STR.as_ref())));
|
let body = once(ok::<_, Error>(Bytes::from_static(STR.as_ref())));
|
||||||
ok::<_, ()>(Response::builder(StatusCode::OK).streaming(body))
|
ready(Response::builder(StatusCode::OK).streaming(body))
|
||||||
})
|
})
|
||||||
.tcp()
|
.tcp()
|
||||||
})
|
})
|
||||||
|
@ -630,9 +631,10 @@ async fn test_h1_response_http_error_handling() {
|
||||||
HttpService::build()
|
HttpService::build()
|
||||||
.h1(fn_service(|_| {
|
.h1(fn_service(|_| {
|
||||||
let broken_header = Bytes::from_static(b"\0\0\0");
|
let broken_header = Bytes::from_static(b"\0\0\0");
|
||||||
ok::<_, ()>(
|
ready(
|
||||||
Response::builder(StatusCode::OK)
|
Response::builder(StatusCode::OK)
|
||||||
.insert_header((http::header::CONTENT_TYPE, broken_header))
|
.insert_header((http::header::CONTENT_TYPE, broken_header))
|
||||||
|
.take()
|
||||||
.body(STR),
|
.body(STR),
|
||||||
)
|
)
|
||||||
}))
|
}))
|
||||||
|
|
|
@ -52,7 +52,11 @@ where
|
||||||
|
|
||||||
fn call(&self, (req, mut framed): (Request, Framed<T, h1::Codec>)) -> Self::Future {
|
fn call(&self, (req, mut framed): (Request, Framed<T, h1::Codec>)) -> Self::Future {
|
||||||
let fut = async move {
|
let fut = async move {
|
||||||
let res = ws::handshake(req.head()).unwrap().message_body(());
|
let res = ws::handshake(req.head())
|
||||||
|
.unwrap()
|
||||||
|
.finish()
|
||||||
|
.unwrap()
|
||||||
|
.set_body(());
|
||||||
|
|
||||||
framed
|
framed
|
||||||
.send((res, body::BodySize::None).into())
|
.send((res, body::BodySize::None).into())
|
||||||
|
|
|
@ -82,8 +82,8 @@ impl Responder for HttpResponseBuilder {
|
||||||
|
|
||||||
impl Responder for actix_http::ResponseBuilder {
|
impl Responder for actix_http::ResponseBuilder {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn respond_to(mut self, _: &HttpRequest) -> HttpResponse {
|
fn respond_to(self, _: &HttpRequest) -> HttpResponse {
|
||||||
HttpResponse::from(self.finish())
|
HttpResponse::from(self.complete())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue