mirror of
https://github.com/fafhrd91/actix-web
synced 2025-06-25 06:39:22 +02:00
refined error model (#2253)
This commit is contained in:
@ -1,5 +1,7 @@
|
||||
use std::convert::Infallible;
|
||||
|
||||
use actix_http::{
|
||||
http, http::StatusCode, HttpMessage, HttpService, Request, Response, ResponseError,
|
||||
body::AnyBody, http, http::StatusCode, HttpMessage, HttpService, Request, Response,
|
||||
};
|
||||
use actix_http_test::test_server;
|
||||
use actix_service::ServiceFactoryExt;
|
||||
@ -34,7 +36,7 @@ const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
|
||||
async fn test_h1_v2() {
|
||||
let srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.finish(|_| future::ok::<_, ()>(Response::ok().set_body(STR)))
|
||||
.finish(|_| future::ok::<_, Infallible>(Response::ok().set_body(STR)))
|
||||
.tcp()
|
||||
})
|
||||
.await;
|
||||
@ -62,7 +64,7 @@ async fn test_h1_v2() {
|
||||
async fn test_connection_close() {
|
||||
let srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.finish(|_| future::ok::<_, ()>(Response::ok().set_body(STR)))
|
||||
.finish(|_| future::ok::<_, Infallible>(Response::ok().set_body(STR)))
|
||||
.tcp()
|
||||
.map(|_| ())
|
||||
})
|
||||
@ -76,11 +78,11 @@ async fn test_connection_close() {
|
||||
async fn test_with_query_parameter() {
|
||||
let srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.finish(|req: Request| {
|
||||
.finish(|req: Request| async move {
|
||||
if req.uri().query().unwrap().contains("qp=") {
|
||||
future::ok::<_, ()>(Response::ok())
|
||||
Ok::<_, Infallible>(Response::ok())
|
||||
} else {
|
||||
future::ok::<_, ()>(Response::bad_request())
|
||||
Ok(Response::bad_request())
|
||||
}
|
||||
})
|
||||
.tcp()
|
||||
@ -97,9 +99,9 @@ async fn test_with_query_parameter() {
|
||||
#[display(fmt = "expect failed")]
|
||||
struct ExpectFailed;
|
||||
|
||||
impl ResponseError for ExpectFailed {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
StatusCode::EXPECTATION_FAILED
|
||||
impl From<ExpectFailed> for Response<AnyBody> {
|
||||
fn from(_: ExpectFailed) -> Self {
|
||||
Response::new(StatusCode::EXPECTATION_FAILED)
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,7 +125,7 @@ async fn test_h1_expect() {
|
||||
let str = std::str::from_utf8(&buf).unwrap();
|
||||
assert_eq!(str, "expect body");
|
||||
|
||||
Ok::<_, ()>(Response::ok())
|
||||
Ok::<_, Infallible>(Response::ok())
|
||||
})
|
||||
.tcp()
|
||||
})
|
||||
|
@ -2,16 +2,16 @@
|
||||
|
||||
extern crate tls_openssl as openssl;
|
||||
|
||||
use std::io;
|
||||
use std::{convert::Infallible, io};
|
||||
|
||||
use actix_http::{
|
||||
body::{Body, SizedStream},
|
||||
body::{AnyBody, Body, SizedStream},
|
||||
error::PayloadError,
|
||||
http::{
|
||||
header::{self, HeaderName, HeaderValue},
|
||||
Method, StatusCode, Version,
|
||||
},
|
||||
Error, HttpMessage, HttpService, Request, Response, ResponseError,
|
||||
Error, HttpMessage, HttpService, Request, Response,
|
||||
};
|
||||
use actix_http_test::test_server;
|
||||
use actix_service::{fn_service, ServiceFactoryExt};
|
||||
@ -136,7 +136,7 @@ async fn test_h2_content_length() {
|
||||
StatusCode::OK,
|
||||
StatusCode::NOT_FOUND,
|
||||
];
|
||||
ok::<_, ()>(Response::new(statuses[idx]))
|
||||
ok::<_, Infallible>(Response::new(statuses[idx]))
|
||||
})
|
||||
.openssl(tls_config())
|
||||
.map_err(|_| ())
|
||||
@ -206,7 +206,7 @@ async fn test_h2_headers() {
|
||||
TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST ",
|
||||
));
|
||||
}
|
||||
ok::<_, ()>(builder.body(data.clone()))
|
||||
ok::<_, Infallible>(builder.body(data.clone()))
|
||||
})
|
||||
.openssl(tls_config())
|
||||
.map_err(|_| ())
|
||||
@ -246,7 +246,7 @@ const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
|
||||
async fn test_h2_body2() {
|
||||
let mut srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(|_| ok::<_, ()>(Response::ok().set_body(STR)))
|
||||
.h2(|_| ok::<_, Infallible>(Response::ok().set_body(STR)))
|
||||
.openssl(tls_config())
|
||||
.map_err(|_| ())
|
||||
})
|
||||
@ -264,7 +264,7 @@ async fn test_h2_body2() {
|
||||
async fn test_h2_head_empty() {
|
||||
let mut srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.finish(|_| ok::<_, ()>(Response::ok().set_body(STR)))
|
||||
.finish(|_| ok::<_, Infallible>(Response::ok().set_body(STR)))
|
||||
.openssl(tls_config())
|
||||
.map_err(|_| ())
|
||||
})
|
||||
@ -288,7 +288,7 @@ async fn test_h2_head_empty() {
|
||||
async fn test_h2_head_binary() {
|
||||
let mut srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(|_| ok::<_, ()>(Response::ok().set_body(STR)))
|
||||
.h2(|_| ok::<_, Infallible>(Response::ok().set_body(STR)))
|
||||
.openssl(tls_config())
|
||||
.map_err(|_| ())
|
||||
})
|
||||
@ -311,7 +311,7 @@ async fn test_h2_head_binary() {
|
||||
async fn test_h2_head_binary2() {
|
||||
let srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(|_| ok::<_, ()>(Response::ok().set_body(STR)))
|
||||
.h2(|_| ok::<_, Infallible>(Response::ok().set_body(STR)))
|
||||
.openssl(tls_config())
|
||||
.map_err(|_| ())
|
||||
})
|
||||
@ -330,9 +330,12 @@ async fn test_h2_head_binary2() {
|
||||
async fn test_h2_body_length() {
|
||||
let mut srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(|_| {
|
||||
let body = once(ok(Bytes::from_static(STR.as_ref())));
|
||||
ok::<_, ()>(
|
||||
.h2(|_| async {
|
||||
let body = once(async {
|
||||
Ok::<_, Infallible>(Bytes::from_static(STR.as_ref()))
|
||||
});
|
||||
|
||||
Ok::<_, Infallible>(
|
||||
Response::ok().set_body(SizedStream::new(STR.len() as u64, body)),
|
||||
)
|
||||
})
|
||||
@ -355,7 +358,7 @@ async fn test_h2_body_chunked_explicit() {
|
||||
HttpService::build()
|
||||
.h2(|_| {
|
||||
let body = once(ok::<_, Error>(Bytes::from_static(STR.as_ref())));
|
||||
ok::<_, ()>(
|
||||
ok::<_, Infallible>(
|
||||
Response::build(StatusCode::OK)
|
||||
.insert_header((header::TRANSFER_ENCODING, "chunked"))
|
||||
.streaming(body),
|
||||
@ -383,7 +386,7 @@ async fn test_h2_response_http_error_handling() {
|
||||
HttpService::build()
|
||||
.h2(fn_service(|_| {
|
||||
let broken_header = Bytes::from_static(b"\0\0\0");
|
||||
ok::<_, ()>(
|
||||
ok::<_, Infallible>(
|
||||
Response::build(StatusCode::OK)
|
||||
.insert_header((header::CONTENT_TYPE, broken_header))
|
||||
.body(STR),
|
||||
@ -399,16 +402,19 @@ async fn test_h2_response_http_error_handling() {
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).await.unwrap();
|
||||
assert_eq!(bytes, Bytes::from_static(b"failed to parse header value"));
|
||||
assert_eq!(
|
||||
bytes,
|
||||
Bytes::from_static(b"error processing HTTP: failed to parse header value")
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Debug, Display, Error)]
|
||||
#[display(fmt = "error")]
|
||||
struct BadRequest;
|
||||
|
||||
impl ResponseError for BadRequest {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
StatusCode::BAD_REQUEST
|
||||
impl From<BadRequest> for Response<AnyBody> {
|
||||
fn from(err: BadRequest) -> Self {
|
||||
Response::build(StatusCode::BAD_REQUEST).body(err.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
@ -439,7 +445,7 @@ async fn test_h2_on_connect() {
|
||||
})
|
||||
.h2(|req: Request| {
|
||||
assert!(req.extensions().contains::<isize>());
|
||||
ok::<_, ()>(Response::ok())
|
||||
ok::<_, Infallible>(Response::ok())
|
||||
})
|
||||
.openssl(tls_config())
|
||||
.map_err(|_| ())
|
||||
|
@ -2,14 +2,21 @@
|
||||
|
||||
extern crate tls_rustls as rustls;
|
||||
|
||||
use std::{
|
||||
convert::Infallible,
|
||||
io::{self, BufReader, Write},
|
||||
net::{SocketAddr, TcpStream as StdTcpStream},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use actix_http::{
|
||||
body::{Body, SizedStream},
|
||||
body::{AnyBody, Body, SizedStream},
|
||||
error::PayloadError,
|
||||
http::{
|
||||
header::{self, HeaderName, HeaderValue},
|
||||
Method, StatusCode, Version,
|
||||
},
|
||||
Error, HttpService, Request, Response, ResponseError,
|
||||
Error, HttpService, Request, Response,
|
||||
};
|
||||
use actix_http_test::test_server;
|
||||
use actix_service::{fn_factory_with_config, fn_service};
|
||||
@ -24,12 +31,6 @@ use rustls::{
|
||||
};
|
||||
use webpki::DNSNameRef;
|
||||
|
||||
use std::{
|
||||
io::{self, BufReader, Write},
|
||||
net::{SocketAddr, TcpStream as StdTcpStream},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
async fn load_body<S>(mut stream: S) -> Result<BytesMut, PayloadError>
|
||||
where
|
||||
S: Stream<Item = Result<Bytes, PayloadError>> + Unpin,
|
||||
@ -173,7 +174,7 @@ async fn test_h2_content_length() {
|
||||
StatusCode::OK,
|
||||
StatusCode::NOT_FOUND,
|
||||
];
|
||||
ok::<_, ()>(Response::new(statuses[indx]))
|
||||
ok::<_, Infallible>(Response::new(statuses[indx]))
|
||||
})
|
||||
.rustls(tls_config())
|
||||
})
|
||||
@ -242,7 +243,7 @@ async fn test_h2_headers() {
|
||||
TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST ",
|
||||
));
|
||||
}
|
||||
ok::<_, ()>(config.body(data.clone()))
|
||||
ok::<_, Infallible>(config.body(data.clone()))
|
||||
})
|
||||
.rustls(tls_config())
|
||||
}).await;
|
||||
@ -281,7 +282,7 @@ const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
|
||||
async fn test_h2_body2() {
|
||||
let mut srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(|_| ok::<_, ()>(Response::ok().set_body(STR)))
|
||||
.h2(|_| ok::<_, Infallible>(Response::ok().set_body(STR)))
|
||||
.rustls(tls_config())
|
||||
})
|
||||
.await;
|
||||
@ -298,7 +299,7 @@ async fn test_h2_body2() {
|
||||
async fn test_h2_head_empty() {
|
||||
let mut srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.finish(|_| ok::<_, ()>(Response::ok().set_body(STR)))
|
||||
.finish(|_| ok::<_, Infallible>(Response::ok().set_body(STR)))
|
||||
.rustls(tls_config())
|
||||
})
|
||||
.await;
|
||||
@ -324,7 +325,7 @@ async fn test_h2_head_empty() {
|
||||
async fn test_h2_head_binary() {
|
||||
let mut srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(|_| ok::<_, ()>(Response::ok().set_body(STR)))
|
||||
.h2(|_| ok::<_, Infallible>(Response::ok().set_body(STR)))
|
||||
.rustls(tls_config())
|
||||
})
|
||||
.await;
|
||||
@ -349,7 +350,7 @@ async fn test_h2_head_binary() {
|
||||
async fn test_h2_head_binary2() {
|
||||
let srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(|_| ok::<_, ()>(Response::ok().set_body(STR)))
|
||||
.h2(|_| ok::<_, Infallible>(Response::ok().set_body(STR)))
|
||||
.rustls(tls_config())
|
||||
})
|
||||
.await;
|
||||
@ -371,8 +372,8 @@ async fn test_h2_body_length() {
|
||||
let mut srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(|_| {
|
||||
let body = once(ok(Bytes::from_static(STR.as_ref())));
|
||||
ok::<_, ()>(
|
||||
let body = once(ok::<_, Infallible>(Bytes::from_static(STR.as_ref())));
|
||||
ok::<_, Infallible>(
|
||||
Response::ok().set_body(SizedStream::new(STR.len() as u64, body)),
|
||||
)
|
||||
})
|
||||
@ -394,7 +395,7 @@ async fn test_h2_body_chunked_explicit() {
|
||||
HttpService::build()
|
||||
.h2(|_| {
|
||||
let body = once(ok::<_, Error>(Bytes::from_static(STR.as_ref())));
|
||||
ok::<_, ()>(
|
||||
ok::<_, Infallible>(
|
||||
Response::build(StatusCode::OK)
|
||||
.insert_header((header::TRANSFER_ENCODING, "chunked"))
|
||||
.streaming(body),
|
||||
@ -420,9 +421,9 @@ async fn test_h2_response_http_error_handling() {
|
||||
let mut srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(fn_factory_with_config(|_: ()| {
|
||||
ok::<_, ()>(fn_service(|_| {
|
||||
ok::<_, Infallible>(fn_service(|_| {
|
||||
let broken_header = Bytes::from_static(b"\0\0\0");
|
||||
ok::<_, ()>(
|
||||
ok::<_, Infallible>(
|
||||
Response::build(StatusCode::OK)
|
||||
.insert_header((http::header::CONTENT_TYPE, broken_header))
|
||||
.body(STR),
|
||||
@ -438,16 +439,19 @@ async fn test_h2_response_http_error_handling() {
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).await.unwrap();
|
||||
assert_eq!(bytes, Bytes::from_static(b"failed to parse header value"));
|
||||
assert_eq!(
|
||||
bytes,
|
||||
Bytes::from_static(b"error processing HTTP: failed to parse header value")
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Debug, Display, Error)]
|
||||
#[display(fmt = "error")]
|
||||
struct BadRequest;
|
||||
|
||||
impl ResponseError for BadRequest {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
StatusCode::BAD_REQUEST
|
||||
impl From<BadRequest> for Response<AnyBody> {
|
||||
fn from(_: BadRequest) -> Self {
|
||||
Response::bad_request().set_body(AnyBody::from("error"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,21 +1,25 @@
|
||||
use std::io::{Read, Write};
|
||||
use std::time::Duration;
|
||||
use std::{net, thread};
|
||||
use std::{
|
||||
convert::Infallible,
|
||||
io::{Read, Write},
|
||||
net, thread,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use actix_http::{
|
||||
body::{Body, SizedStream},
|
||||
http::{self, header, StatusCode},
|
||||
Error, HttpService, KeepAlive, Request, Response,
|
||||
body::{AnyBody, Body, SizedStream},
|
||||
header, http, Error, HttpMessage, HttpService, KeepAlive, Request, Response,
|
||||
StatusCode,
|
||||
};
|
||||
use actix_http::{HttpMessage, ResponseError};
|
||||
use actix_http_test::test_server;
|
||||
use actix_rt::time::sleep;
|
||||
use actix_service::fn_service;
|
||||
use actix_utils::future::{err, ok, ready};
|
||||
use bytes::Bytes;
|
||||
use derive_more::{Display, Error};
|
||||
use futures_util::stream::{once, StreamExt as _};
|
||||
use futures_util::FutureExt as _;
|
||||
use futures_util::{
|
||||
stream::{once, StreamExt as _},
|
||||
FutureExt as _,
|
||||
};
|
||||
use regex::Regex;
|
||||
|
||||
#[actix_rt::test]
|
||||
@ -27,7 +31,7 @@ async fn test_h1() {
|
||||
.client_disconnect(1000)
|
||||
.h1(|req: Request| {
|
||||
assert!(req.peer_addr().is_some());
|
||||
ok::<_, ()>(Response::ok())
|
||||
ok::<_, Infallible>(Response::ok())
|
||||
})
|
||||
.tcp()
|
||||
})
|
||||
@ -47,7 +51,7 @@ async fn test_h1_2() {
|
||||
.finish(|req: Request| {
|
||||
assert!(req.peer_addr().is_some());
|
||||
assert_eq!(req.version(), http::Version::HTTP_11);
|
||||
ok::<_, ()>(Response::ok())
|
||||
ok::<_, Infallible>(Response::ok())
|
||||
})
|
||||
.tcp()
|
||||
})
|
||||
@ -61,9 +65,9 @@ async fn test_h1_2() {
|
||||
#[display(fmt = "expect failed")]
|
||||
struct ExpectFailed;
|
||||
|
||||
impl ResponseError for ExpectFailed {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
StatusCode::PRECONDITION_FAILED
|
||||
impl From<ExpectFailed> for Response<AnyBody> {
|
||||
fn from(_: ExpectFailed) -> Self {
|
||||
Response::new(StatusCode::EXPECTATION_FAILED)
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,7 +82,7 @@ async fn test_expect_continue() {
|
||||
err(ExpectFailed)
|
||||
}
|
||||
}))
|
||||
.finish(|_| ok::<_, ()>(Response::ok()))
|
||||
.finish(|_| ok::<_, Infallible>(Response::ok()))
|
||||
.tcp()
|
||||
})
|
||||
.await;
|
||||
@ -87,7 +91,7 @@ async fn test_expect_continue() {
|
||||
let _ = stream.write_all(b"GET /test HTTP/1.1\r\nexpect: 100-continue\r\n\r\n");
|
||||
let mut data = String::new();
|
||||
let _ = stream.read_to_string(&mut data);
|
||||
assert!(data.starts_with("HTTP/1.1 412 Precondition Failed\r\ncontent-length"));
|
||||
assert!(data.starts_with("HTTP/1.1 417 Expectation Failed\r\ncontent-length"));
|
||||
|
||||
let mut stream = net::TcpStream::connect(srv.addr()).unwrap();
|
||||
let _ = stream.write_all(b"GET /test?yes= HTTP/1.1\r\nexpect: 100-continue\r\n\r\n");
|
||||
@ -109,7 +113,7 @@ async fn test_expect_continue_h1() {
|
||||
}
|
||||
})
|
||||
}))
|
||||
.h1(fn_service(|_| ok::<_, ()>(Response::ok())))
|
||||
.h1(fn_service(|_| ok::<_, Infallible>(Response::ok())))
|
||||
.tcp()
|
||||
})
|
||||
.await;
|
||||
@ -118,7 +122,7 @@ async fn test_expect_continue_h1() {
|
||||
let _ = stream.write_all(b"GET /test HTTP/1.1\r\nexpect: 100-continue\r\n\r\n");
|
||||
let mut data = String::new();
|
||||
let _ = stream.read_to_string(&mut data);
|
||||
assert!(data.starts_with("HTTP/1.1 412 Precondition Failed\r\ncontent-length"));
|
||||
assert!(data.starts_with("HTTP/1.1 417 Expectation Failed\r\ncontent-length"));
|
||||
|
||||
let mut stream = net::TcpStream::connect(srv.addr()).unwrap();
|
||||
let _ = stream.write_all(b"GET /test?yes= HTTP/1.1\r\nexpect: 100-continue\r\n\r\n");
|
||||
@ -190,7 +194,7 @@ async fn test_slow_request() {
|
||||
let srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.client_timeout(100)
|
||||
.finish(|_| ok::<_, ()>(Response::ok()))
|
||||
.finish(|_| ok::<_, Infallible>(Response::ok()))
|
||||
.tcp()
|
||||
})
|
||||
.await;
|
||||
@ -206,7 +210,7 @@ async fn test_slow_request() {
|
||||
async fn test_http1_malformed_request() {
|
||||
let srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.h1(|_| ok::<_, ()>(Response::ok()))
|
||||
.h1(|_| ok::<_, Infallible>(Response::ok()))
|
||||
.tcp()
|
||||
})
|
||||
.await;
|
||||
@ -222,7 +226,7 @@ async fn test_http1_malformed_request() {
|
||||
async fn test_http1_keepalive() {
|
||||
let srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.h1(|_| ok::<_, ()>(Response::ok()))
|
||||
.h1(|_| ok::<_, Infallible>(Response::ok()))
|
||||
.tcp()
|
||||
})
|
||||
.await;
|
||||
@ -244,7 +248,7 @@ async fn test_http1_keepalive_timeout() {
|
||||
let srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.keep_alive(1)
|
||||
.h1(|_| ok::<_, ()>(Response::ok()))
|
||||
.h1(|_| ok::<_, Infallible>(Response::ok()))
|
||||
.tcp()
|
||||
})
|
||||
.await;
|
||||
@ -265,7 +269,7 @@ async fn test_http1_keepalive_timeout() {
|
||||
async fn test_http1_keepalive_close() {
|
||||
let srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.h1(|_| ok::<_, ()>(Response::ok()))
|
||||
.h1(|_| ok::<_, Infallible>(Response::ok()))
|
||||
.tcp()
|
||||
})
|
||||
.await;
|
||||
@ -286,7 +290,7 @@ async fn test_http1_keepalive_close() {
|
||||
async fn test_http10_keepalive_default_close() {
|
||||
let srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.h1(|_| ok::<_, ()>(Response::ok()))
|
||||
.h1(|_| ok::<_, Infallible>(Response::ok()))
|
||||
.tcp()
|
||||
})
|
||||
.await;
|
||||
@ -306,7 +310,7 @@ async fn test_http10_keepalive_default_close() {
|
||||
async fn test_http10_keepalive() {
|
||||
let srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.h1(|_| ok::<_, ()>(Response::ok()))
|
||||
.h1(|_| ok::<_, Infallible>(Response::ok()))
|
||||
.tcp()
|
||||
})
|
||||
.await;
|
||||
@ -334,7 +338,7 @@ async fn test_http1_keepalive_disabled() {
|
||||
let srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.keep_alive(KeepAlive::Disabled)
|
||||
.h1(|_| ok::<_, ()>(Response::ok()))
|
||||
.h1(|_| ok::<_, Infallible>(Response::ok()))
|
||||
.tcp()
|
||||
})
|
||||
.await;
|
||||
@ -369,7 +373,7 @@ async fn test_content_length() {
|
||||
StatusCode::OK,
|
||||
StatusCode::NOT_FOUND,
|
||||
];
|
||||
ok::<_, ()>(Response::new(statuses[indx]))
|
||||
ok::<_, Infallible>(Response::new(statuses[indx]))
|
||||
})
|
||||
.tcp()
|
||||
})
|
||||
@ -424,7 +428,7 @@ async fn test_h1_headers() {
|
||||
TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST ",
|
||||
));
|
||||
}
|
||||
ok::<_, ()>(builder.body(data.clone()))
|
||||
ok::<_, Infallible>(builder.body(data.clone()))
|
||||
}).tcp()
|
||||
}).await;
|
||||
|
||||
@ -462,7 +466,7 @@ const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
|
||||
async fn test_h1_body() {
|
||||
let mut srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.h1(|_| ok::<_, ()>(Response::ok().set_body(STR)))
|
||||
.h1(|_| ok::<_, Infallible>(Response::ok().set_body(STR)))
|
||||
.tcp()
|
||||
})
|
||||
.await;
|
||||
@ -479,7 +483,7 @@ async fn test_h1_body() {
|
||||
async fn test_h1_head_empty() {
|
||||
let mut srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.h1(|_| ok::<_, ()>(Response::ok().set_body(STR)))
|
||||
.h1(|_| ok::<_, Infallible>(Response::ok().set_body(STR)))
|
||||
.tcp()
|
||||
})
|
||||
.await;
|
||||
@ -504,7 +508,7 @@ async fn test_h1_head_empty() {
|
||||
async fn test_h1_head_binary() {
|
||||
let mut srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.h1(|_| ok::<_, ()>(Response::ok().set_body(STR)))
|
||||
.h1(|_| ok::<_, Infallible>(Response::ok().set_body(STR)))
|
||||
.tcp()
|
||||
})
|
||||
.await;
|
||||
@ -529,7 +533,7 @@ async fn test_h1_head_binary() {
|
||||
async fn test_h1_head_binary2() {
|
||||
let srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.h1(|_| ok::<_, ()>(Response::ok().set_body(STR)))
|
||||
.h1(|_| ok::<_, Infallible>(Response::ok().set_body(STR)))
|
||||
.tcp()
|
||||
})
|
||||
.await;
|
||||
@ -551,8 +555,8 @@ async fn test_h1_body_length() {
|
||||
let mut srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.h1(|_| {
|
||||
let body = once(ok(Bytes::from_static(STR.as_ref())));
|
||||
ok::<_, ()>(
|
||||
let body = once(ok::<_, Infallible>(Bytes::from_static(STR.as_ref())));
|
||||
ok::<_, Infallible>(
|
||||
Response::ok().set_body(SizedStream::new(STR.len() as u64, body)),
|
||||
)
|
||||
})
|
||||
@ -574,7 +578,7 @@ async fn test_h1_body_chunked_explicit() {
|
||||
HttpService::build()
|
||||
.h1(|_| {
|
||||
let body = once(ok::<_, Error>(Bytes::from_static(STR.as_ref())));
|
||||
ok::<_, ()>(
|
||||
ok::<_, Infallible>(
|
||||
Response::build(StatusCode::OK)
|
||||
.insert_header((header::TRANSFER_ENCODING, "chunked"))
|
||||
.streaming(body),
|
||||
@ -609,7 +613,7 @@ async fn test_h1_body_chunked_implicit() {
|
||||
HttpService::build()
|
||||
.h1(|_| {
|
||||
let body = once(ok::<_, Error>(Bytes::from_static(STR.as_ref())));
|
||||
ok::<_, ()>(Response::build(StatusCode::OK).streaming(body))
|
||||
ok::<_, Infallible>(Response::build(StatusCode::OK).streaming(body))
|
||||
})
|
||||
.tcp()
|
||||
})
|
||||
@ -638,7 +642,7 @@ async fn test_h1_response_http_error_handling() {
|
||||
HttpService::build()
|
||||
.h1(fn_service(|_| {
|
||||
let broken_header = Bytes::from_static(b"\0\0\0");
|
||||
ok::<_, ()>(
|
||||
ok::<_, Infallible>(
|
||||
Response::build(StatusCode::OK)
|
||||
.insert_header((http::header::CONTENT_TYPE, broken_header))
|
||||
.body(STR),
|
||||
@ -653,16 +657,19 @@ async fn test_h1_response_http_error_handling() {
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).await.unwrap();
|
||||
assert_eq!(bytes, Bytes::from_static(b"failed to parse header value"));
|
||||
assert_eq!(
|
||||
bytes,
|
||||
Bytes::from_static(b"error processing HTTP: failed to parse header value")
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Debug, Display, Error)]
|
||||
#[display(fmt = "error")]
|
||||
struct BadRequest;
|
||||
|
||||
impl ResponseError for BadRequest {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
StatusCode::BAD_REQUEST
|
||||
impl From<BadRequest> for Response<AnyBody> {
|
||||
fn from(_: BadRequest) -> Self {
|
||||
Response::bad_request().set_body(AnyBody::from("error"))
|
||||
}
|
||||
}
|
||||
|
||||
@ -692,7 +699,7 @@ async fn test_h1_on_connect() {
|
||||
})
|
||||
.h1(|req: Request| {
|
||||
assert!(req.extensions().contains::<isize>());
|
||||
ok::<_, ()>(Response::ok())
|
||||
ok::<_, Infallible>(Response::ok())
|
||||
})
|
||||
.tcp()
|
||||
})
|
||||
|
@ -1,11 +1,12 @@
|
||||
use std::{
|
||||
cell::Cell,
|
||||
convert::Infallible,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
use actix_codec::{AsyncRead, AsyncWrite, Framed};
|
||||
use actix_http::{
|
||||
body::BodySize,
|
||||
body::{AnyBody, BodySize},
|
||||
h1,
|
||||
ws::{self, CloseCode, Frame, Item, Message},
|
||||
Error, HttpService, Request, Response,
|
||||
@ -13,6 +14,7 @@ use actix_http::{
|
||||
use actix_http_test::test_server;
|
||||
use actix_service::{fn_factory, Service};
|
||||
use bytes::Bytes;
|
||||
use derive_more::{Display, Error, From};
|
||||
use futures_core::future::LocalBoxFuture;
|
||||
use futures_util::{SinkExt as _, StreamExt as _};
|
||||
|
||||
@ -33,12 +35,39 @@ impl WsService {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Display, Error, From)]
|
||||
enum WsServiceError {
|
||||
#[display(fmt = "http error")]
|
||||
Http(actix_http::Error),
|
||||
|
||||
#[display(fmt = "ws handshake error")]
|
||||
Ws(actix_http::ws::HandshakeError),
|
||||
|
||||
#[display(fmt = "io error")]
|
||||
Io(std::io::Error),
|
||||
|
||||
#[display(fmt = "dispatcher error")]
|
||||
Dispatcher,
|
||||
}
|
||||
|
||||
impl From<WsServiceError> for Response<AnyBody> {
|
||||
fn from(err: WsServiceError) -> Self {
|
||||
match err {
|
||||
WsServiceError::Http(err) => err.into(),
|
||||
WsServiceError::Ws(err) => err.into(),
|
||||
WsServiceError::Io(_err) => unreachable!(),
|
||||
WsServiceError::Dispatcher => Response::internal_server_error()
|
||||
.set_body(AnyBody::from(format!("{}", err))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Service<(Request, Framed<T, h1::Codec>)> for WsService
|
||||
where
|
||||
T: AsyncRead + AsyncWrite + Unpin + 'static,
|
||||
{
|
||||
type Response = ();
|
||||
type Error = Error;
|
||||
type Error = WsServiceError;
|
||||
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
|
||||
|
||||
fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
@ -56,7 +85,9 @@ where
|
||||
|
||||
let framed = framed.replace_codec(ws::Codec::new());
|
||||
|
||||
ws::Dispatcher::with(framed, service).await?;
|
||||
ws::Dispatcher::with(framed, service)
|
||||
.await
|
||||
.map_err(|_| WsServiceError::Dispatcher)?;
|
||||
|
||||
Ok(())
|
||||
})
|
||||
@ -72,7 +103,7 @@ async fn service(msg: Frame) -> Result<Message, Error> {
|
||||
Frame::Binary(bin) => Message::Binary(bin),
|
||||
Frame::Continuation(item) => Message::Continuation(item),
|
||||
Frame::Close(reason) => Message::Close(reason),
|
||||
_ => return Err(Error::from(ws::ProtocolError::BadOpCode)),
|
||||
_ => return Err(ws::ProtocolError::BadOpCode.into()),
|
||||
};
|
||||
|
||||
Ok(msg)
|
||||
@ -82,8 +113,10 @@ async fn service(msg: Frame) -> Result<Message, Error> {
|
||||
async fn test_simple() {
|
||||
let mut srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.upgrade(fn_factory(|| async { Ok::<_, ()>(WsService::new()) }))
|
||||
.finish(|_| async { Ok::<_, ()>(Response::not_found()) })
|
||||
.upgrade(fn_factory(|| async {
|
||||
Ok::<_, Infallible>(WsService::new())
|
||||
}))
|
||||
.finish(|_| async { Ok::<_, Infallible>(Response::not_found()) })
|
||||
.tcp()
|
||||
})
|
||||
.await;
|
||||
|
Reference in New Issue
Block a user