mirror of
https://github.com/fafhrd91/actix-web
synced 2025-06-24 22:37:35 +02:00
drop unpin constraint
This commit is contained in:
@ -1,9 +1,9 @@
|
||||
use actix_service::NewService;
|
||||
use actix_service::ServiceFactory;
|
||||
use bytes::Bytes;
|
||||
use futures::future::{self, ok};
|
||||
|
||||
use actix_http::{http, HttpService, Request, Response};
|
||||
use actix_http_test::TestServer;
|
||||
use actix_http_test::{block_on, TestServer};
|
||||
|
||||
const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
@ -29,55 +29,63 @@ const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
|
||||
|
||||
#[test]
|
||||
fn test_h1_v2() {
|
||||
env_logger::init();
|
||||
let mut srv = TestServer::new(move || {
|
||||
HttpService::build().finish(|_| future::ok::<_, ()>(Response::Ok().body(STR)))
|
||||
});
|
||||
let response = srv.block_on(srv.get("/").send()).unwrap();
|
||||
assert!(response.status().is_success());
|
||||
block_on(async {
|
||||
let srv = TestServer::start(move || {
|
||||
HttpService::build()
|
||||
.finish(|_| future::ok::<_, ()>(Response::Ok().body(STR)))
|
||||
});
|
||||
|
||||
let request = srv.get("/").header("x-test", "111").send();
|
||||
let response = srv.block_on(request).unwrap();
|
||||
assert!(response.status().is_success());
|
||||
let response = srv.get("/").send().await.unwrap();
|
||||
assert!(response.status().is_success());
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).unwrap();
|
||||
assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
|
||||
let request = srv.get("/").header("x-test", "111").send();
|
||||
let mut response = request.await.unwrap();
|
||||
assert!(response.status().is_success());
|
||||
|
||||
let response = srv.block_on(srv.post("/").send()).unwrap();
|
||||
assert!(response.status().is_success());
|
||||
// read response
|
||||
let bytes = response.body().await.unwrap();
|
||||
assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).unwrap();
|
||||
assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
|
||||
let mut response = srv.post("/").send().await.unwrap();
|
||||
assert!(response.status().is_success());
|
||||
|
||||
// read response
|
||||
let bytes = response.body().await.unwrap();
|
||||
assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_connection_close() {
|
||||
let mut srv = TestServer::new(move || {
|
||||
HttpService::build()
|
||||
.finish(|_| ok::<_, ()>(Response::Ok().body(STR)))
|
||||
.map(|_| ())
|
||||
});
|
||||
let response = srv.block_on(srv.get("/").force_close().send()).unwrap();
|
||||
assert!(response.status().is_success());
|
||||
block_on(async {
|
||||
let srv = TestServer::start(move || {
|
||||
HttpService::build()
|
||||
.finish(|_| ok::<_, ()>(Response::Ok().body(STR)))
|
||||
.map(|_| ())
|
||||
});
|
||||
|
||||
let response = srv.get("/").force_close().send().await.unwrap();
|
||||
assert!(response.status().is_success());
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_with_query_parameter() {
|
||||
let mut srv = TestServer::new(move || {
|
||||
HttpService::build()
|
||||
.finish(|req: Request| {
|
||||
if req.uri().query().unwrap().contains("qp=") {
|
||||
ok::<_, ()>(Response::Ok().finish())
|
||||
} else {
|
||||
ok::<_, ()>(Response::BadRequest().finish())
|
||||
}
|
||||
})
|
||||
.map(|_| ())
|
||||
});
|
||||
block_on(async {
|
||||
let srv = TestServer::start(move || {
|
||||
HttpService::build()
|
||||
.finish(|req: Request| {
|
||||
if req.uri().query().unwrap().contains("qp=") {
|
||||
ok::<_, ()>(Response::Ok().finish())
|
||||
} else {
|
||||
ok::<_, ()>(Response::BadRequest().finish())
|
||||
}
|
||||
})
|
||||
.map(|_| ())
|
||||
});
|
||||
|
||||
let request = srv.request(http::Method::GET, srv.url("/?qp=5")).send();
|
||||
let response = srv.block_on(request).unwrap();
|
||||
assert!(response.status().is_success());
|
||||
let request = srv.request(http::Method::GET, srv.url("/?qp=5"));
|
||||
let response = request.send().await.unwrap();
|
||||
assert!(response.status().is_success());
|
||||
})
|
||||
}
|
||||
|
545
actix-http/tests/test_openssl.rs
Normal file
545
actix-http/tests/test_openssl.rs
Normal file
@ -0,0 +1,545 @@
|
||||
#![cfg(feature = "openssl")]
|
||||
use std::io;
|
||||
|
||||
use actix_codec::{AsyncRead, AsyncWrite};
|
||||
use actix_http_test::{block_on, TestServer};
|
||||
use actix_server::ssl::OpensslAcceptor;
|
||||
use actix_server_config::ServerConfig;
|
||||
use actix_service::{factory_fn_cfg, pipeline_factory, service_fn2, ServiceFactory};
|
||||
|
||||
use bytes::{Bytes, BytesMut};
|
||||
use futures::future::{err, ok, ready};
|
||||
use futures::stream::{once, Stream, StreamExt};
|
||||
use open_ssl::ssl::{AlpnError, SslAcceptor, SslFiletype, SslMethod};
|
||||
|
||||
use actix_http::error::{ErrorBadRequest, PayloadError};
|
||||
use actix_http::http::header::{self, HeaderName, HeaderValue};
|
||||
use actix_http::http::{Method, StatusCode, Version};
|
||||
use actix_http::httpmessage::HttpMessage;
|
||||
use actix_http::{body, Error, HttpService, Request, Response};
|
||||
|
||||
async fn load_body<S>(stream: S) -> Result<BytesMut, PayloadError>
|
||||
where
|
||||
S: Stream<Item = Result<Bytes, PayloadError>>,
|
||||
{
|
||||
let body = stream
|
||||
.map(|res| match res {
|
||||
Ok(chunk) => chunk,
|
||||
Err(_) => panic!(),
|
||||
})
|
||||
.fold(BytesMut::new(), move |mut body, chunk| {
|
||||
body.extend_from_slice(&chunk);
|
||||
ready(body)
|
||||
})
|
||||
.await;
|
||||
|
||||
Ok(body)
|
||||
}
|
||||
|
||||
fn ssl_acceptor<T: AsyncRead + AsyncWrite>() -> io::Result<OpensslAcceptor<T, ()>> {
|
||||
// load ssl keys
|
||||
let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
|
||||
builder
|
||||
.set_private_key_file("../tests/key.pem", SslFiletype::PEM)
|
||||
.unwrap();
|
||||
builder
|
||||
.set_certificate_chain_file("../tests/cert.pem")
|
||||
.unwrap();
|
||||
builder.set_alpn_select_callback(|_, protos| {
|
||||
const H2: &[u8] = b"\x02h2";
|
||||
if protos.windows(3).any(|window| window == H2) {
|
||||
Ok(b"h2")
|
||||
} else {
|
||||
Err(AlpnError::NOACK)
|
||||
}
|
||||
});
|
||||
builder.set_alpn_protos(b"\x02h2")?;
|
||||
Ok(OpensslAcceptor::new(builder.build()))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2() -> io::Result<()> {
|
||||
block_on(async {
|
||||
let openssl = ssl_acceptor()?;
|
||||
let srv = TestServer::start(move || {
|
||||
pipeline_factory(
|
||||
openssl
|
||||
.clone()
|
||||
.map_err(|e| println!("Openssl error: {}", e)),
|
||||
)
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|_| ok::<_, Error>(Response::Ok().finish()))
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.sget("/").send().await.unwrap();
|
||||
assert!(response.status().is_success());
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_1() -> io::Result<()> {
|
||||
block_on(async {
|
||||
let openssl = ssl_acceptor()?;
|
||||
let srv = TestServer::start(move || {
|
||||
pipeline_factory(
|
||||
openssl
|
||||
.clone()
|
||||
.map_err(|e| println!("Openssl error: {}", e)),
|
||||
)
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.finish(|req: Request| {
|
||||
assert!(req.peer_addr().is_some());
|
||||
assert_eq!(req.version(), Version::HTTP_2);
|
||||
ok::<_, Error>(Response::Ok().finish())
|
||||
})
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.sget("/").send().await.unwrap();
|
||||
assert!(response.status().is_success());
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_body() -> io::Result<()> {
|
||||
block_on(async {
|
||||
let data = "HELLOWORLD".to_owned().repeat(64 * 1024);
|
||||
let openssl = ssl_acceptor()?;
|
||||
let mut srv = TestServer::start(move || {
|
||||
pipeline_factory(
|
||||
openssl
|
||||
.clone()
|
||||
.map_err(|e| println!("Openssl error: {}", e)),
|
||||
)
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|mut req: Request<_>| {
|
||||
async move {
|
||||
let body = load_body(req.take_payload()).await?;
|
||||
Ok::<_, Error>(Response::Ok().body(body))
|
||||
}
|
||||
})
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.sget("/").send_body(data.clone()).await.unwrap();
|
||||
assert!(response.status().is_success());
|
||||
|
||||
let body = srv.load_body(response).await.unwrap();
|
||||
assert_eq!(&body, data.as_bytes());
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_content_length() {
|
||||
block_on(async {
|
||||
let openssl = ssl_acceptor().unwrap();
|
||||
|
||||
let srv = TestServer::start(move || {
|
||||
pipeline_factory(
|
||||
openssl
|
||||
.clone()
|
||||
.map_err(|e| println!("Openssl error: {}", e)),
|
||||
)
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|req: Request| {
|
||||
let indx: usize = req.uri().path()[1..].parse().unwrap();
|
||||
let statuses = [
|
||||
StatusCode::NO_CONTENT,
|
||||
StatusCode::CONTINUE,
|
||||
StatusCode::SWITCHING_PROTOCOLS,
|
||||
StatusCode::PROCESSING,
|
||||
StatusCode::OK,
|
||||
StatusCode::NOT_FOUND,
|
||||
];
|
||||
ok::<_, ()>(Response::new(statuses[indx]))
|
||||
})
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let header = HeaderName::from_static("content-length");
|
||||
let value = HeaderValue::from_static("0");
|
||||
|
||||
{
|
||||
for i in 0..4 {
|
||||
let req = srv
|
||||
.request(Method::GET, srv.surl(&format!("/{}", i)))
|
||||
.send();
|
||||
let response = req.await.unwrap();
|
||||
assert_eq!(response.headers().get(&header), None);
|
||||
|
||||
let req = srv
|
||||
.request(Method::HEAD, srv.surl(&format!("/{}", i)))
|
||||
.send();
|
||||
let response = req.await.unwrap();
|
||||
assert_eq!(response.headers().get(&header), None);
|
||||
}
|
||||
|
||||
for i in 4..6 {
|
||||
let req = srv
|
||||
.request(Method::GET, srv.surl(&format!("/{}", i)))
|
||||
.send();
|
||||
let response = req.await.unwrap();
|
||||
assert_eq!(response.headers().get(&header), Some(&value));
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_headers() {
|
||||
block_on(async {
|
||||
let data = STR.repeat(10);
|
||||
let data2 = data.clone();
|
||||
let openssl = ssl_acceptor().unwrap();
|
||||
|
||||
let mut srv = TestServer::start(move || {
|
||||
let data = data.clone();
|
||||
pipeline_factory(openssl
|
||||
.clone()
|
||||
.map_err(|e| println!("Openssl error: {}", e)))
|
||||
.and_then(
|
||||
HttpService::build().h2(move |_| {
|
||||
let mut builder = Response::Ok();
|
||||
for idx in 0..90 {
|
||||
builder.header(
|
||||
format!("X-TEST-{}", idx).as_str(),
|
||||
"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 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 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 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 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 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 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()))
|
||||
}).map_err(|_| ()))
|
||||
});
|
||||
|
||||
let response = srv.sget("/").send().await.unwrap();
|
||||
assert!(response.status().is_success());
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).await.unwrap();
|
||||
assert_eq!(bytes, Bytes::from(data2));
|
||||
})
|
||||
}
|
||||
|
||||
const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World";
|
||||
|
||||
#[test]
|
||||
fn test_h2_body2() {
|
||||
block_on(async {
|
||||
let openssl = ssl_acceptor().unwrap();
|
||||
let mut srv = TestServer::start(move || {
|
||||
pipeline_factory(
|
||||
openssl
|
||||
.clone()
|
||||
.map_err(|e| println!("Openssl error: {}", e)),
|
||||
)
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|_| ok::<_, ()>(Response::Ok().body(STR)))
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.sget("/").send().await.unwrap();
|
||||
assert!(response.status().is_success());
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).await.unwrap();
|
||||
assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_head_empty() {
|
||||
block_on(async {
|
||||
let openssl = ssl_acceptor().unwrap();
|
||||
let mut srv = TestServer::start(move || {
|
||||
pipeline_factory(
|
||||
openssl
|
||||
.clone()
|
||||
.map_err(|e| println!("Openssl error: {}", e)),
|
||||
)
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.finish(|_| ok::<_, ()>(Response::Ok().body(STR)))
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.shead("/").send().await.unwrap();
|
||||
assert!(response.status().is_success());
|
||||
assert_eq!(response.version(), Version::HTTP_2);
|
||||
|
||||
{
|
||||
let len = response.headers().get(header::CONTENT_LENGTH).unwrap();
|
||||
assert_eq!(format!("{}", STR.len()), len.to_str().unwrap());
|
||||
}
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).await.unwrap();
|
||||
assert!(bytes.is_empty());
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_head_binary() {
|
||||
block_on(async {
|
||||
let openssl = ssl_acceptor().unwrap();
|
||||
let mut srv = TestServer::start(move || {
|
||||
pipeline_factory(
|
||||
openssl
|
||||
.clone()
|
||||
.map_err(|e| println!("Openssl error: {}", e)),
|
||||
)
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|_| {
|
||||
ok::<_, ()>(
|
||||
Response::Ok().content_length(STR.len() as u64).body(STR),
|
||||
)
|
||||
})
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.shead("/").send().await.unwrap();
|
||||
assert!(response.status().is_success());
|
||||
|
||||
{
|
||||
let len = response.headers().get(header::CONTENT_LENGTH).unwrap();
|
||||
assert_eq!(format!("{}", STR.len()), len.to_str().unwrap());
|
||||
}
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).await.unwrap();
|
||||
assert!(bytes.is_empty());
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_head_binary2() {
|
||||
block_on(async {
|
||||
let openssl = ssl_acceptor().unwrap();
|
||||
let srv = TestServer::start(move || {
|
||||
pipeline_factory(
|
||||
openssl
|
||||
.clone()
|
||||
.map_err(|e| println!("Openssl error: {}", e)),
|
||||
)
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|_| ok::<_, ()>(Response::Ok().body(STR)))
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.shead("/").send().await.unwrap();
|
||||
assert!(response.status().is_success());
|
||||
|
||||
{
|
||||
let len = response.headers().get(header::CONTENT_LENGTH).unwrap();
|
||||
assert_eq!(format!("{}", STR.len()), len.to_str().unwrap());
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_body_length() {
|
||||
block_on(async {
|
||||
let openssl = ssl_acceptor().unwrap();
|
||||
let mut srv = TestServer::start(move || {
|
||||
pipeline_factory(
|
||||
openssl
|
||||
.clone()
|
||||
.map_err(|e| println!("Openssl error: {}", e)),
|
||||
)
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|_| {
|
||||
let body = once(ok(Bytes::from_static(STR.as_ref())));
|
||||
ok::<_, ()>(
|
||||
Response::Ok()
|
||||
.body(body::SizedStream::new(STR.len() as u64, body)),
|
||||
)
|
||||
})
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.sget("/").send().await.unwrap();
|
||||
assert!(response.status().is_success());
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).await.unwrap();
|
||||
assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_body_chunked_explicit() {
|
||||
block_on(async {
|
||||
let openssl = ssl_acceptor().unwrap();
|
||||
let mut srv = TestServer::start(move || {
|
||||
pipeline_factory(
|
||||
openssl
|
||||
.clone()
|
||||
.map_err(|e| println!("Openssl error: {}", e)),
|
||||
)
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|_| {
|
||||
let body =
|
||||
once(ok::<_, Error>(Bytes::from_static(STR.as_ref())));
|
||||
ok::<_, ()>(
|
||||
Response::Ok()
|
||||
.header(header::TRANSFER_ENCODING, "chunked")
|
||||
.streaming(body),
|
||||
)
|
||||
})
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.sget("/").send().await.unwrap();
|
||||
assert!(response.status().is_success());
|
||||
assert!(!response.headers().contains_key(header::TRANSFER_ENCODING));
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).await.unwrap();
|
||||
|
||||
// decode
|
||||
assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_response_http_error_handling() {
|
||||
block_on(async {
|
||||
let openssl = ssl_acceptor().unwrap();
|
||||
|
||||
let mut srv = TestServer::start(move || {
|
||||
pipeline_factory(
|
||||
openssl
|
||||
.clone()
|
||||
.map_err(|e| println!("Openssl error: {}", e)),
|
||||
)
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(factory_fn_cfg(|_: &ServerConfig| {
|
||||
ok::<_, ()>(service_fn2(|_| {
|
||||
let broken_header = Bytes::from_static(b"\0\0\0");
|
||||
ok::<_, ()>(
|
||||
Response::Ok()
|
||||
.header(header::CONTENT_TYPE, broken_header)
|
||||
.body(STR),
|
||||
)
|
||||
}))
|
||||
}))
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.sget("/").send().await.unwrap();
|
||||
assert_eq!(response.status(), StatusCode::INTERNAL_SERVER_ERROR);
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).await.unwrap();
|
||||
assert_eq!(bytes, Bytes::from_static(b"failed to parse header value"));
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_service_error() {
|
||||
block_on(async {
|
||||
let openssl = ssl_acceptor().unwrap();
|
||||
|
||||
let mut srv = TestServer::start(move || {
|
||||
pipeline_factory(
|
||||
openssl
|
||||
.clone()
|
||||
.map_err(|e| println!("Openssl error: {}", e)),
|
||||
)
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|_| err::<Response, Error>(ErrorBadRequest("error")))
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.sget("/").send().await.unwrap();
|
||||
assert_eq!(response.status(), StatusCode::BAD_REQUEST);
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).await.unwrap();
|
||||
assert_eq!(bytes, Bytes::from_static(b"error"));
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_on_connect() {
|
||||
block_on(async {
|
||||
let openssl = ssl_acceptor().unwrap();
|
||||
|
||||
let srv = TestServer::start(move || {
|
||||
pipeline_factory(
|
||||
openssl
|
||||
.clone()
|
||||
.map_err(|e| println!("Openssl error: {}", e)),
|
||||
)
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.on_connect(|_| 10usize)
|
||||
.h2(|req: Request| {
|
||||
assert!(req.extensions().contains::<usize>());
|
||||
ok::<_, ()>(Response::Ok().finish())
|
||||
})
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.sget("/").send().await.unwrap();
|
||||
assert!(response.status().is_success());
|
||||
})
|
||||
}
|
474
actix-http/tests/test_rustls.rs
Normal file
474
actix-http/tests/test_rustls.rs
Normal file
@ -0,0 +1,474 @@
|
||||
#![cfg(feature = "rustls")]
|
||||
use actix_codec::{AsyncRead, AsyncWrite};
|
||||
use actix_http::error::PayloadError;
|
||||
use actix_http::http::header::{self, HeaderName, HeaderValue};
|
||||
use actix_http::http::{Method, StatusCode, Version};
|
||||
use actix_http::{body, error, Error, HttpService, Request, Response};
|
||||
use actix_http_test::{block_on, TestServer};
|
||||
use actix_server::ssl::RustlsAcceptor;
|
||||
use actix_server_config::ServerConfig;
|
||||
use actix_service::{factory_fn_cfg, pipeline_factory, service_fn2, ServiceFactory};
|
||||
|
||||
use bytes::{Bytes, BytesMut};
|
||||
use futures::future::{self, err, ok};
|
||||
use futures::stream::{once, Stream, StreamExt};
|
||||
use rust_tls::{
|
||||
internal::pemfile::{certs, pkcs8_private_keys},
|
||||
NoClientAuth, ServerConfig as RustlsServerConfig,
|
||||
};
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::{self, BufReader};
|
||||
|
||||
async fn load_body<S>(mut stream: S) -> Result<BytesMut, PayloadError>
|
||||
where
|
||||
S: Stream<Item = Result<Bytes, PayloadError>> + Unpin,
|
||||
{
|
||||
let mut body = BytesMut::new();
|
||||
while let Some(item) = stream.next().await {
|
||||
body.extend_from_slice(&item?)
|
||||
}
|
||||
Ok(body)
|
||||
}
|
||||
|
||||
fn ssl_acceptor<T: AsyncRead + AsyncWrite>() -> io::Result<RustlsAcceptor<T, ()>> {
|
||||
// load ssl keys
|
||||
let mut config = RustlsServerConfig::new(NoClientAuth::new());
|
||||
let cert_file = &mut BufReader::new(File::open("../tests/cert.pem").unwrap());
|
||||
let key_file = &mut BufReader::new(File::open("../tests/key.pem").unwrap());
|
||||
let cert_chain = certs(cert_file).unwrap();
|
||||
let mut keys = pkcs8_private_keys(key_file).unwrap();
|
||||
config.set_single_cert(cert_chain, keys.remove(0)).unwrap();
|
||||
|
||||
let protos = vec![b"h2".to_vec()];
|
||||
config.set_protocols(&protos);
|
||||
Ok(RustlsAcceptor::new(config))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2() -> io::Result<()> {
|
||||
block_on(async {
|
||||
let rustls = ssl_acceptor()?;
|
||||
let srv = TestServer::start(move || {
|
||||
pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e)))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|_| future::ok::<_, Error>(Response::Ok().finish()))
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.sget("/").send().await.unwrap();
|
||||
assert!(response.status().is_success());
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_1() -> io::Result<()> {
|
||||
block_on(async {
|
||||
let rustls = ssl_acceptor()?;
|
||||
let srv = TestServer::start(move || {
|
||||
pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e)))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.finish(|req: Request| {
|
||||
assert!(req.peer_addr().is_some());
|
||||
assert_eq!(req.version(), Version::HTTP_2);
|
||||
future::ok::<_, Error>(Response::Ok().finish())
|
||||
})
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.sget("/").send().await.unwrap();
|
||||
assert!(response.status().is_success());
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_body1() -> io::Result<()> {
|
||||
block_on(async {
|
||||
let data = "HELLOWORLD".to_owned().repeat(64 * 1024);
|
||||
let rustls = ssl_acceptor()?;
|
||||
let mut srv = TestServer::start(move || {
|
||||
pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e)))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|mut req: Request<_>| {
|
||||
async move {
|
||||
let body = load_body(req.take_payload()).await?;
|
||||
Ok::<_, Error>(Response::Ok().body(body))
|
||||
}
|
||||
})
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.sget("/").send_body(data.clone()).await.unwrap();
|
||||
assert!(response.status().is_success());
|
||||
|
||||
let body = srv.load_body(response).await.unwrap();
|
||||
assert_eq!(&body, data.as_bytes());
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_content_length() {
|
||||
block_on(async {
|
||||
let rustls = ssl_acceptor().unwrap();
|
||||
|
||||
let srv = TestServer::start(move || {
|
||||
pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e)))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|req: Request| {
|
||||
let indx: usize = req.uri().path()[1..].parse().unwrap();
|
||||
let statuses = [
|
||||
StatusCode::NO_CONTENT,
|
||||
StatusCode::CONTINUE,
|
||||
StatusCode::SWITCHING_PROTOCOLS,
|
||||
StatusCode::PROCESSING,
|
||||
StatusCode::OK,
|
||||
StatusCode::NOT_FOUND,
|
||||
];
|
||||
future::ok::<_, ()>(Response::new(statuses[indx]))
|
||||
})
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let header = HeaderName::from_static("content-length");
|
||||
let value = HeaderValue::from_static("0");
|
||||
|
||||
{
|
||||
for i in 0..4 {
|
||||
let req = srv
|
||||
.request(Method::GET, srv.surl(&format!("/{}", i)))
|
||||
.send();
|
||||
let response = req.await.unwrap();
|
||||
assert_eq!(response.headers().get(&header), None);
|
||||
|
||||
let req = srv
|
||||
.request(Method::HEAD, srv.surl(&format!("/{}", i)))
|
||||
.send();
|
||||
let response = req.await.unwrap();
|
||||
assert_eq!(response.headers().get(&header), None);
|
||||
}
|
||||
|
||||
for i in 4..6 {
|
||||
let req = srv
|
||||
.request(Method::GET, srv.surl(&format!("/{}", i)))
|
||||
.send();
|
||||
let response = req.await.unwrap();
|
||||
assert_eq!(response.headers().get(&header), Some(&value));
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_headers() {
|
||||
block_on(async {
|
||||
let data = STR.repeat(10);
|
||||
let data2 = data.clone();
|
||||
let rustls = ssl_acceptor().unwrap();
|
||||
|
||||
let mut srv = TestServer::start(move || {
|
||||
let data = data.clone();
|
||||
pipeline_factory(rustls
|
||||
.clone()
|
||||
.map_err(|e| println!("Rustls error: {}", e)))
|
||||
.and_then(
|
||||
HttpService::build().h2(move |_| {
|
||||
let mut config = Response::Ok();
|
||||
for idx in 0..90 {
|
||||
config.header(
|
||||
format!("X-TEST-{}", idx).as_str(),
|
||||
"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 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 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 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 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 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 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 ",
|
||||
);
|
||||
}
|
||||
future::ok::<_, ()>(config.body(data.clone()))
|
||||
}).map_err(|_| ()))
|
||||
});
|
||||
|
||||
let response = srv.sget("/").send().await.unwrap();
|
||||
assert!(response.status().is_success());
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).await.unwrap();
|
||||
assert_eq!(bytes, Bytes::from(data2));
|
||||
})
|
||||
}
|
||||
|
||||
const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World";
|
||||
|
||||
#[test]
|
||||
fn test_h2_body2() {
|
||||
block_on(async {
|
||||
let rustls = ssl_acceptor().unwrap();
|
||||
let mut srv = TestServer::start(move || {
|
||||
pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e)))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|_| future::ok::<_, ()>(Response::Ok().body(STR)))
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.sget("/").send().await.unwrap();
|
||||
assert!(response.status().is_success());
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).await.unwrap();
|
||||
assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_head_empty() {
|
||||
block_on(async {
|
||||
let rustls = ssl_acceptor().unwrap();
|
||||
let mut srv = TestServer::start(move || {
|
||||
pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e)))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.finish(|_| ok::<_, ()>(Response::Ok().body(STR)))
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.shead("/").send().await.unwrap();
|
||||
assert!(response.status().is_success());
|
||||
assert_eq!(response.version(), Version::HTTP_2);
|
||||
|
||||
{
|
||||
let len = response
|
||||
.headers()
|
||||
.get(http::header::CONTENT_LENGTH)
|
||||
.unwrap();
|
||||
assert_eq!(format!("{}", STR.len()), len.to_str().unwrap());
|
||||
}
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).await.unwrap();
|
||||
assert!(bytes.is_empty());
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_head_binary() {
|
||||
block_on(async {
|
||||
let rustls = ssl_acceptor().unwrap();
|
||||
let mut srv = TestServer::start(move || {
|
||||
pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e)))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|_| {
|
||||
ok::<_, ()>(
|
||||
Response::Ok()
|
||||
.content_length(STR.len() as u64)
|
||||
.body(STR),
|
||||
)
|
||||
})
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.shead("/").send().await.unwrap();
|
||||
assert!(response.status().is_success());
|
||||
|
||||
{
|
||||
let len = response
|
||||
.headers()
|
||||
.get(http::header::CONTENT_LENGTH)
|
||||
.unwrap();
|
||||
assert_eq!(format!("{}", STR.len()), len.to_str().unwrap());
|
||||
}
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).await.unwrap();
|
||||
assert!(bytes.is_empty());
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_head_binary2() {
|
||||
block_on(async {
|
||||
let rustls = ssl_acceptor().unwrap();
|
||||
let srv = TestServer::start(move || {
|
||||
pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e)))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|_| ok::<_, ()>(Response::Ok().body(STR)))
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.shead("/").send().await.unwrap();
|
||||
assert!(response.status().is_success());
|
||||
|
||||
{
|
||||
let len = response
|
||||
.headers()
|
||||
.get(http::header::CONTENT_LENGTH)
|
||||
.unwrap();
|
||||
assert_eq!(format!("{}", STR.len()), len.to_str().unwrap());
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_body_length() {
|
||||
block_on(async {
|
||||
let rustls = ssl_acceptor().unwrap();
|
||||
let mut srv = TestServer::start(move || {
|
||||
pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e)))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|_| {
|
||||
let body = once(ok(Bytes::from_static(STR.as_ref())));
|
||||
ok::<_, ()>(
|
||||
Response::Ok().body(body::SizedStream::new(
|
||||
STR.len() as u64,
|
||||
body,
|
||||
)),
|
||||
)
|
||||
})
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.sget("/").send().await.unwrap();
|
||||
assert!(response.status().is_success());
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).await.unwrap();
|
||||
assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_body_chunked_explicit() {
|
||||
block_on(async {
|
||||
let rustls = ssl_acceptor().unwrap();
|
||||
let mut srv = TestServer::start(move || {
|
||||
pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e)))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|_| {
|
||||
let body =
|
||||
once(ok::<_, Error>(Bytes::from_static(STR.as_ref())));
|
||||
ok::<_, ()>(
|
||||
Response::Ok()
|
||||
.header(header::TRANSFER_ENCODING, "chunked")
|
||||
.streaming(body),
|
||||
)
|
||||
})
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.sget("/").send().await.unwrap();
|
||||
assert!(response.status().is_success());
|
||||
assert!(!response.headers().contains_key(header::TRANSFER_ENCODING));
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).await.unwrap();
|
||||
|
||||
// decode
|
||||
assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_response_http_error_handling() {
|
||||
block_on(async {
|
||||
let rustls = ssl_acceptor().unwrap();
|
||||
|
||||
let mut srv = TestServer::start(move || {
|
||||
pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e)))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(factory_fn_cfg(|_: &ServerConfig| {
|
||||
ok::<_, ()>(service_fn2(|_| {
|
||||
let broken_header = Bytes::from_static(b"\0\0\0");
|
||||
ok::<_, ()>(
|
||||
Response::Ok()
|
||||
.header(
|
||||
http::header::CONTENT_TYPE,
|
||||
broken_header,
|
||||
)
|
||||
.body(STR),
|
||||
)
|
||||
}))
|
||||
}))
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.sget("/").send().await.unwrap();
|
||||
assert_eq!(response.status(), http::StatusCode::INTERNAL_SERVER_ERROR);
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).await.unwrap();
|
||||
assert_eq!(bytes, Bytes::from_static(b"failed to parse header value"));
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_service_error() {
|
||||
block_on(async {
|
||||
let rustls = ssl_acceptor().unwrap();
|
||||
|
||||
let mut srv = TestServer::start(move || {
|
||||
pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e)))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|_| err::<Response, Error>(error::ErrorBadRequest("error")))
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.sget("/").send().await.unwrap();
|
||||
assert_eq!(response.status(), http::StatusCode::BAD_REQUEST);
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).await.unwrap();
|
||||
assert_eq!(bytes, Bytes::from_static(b"error"));
|
||||
})
|
||||
}
|
@ -1,462 +0,0 @@
|
||||
#![cfg(feature = "rust-tls")]
|
||||
use actix_codec::{AsyncRead, AsyncWrite};
|
||||
use actix_http::error::PayloadError;
|
||||
use actix_http::http::header::{self, HeaderName, HeaderValue};
|
||||
use actix_http::http::{Method, StatusCode, Version};
|
||||
use actix_http::{body, error, Error, HttpService, Request, Response};
|
||||
use actix_http_test::TestServer;
|
||||
use actix_server::ssl::RustlsAcceptor;
|
||||
use actix_server_config::ServerConfig;
|
||||
use actix_service::{new_service_cfg, NewService};
|
||||
|
||||
use bytes::{Bytes, BytesMut};
|
||||
use futures::future::{self, ok, Future};
|
||||
use futures::stream::{once, Stream};
|
||||
use rustls::{
|
||||
internal::pemfile::{certs, pkcs8_private_keys},
|
||||
NoClientAuth, ServerConfig as RustlsServerConfig,
|
||||
};
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::{BufReader, Result};
|
||||
|
||||
fn load_body<S>(stream: S) -> impl Future<Item = BytesMut, Error = PayloadError>
|
||||
where
|
||||
S: Stream<Item = Bytes, Error = PayloadError>,
|
||||
{
|
||||
stream.fold(BytesMut::new(), move |mut body, chunk| {
|
||||
body.extend_from_slice(&chunk);
|
||||
Ok::<_, PayloadError>(body)
|
||||
})
|
||||
}
|
||||
|
||||
fn ssl_acceptor<T: AsyncRead + AsyncWrite>() -> Result<RustlsAcceptor<T, ()>> {
|
||||
// load ssl keys
|
||||
let mut config = RustlsServerConfig::new(NoClientAuth::new());
|
||||
let cert_file = &mut BufReader::new(File::open("../tests/cert.pem").unwrap());
|
||||
let key_file = &mut BufReader::new(File::open("../tests/key.pem").unwrap());
|
||||
let cert_chain = certs(cert_file).unwrap();
|
||||
let mut keys = pkcs8_private_keys(key_file).unwrap();
|
||||
config.set_single_cert(cert_chain, keys.remove(0)).unwrap();
|
||||
|
||||
let protos = vec![b"h2".to_vec()];
|
||||
config.set_protocols(&protos);
|
||||
Ok(RustlsAcceptor::new(config))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2() -> Result<()> {
|
||||
let rustls = ssl_acceptor()?;
|
||||
let mut srv = TestServer::new(move || {
|
||||
rustls
|
||||
.clone()
|
||||
.map_err(|e| println!("Rustls error: {}", e))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|_| future::ok::<_, Error>(Response::Ok().finish()))
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.block_on(srv.sget("/").send()).unwrap();
|
||||
assert!(response.status().is_success());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_1() -> Result<()> {
|
||||
let rustls = ssl_acceptor()?;
|
||||
let mut srv = TestServer::new(move || {
|
||||
rustls
|
||||
.clone()
|
||||
.map_err(|e| println!("Rustls error: {}", e))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.finish(|req: Request| {
|
||||
assert!(req.peer_addr().is_some());
|
||||
assert_eq!(req.version(), Version::HTTP_2);
|
||||
future::ok::<_, Error>(Response::Ok().finish())
|
||||
})
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.block_on(srv.sget("/").send()).unwrap();
|
||||
assert!(response.status().is_success());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_body() -> Result<()> {
|
||||
let data = "HELLOWORLD".to_owned().repeat(64 * 1024);
|
||||
let rustls = ssl_acceptor()?;
|
||||
let mut srv = TestServer::new(move || {
|
||||
rustls
|
||||
.clone()
|
||||
.map_err(|e| println!("Rustls error: {}", e))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|mut req: Request<_>| {
|
||||
load_body(req.take_payload())
|
||||
.and_then(|body| Ok(Response::Ok().body(body)))
|
||||
})
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.block_on(srv.sget("/").send_body(data.clone())).unwrap();
|
||||
assert!(response.status().is_success());
|
||||
|
||||
let body = srv.load_body(response).unwrap();
|
||||
assert_eq!(&body, data.as_bytes());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_content_length() {
|
||||
let rustls = ssl_acceptor().unwrap();
|
||||
|
||||
let mut srv = TestServer::new(move || {
|
||||
rustls
|
||||
.clone()
|
||||
.map_err(|e| println!("Rustls error: {}", e))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|req: Request| {
|
||||
let indx: usize = req.uri().path()[1..].parse().unwrap();
|
||||
let statuses = [
|
||||
StatusCode::NO_CONTENT,
|
||||
StatusCode::CONTINUE,
|
||||
StatusCode::SWITCHING_PROTOCOLS,
|
||||
StatusCode::PROCESSING,
|
||||
StatusCode::OK,
|
||||
StatusCode::NOT_FOUND,
|
||||
];
|
||||
future::ok::<_, ()>(Response::new(statuses[indx]))
|
||||
})
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let header = HeaderName::from_static("content-length");
|
||||
let value = HeaderValue::from_static("0");
|
||||
|
||||
{
|
||||
for i in 0..4 {
|
||||
let req = srv
|
||||
.request(Method::GET, srv.surl(&format!("/{}", i)))
|
||||
.send();
|
||||
let response = srv.block_on(req).unwrap();
|
||||
assert_eq!(response.headers().get(&header), None);
|
||||
|
||||
let req = srv
|
||||
.request(Method::HEAD, srv.surl(&format!("/{}", i)))
|
||||
.send();
|
||||
let response = srv.block_on(req).unwrap();
|
||||
assert_eq!(response.headers().get(&header), None);
|
||||
}
|
||||
|
||||
for i in 4..6 {
|
||||
let req = srv
|
||||
.request(Method::GET, srv.surl(&format!("/{}", i)))
|
||||
.send();
|
||||
let response = srv.block_on(req).unwrap();
|
||||
assert_eq!(response.headers().get(&header), Some(&value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_headers() {
|
||||
let data = STR.repeat(10);
|
||||
let data2 = data.clone();
|
||||
let rustls = ssl_acceptor().unwrap();
|
||||
|
||||
let mut srv = TestServer::new(move || {
|
||||
let data = data.clone();
|
||||
rustls
|
||||
.clone()
|
||||
.map_err(|e| println!("Rustls error: {}", e))
|
||||
.and_then(
|
||||
HttpService::build().h2(move |_| {
|
||||
let mut config = Response::Ok();
|
||||
for idx in 0..90 {
|
||||
config.header(
|
||||
format!("X-TEST-{}", idx).as_str(),
|
||||
"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 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 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 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 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 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 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 ",
|
||||
);
|
||||
}
|
||||
future::ok::<_, ()>(config.body(data.clone()))
|
||||
}).map_err(|_| ()))
|
||||
});
|
||||
|
||||
let response = srv.block_on(srv.sget("/").send()).unwrap();
|
||||
assert!(response.status().is_success());
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).unwrap();
|
||||
assert_eq!(bytes, Bytes::from(data2));
|
||||
}
|
||||
|
||||
const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World";
|
||||
|
||||
#[test]
|
||||
fn test_h2_body2() {
|
||||
let rustls = ssl_acceptor().unwrap();
|
||||
let mut srv = TestServer::new(move || {
|
||||
rustls
|
||||
.clone()
|
||||
.map_err(|e| println!("Rustls error: {}", e))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|_| future::ok::<_, ()>(Response::Ok().body(STR)))
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.block_on(srv.sget("/").send()).unwrap();
|
||||
assert!(response.status().is_success());
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).unwrap();
|
||||
assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_head_empty() {
|
||||
let rustls = ssl_acceptor().unwrap();
|
||||
let mut srv = TestServer::new(move || {
|
||||
rustls
|
||||
.clone()
|
||||
.map_err(|e| println!("Rustls error: {}", e))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.finish(|_| ok::<_, ()>(Response::Ok().body(STR)))
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.block_on(srv.shead("/").send()).unwrap();
|
||||
assert!(response.status().is_success());
|
||||
assert_eq!(response.version(), Version::HTTP_2);
|
||||
|
||||
{
|
||||
let len = response
|
||||
.headers()
|
||||
.get(http::header::CONTENT_LENGTH)
|
||||
.unwrap();
|
||||
assert_eq!(format!("{}", STR.len()), len.to_str().unwrap());
|
||||
}
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).unwrap();
|
||||
assert!(bytes.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_head_binary() {
|
||||
let rustls = ssl_acceptor().unwrap();
|
||||
let mut srv = TestServer::new(move || {
|
||||
rustls
|
||||
.clone()
|
||||
.map_err(|e| println!("Rustls error: {}", e))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|_| {
|
||||
ok::<_, ()>(
|
||||
Response::Ok().content_length(STR.len() as u64).body(STR),
|
||||
)
|
||||
})
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.block_on(srv.shead("/").send()).unwrap();
|
||||
assert!(response.status().is_success());
|
||||
|
||||
{
|
||||
let len = response
|
||||
.headers()
|
||||
.get(http::header::CONTENT_LENGTH)
|
||||
.unwrap();
|
||||
assert_eq!(format!("{}", STR.len()), len.to_str().unwrap());
|
||||
}
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).unwrap();
|
||||
assert!(bytes.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_head_binary2() {
|
||||
let rustls = ssl_acceptor().unwrap();
|
||||
let mut srv = TestServer::new(move || {
|
||||
rustls
|
||||
.clone()
|
||||
.map_err(|e| println!("Rustls error: {}", e))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|_| ok::<_, ()>(Response::Ok().body(STR)))
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.block_on(srv.shead("/").send()).unwrap();
|
||||
assert!(response.status().is_success());
|
||||
|
||||
{
|
||||
let len = response
|
||||
.headers()
|
||||
.get(http::header::CONTENT_LENGTH)
|
||||
.unwrap();
|
||||
assert_eq!(format!("{}", STR.len()), len.to_str().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_body_length() {
|
||||
let rustls = ssl_acceptor().unwrap();
|
||||
let mut srv = TestServer::new(move || {
|
||||
rustls
|
||||
.clone()
|
||||
.map_err(|e| println!("Rustls error: {}", e))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|_| {
|
||||
let body = once(Ok(Bytes::from_static(STR.as_ref())));
|
||||
ok::<_, ()>(
|
||||
Response::Ok()
|
||||
.body(body::SizedStream::new(STR.len() as u64, body)),
|
||||
)
|
||||
})
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.block_on(srv.sget("/").send()).unwrap();
|
||||
assert!(response.status().is_success());
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).unwrap();
|
||||
assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_body_chunked_explicit() {
|
||||
let rustls = ssl_acceptor().unwrap();
|
||||
let mut srv = TestServer::new(move || {
|
||||
rustls
|
||||
.clone()
|
||||
.map_err(|e| println!("Rustls error: {}", e))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|_| {
|
||||
let body =
|
||||
once::<_, Error>(Ok(Bytes::from_static(STR.as_ref())));
|
||||
ok::<_, ()>(
|
||||
Response::Ok()
|
||||
.header(header::TRANSFER_ENCODING, "chunked")
|
||||
.streaming(body),
|
||||
)
|
||||
})
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.block_on(srv.sget("/").send()).unwrap();
|
||||
assert!(response.status().is_success());
|
||||
assert!(!response.headers().contains_key(header::TRANSFER_ENCODING));
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).unwrap();
|
||||
|
||||
// decode
|
||||
assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_response_http_error_handling() {
|
||||
let rustls = ssl_acceptor().unwrap();
|
||||
|
||||
let mut srv = TestServer::new(move || {
|
||||
rustls
|
||||
.clone()
|
||||
.map_err(|e| println!("Rustls error: {}", e))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(new_service_cfg(|_: &ServerConfig| {
|
||||
Ok::<_, ()>(|_| {
|
||||
let broken_header = Bytes::from_static(b"\0\0\0");
|
||||
ok::<_, ()>(
|
||||
Response::Ok()
|
||||
.header(http::header::CONTENT_TYPE, broken_header)
|
||||
.body(STR),
|
||||
)
|
||||
})
|
||||
}))
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.block_on(srv.sget("/").send()).unwrap();
|
||||
assert_eq!(response.status(), http::StatusCode::INTERNAL_SERVER_ERROR);
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).unwrap();
|
||||
assert_eq!(bytes, Bytes::from_static(b"failed to parse header value"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_service_error() {
|
||||
let rustls = ssl_acceptor().unwrap();
|
||||
|
||||
let mut srv = TestServer::new(move || {
|
||||
rustls
|
||||
.clone()
|
||||
.map_err(|e| println!("Rustls error: {}", e))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|_| Err::<Response, Error>(error::ErrorBadRequest("error")))
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.block_on(srv.sget("/").send()).unwrap();
|
||||
assert_eq!(response.status(), http::StatusCode::BAD_REQUEST);
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).unwrap();
|
||||
assert_eq!(bytes, Bytes::from_static(b"error"));
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,480 +0,0 @@
|
||||
#![cfg(feature = "ssl")]
|
||||
use actix_codec::{AsyncRead, AsyncWrite};
|
||||
use actix_http_test::TestServer;
|
||||
use actix_server::ssl::OpensslAcceptor;
|
||||
use actix_server_config::ServerConfig;
|
||||
use actix_service::{new_service_cfg, NewService};
|
||||
|
||||
use bytes::{Bytes, BytesMut};
|
||||
use futures::future::{ok, Future};
|
||||
use futures::stream::{once, Stream};
|
||||
use openssl::ssl::{AlpnError, SslAcceptor, SslFiletype, SslMethod};
|
||||
use std::io::Result;
|
||||
|
||||
use actix_http::error::{ErrorBadRequest, PayloadError};
|
||||
use actix_http::http::header::{self, HeaderName, HeaderValue};
|
||||
use actix_http::http::{Method, StatusCode, Version};
|
||||
use actix_http::httpmessage::HttpMessage;
|
||||
use actix_http::{body, Error, HttpService, Request, Response};
|
||||
|
||||
fn load_body<S>(stream: S) -> impl Future<Item = BytesMut, Error = PayloadError>
|
||||
where
|
||||
S: Stream<Item = Bytes, Error = PayloadError>,
|
||||
{
|
||||
stream.fold(BytesMut::new(), move |mut body, chunk| {
|
||||
body.extend_from_slice(&chunk);
|
||||
Ok::<_, PayloadError>(body)
|
||||
})
|
||||
}
|
||||
|
||||
fn ssl_acceptor<T: AsyncRead + AsyncWrite>() -> Result<OpensslAcceptor<T, ()>> {
|
||||
// load ssl keys
|
||||
let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
|
||||
builder
|
||||
.set_private_key_file("../tests/key.pem", SslFiletype::PEM)
|
||||
.unwrap();
|
||||
builder
|
||||
.set_certificate_chain_file("../tests/cert.pem")
|
||||
.unwrap();
|
||||
builder.set_alpn_select_callback(|_, protos| {
|
||||
const H2: &[u8] = b"\x02h2";
|
||||
if protos.windows(3).any(|window| window == H2) {
|
||||
Ok(b"h2")
|
||||
} else {
|
||||
Err(AlpnError::NOACK)
|
||||
}
|
||||
});
|
||||
builder.set_alpn_protos(b"\x02h2")?;
|
||||
Ok(OpensslAcceptor::new(builder.build()))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2() -> Result<()> {
|
||||
let openssl = ssl_acceptor()?;
|
||||
let mut srv = TestServer::new(move || {
|
||||
openssl
|
||||
.clone()
|
||||
.map_err(|e| println!("Openssl error: {}", e))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|_| ok::<_, Error>(Response::Ok().finish()))
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.block_on(srv.sget("/").send()).unwrap();
|
||||
assert!(response.status().is_success());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_1() -> Result<()> {
|
||||
let openssl = ssl_acceptor()?;
|
||||
let mut srv = TestServer::new(move || {
|
||||
openssl
|
||||
.clone()
|
||||
.map_err(|e| println!("Openssl error: {}", e))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.finish(|req: Request| {
|
||||
assert!(req.peer_addr().is_some());
|
||||
assert_eq!(req.version(), Version::HTTP_2);
|
||||
ok::<_, Error>(Response::Ok().finish())
|
||||
})
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.block_on(srv.sget("/").send()).unwrap();
|
||||
assert!(response.status().is_success());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_body() -> Result<()> {
|
||||
let data = "HELLOWORLD".to_owned().repeat(64 * 1024);
|
||||
let openssl = ssl_acceptor()?;
|
||||
let mut srv = TestServer::new(move || {
|
||||
openssl
|
||||
.clone()
|
||||
.map_err(|e| println!("Openssl error: {}", e))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|mut req: Request<_>| {
|
||||
load_body(req.take_payload())
|
||||
.and_then(|body| Ok(Response::Ok().body(body)))
|
||||
})
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.block_on(srv.sget("/").send_body(data.clone())).unwrap();
|
||||
assert!(response.status().is_success());
|
||||
|
||||
let body = srv.load_body(response).unwrap();
|
||||
assert_eq!(&body, data.as_bytes());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_content_length() {
|
||||
let openssl = ssl_acceptor().unwrap();
|
||||
|
||||
let mut srv = TestServer::new(move || {
|
||||
openssl
|
||||
.clone()
|
||||
.map_err(|e| println!("Openssl error: {}", e))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|req: Request| {
|
||||
let indx: usize = req.uri().path()[1..].parse().unwrap();
|
||||
let statuses = [
|
||||
StatusCode::NO_CONTENT,
|
||||
StatusCode::CONTINUE,
|
||||
StatusCode::SWITCHING_PROTOCOLS,
|
||||
StatusCode::PROCESSING,
|
||||
StatusCode::OK,
|
||||
StatusCode::NOT_FOUND,
|
||||
];
|
||||
ok::<_, ()>(Response::new(statuses[indx]))
|
||||
})
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let header = HeaderName::from_static("content-length");
|
||||
let value = HeaderValue::from_static("0");
|
||||
|
||||
{
|
||||
for i in 0..4 {
|
||||
let req = srv
|
||||
.request(Method::GET, srv.surl(&format!("/{}", i)))
|
||||
.send();
|
||||
let response = srv.block_on(req).unwrap();
|
||||
assert_eq!(response.headers().get(&header), None);
|
||||
|
||||
let req = srv
|
||||
.request(Method::HEAD, srv.surl(&format!("/{}", i)))
|
||||
.send();
|
||||
let response = srv.block_on(req).unwrap();
|
||||
assert_eq!(response.headers().get(&header), None);
|
||||
}
|
||||
|
||||
for i in 4..6 {
|
||||
let req = srv
|
||||
.request(Method::GET, srv.surl(&format!("/{}", i)))
|
||||
.send();
|
||||
let response = srv.block_on(req).unwrap();
|
||||
assert_eq!(response.headers().get(&header), Some(&value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_headers() {
|
||||
let data = STR.repeat(10);
|
||||
let data2 = data.clone();
|
||||
let openssl = ssl_acceptor().unwrap();
|
||||
|
||||
let mut srv = TestServer::new(move || {
|
||||
let data = data.clone();
|
||||
openssl
|
||||
.clone()
|
||||
.map_err(|e| println!("Openssl error: {}", e))
|
||||
.and_then(
|
||||
HttpService::build().h2(move |_| {
|
||||
let mut builder = Response::Ok();
|
||||
for idx in 0..90 {
|
||||
builder.header(
|
||||
format!("X-TEST-{}", idx).as_str(),
|
||||
"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 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 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 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 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 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 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()))
|
||||
}).map_err(|_| ()))
|
||||
});
|
||||
|
||||
let response = srv.block_on(srv.sget("/").send()).unwrap();
|
||||
assert!(response.status().is_success());
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).unwrap();
|
||||
assert_eq!(bytes, Bytes::from(data2));
|
||||
}
|
||||
|
||||
const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World";
|
||||
|
||||
#[test]
|
||||
fn test_h2_body2() {
|
||||
let openssl = ssl_acceptor().unwrap();
|
||||
let mut srv = TestServer::new(move || {
|
||||
openssl
|
||||
.clone()
|
||||
.map_err(|e| println!("Openssl error: {}", e))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|_| ok::<_, ()>(Response::Ok().body(STR)))
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.block_on(srv.sget("/").send()).unwrap();
|
||||
assert!(response.status().is_success());
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).unwrap();
|
||||
assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_head_empty() {
|
||||
let openssl = ssl_acceptor().unwrap();
|
||||
let mut srv = TestServer::new(move || {
|
||||
openssl
|
||||
.clone()
|
||||
.map_err(|e| println!("Openssl error: {}", e))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.finish(|_| ok::<_, ()>(Response::Ok().body(STR)))
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.block_on(srv.shead("/").send()).unwrap();
|
||||
assert!(response.status().is_success());
|
||||
assert_eq!(response.version(), Version::HTTP_2);
|
||||
|
||||
{
|
||||
let len = response.headers().get(header::CONTENT_LENGTH).unwrap();
|
||||
assert_eq!(format!("{}", STR.len()), len.to_str().unwrap());
|
||||
}
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).unwrap();
|
||||
assert!(bytes.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_head_binary() {
|
||||
let openssl = ssl_acceptor().unwrap();
|
||||
let mut srv = TestServer::new(move || {
|
||||
openssl
|
||||
.clone()
|
||||
.map_err(|e| println!("Openssl error: {}", e))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|_| {
|
||||
ok::<_, ()>(
|
||||
Response::Ok().content_length(STR.len() as u64).body(STR),
|
||||
)
|
||||
})
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.block_on(srv.shead("/").send()).unwrap();
|
||||
assert!(response.status().is_success());
|
||||
|
||||
{
|
||||
let len = response.headers().get(header::CONTENT_LENGTH).unwrap();
|
||||
assert_eq!(format!("{}", STR.len()), len.to_str().unwrap());
|
||||
}
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).unwrap();
|
||||
assert!(bytes.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_head_binary2() {
|
||||
let openssl = ssl_acceptor().unwrap();
|
||||
let mut srv = TestServer::new(move || {
|
||||
openssl
|
||||
.clone()
|
||||
.map_err(|e| println!("Openssl error: {}", e))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|_| ok::<_, ()>(Response::Ok().body(STR)))
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.block_on(srv.shead("/").send()).unwrap();
|
||||
assert!(response.status().is_success());
|
||||
|
||||
{
|
||||
let len = response.headers().get(header::CONTENT_LENGTH).unwrap();
|
||||
assert_eq!(format!("{}", STR.len()), len.to_str().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_body_length() {
|
||||
let openssl = ssl_acceptor().unwrap();
|
||||
let mut srv = TestServer::new(move || {
|
||||
openssl
|
||||
.clone()
|
||||
.map_err(|e| println!("Openssl error: {}", e))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|_| {
|
||||
let body = once(Ok(Bytes::from_static(STR.as_ref())));
|
||||
ok::<_, ()>(
|
||||
Response::Ok()
|
||||
.body(body::SizedStream::new(STR.len() as u64, body)),
|
||||
)
|
||||
})
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.block_on(srv.sget("/").send()).unwrap();
|
||||
assert!(response.status().is_success());
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).unwrap();
|
||||
assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_body_chunked_explicit() {
|
||||
let openssl = ssl_acceptor().unwrap();
|
||||
let mut srv = TestServer::new(move || {
|
||||
openssl
|
||||
.clone()
|
||||
.map_err(|e| println!("Openssl error: {}", e))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|_| {
|
||||
let body =
|
||||
once::<_, Error>(Ok(Bytes::from_static(STR.as_ref())));
|
||||
ok::<_, ()>(
|
||||
Response::Ok()
|
||||
.header(header::TRANSFER_ENCODING, "chunked")
|
||||
.streaming(body),
|
||||
)
|
||||
})
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.block_on(srv.sget("/").send()).unwrap();
|
||||
assert!(response.status().is_success());
|
||||
assert!(!response.headers().contains_key(header::TRANSFER_ENCODING));
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).unwrap();
|
||||
|
||||
// decode
|
||||
assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_response_http_error_handling() {
|
||||
let openssl = ssl_acceptor().unwrap();
|
||||
|
||||
let mut srv = TestServer::new(move || {
|
||||
openssl
|
||||
.clone()
|
||||
.map_err(|e| println!("Openssl error: {}", e))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(new_service_cfg(|_: &ServerConfig| {
|
||||
Ok::<_, ()>(|_| {
|
||||
let broken_header = Bytes::from_static(b"\0\0\0");
|
||||
ok::<_, ()>(
|
||||
Response::Ok()
|
||||
.header(header::CONTENT_TYPE, broken_header)
|
||||
.body(STR),
|
||||
)
|
||||
})
|
||||
}))
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.block_on(srv.sget("/").send()).unwrap();
|
||||
assert_eq!(response.status(), StatusCode::INTERNAL_SERVER_ERROR);
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).unwrap();
|
||||
assert_eq!(bytes, Bytes::from_static(b"failed to parse header value"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_service_error() {
|
||||
let openssl = ssl_acceptor().unwrap();
|
||||
|
||||
let mut srv = TestServer::new(move || {
|
||||
openssl
|
||||
.clone()
|
||||
.map_err(|e| println!("Openssl error: {}", e))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.h2(|_| Err::<Response, Error>(ErrorBadRequest("error")))
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.block_on(srv.sget("/").send()).unwrap();
|
||||
assert_eq!(response.status(), StatusCode::BAD_REQUEST);
|
||||
|
||||
// read response
|
||||
let bytes = srv.load_body(response).unwrap();
|
||||
assert_eq!(bytes, Bytes::from_static(b"error"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h2_on_connect() {
|
||||
let openssl = ssl_acceptor().unwrap();
|
||||
|
||||
let mut srv = TestServer::new(move || {
|
||||
openssl
|
||||
.clone()
|
||||
.map_err(|e| println!("Openssl error: {}", e))
|
||||
.and_then(
|
||||
HttpService::build()
|
||||
.on_connect(|_| 10usize)
|
||||
.h2(|req: Request| {
|
||||
assert!(req.extensions().contains::<usize>());
|
||||
ok::<_, ()>(Response::Ok().finish())
|
||||
})
|
||||
.map_err(|_| ()),
|
||||
)
|
||||
});
|
||||
|
||||
let response = srv.block_on(srv.sget("/").send()).unwrap();
|
||||
assert!(response.status().is_success());
|
||||
}
|
@ -1,26 +1,27 @@
|
||||
use actix_codec::{AsyncRead, AsyncWrite, Framed};
|
||||
use actix_http::{body, h1, ws, Error, HttpService, Request, Response};
|
||||
use actix_http_test::TestServer;
|
||||
use actix_http_test::{block_on, TestServer};
|
||||
use actix_utils::framed::FramedTransport;
|
||||
use bytes::{Bytes, BytesMut};
|
||||
use futures::future::{self, ok};
|
||||
use futures::{Future, Sink, Stream};
|
||||
use futures::future;
|
||||
use futures::{SinkExt, StreamExt};
|
||||
|
||||
fn ws_service<T: AsyncRead + AsyncWrite>(
|
||||
(req, framed): (Request, Framed<T, h1::Codec>),
|
||||
) -> impl Future<Item = (), Error = Error> {
|
||||
async fn ws_service<T: AsyncRead + AsyncWrite + Unpin>(
|
||||
(req, mut framed): (Request, Framed<T, h1::Codec>),
|
||||
) -> Result<(), Error> {
|
||||
let res = ws::handshake(req.head()).unwrap().message_body(());
|
||||
|
||||
framed
|
||||
.send((res, body::BodySize::None).into())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
FramedTransport::new(framed.into_framed(ws::Codec::new()), service)
|
||||
.await
|
||||
.map_err(|_| panic!())
|
||||
.and_then(|framed| {
|
||||
FramedTransport::new(framed.into_framed(ws::Codec::new()), service)
|
||||
.map_err(|_| panic!())
|
||||
})
|
||||
}
|
||||
|
||||
fn service(msg: ws::Frame) -> impl Future<Item = ws::Message, Error = Error> {
|
||||
async fn service(msg: ws::Frame) -> Result<ws::Message, Error> {
|
||||
let msg = match msg {
|
||||
ws::Frame::Ping(msg) => ws::Message::Pong(msg),
|
||||
ws::Frame::Text(text) => {
|
||||
@ -30,47 +31,56 @@ fn service(msg: ws::Frame) -> impl Future<Item = ws::Message, Error = Error> {
|
||||
ws::Frame::Close(reason) => ws::Message::Close(reason),
|
||||
_ => panic!(),
|
||||
};
|
||||
ok(msg)
|
||||
Ok(msg)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_simple() {
|
||||
let mut srv = TestServer::new(|| {
|
||||
HttpService::build()
|
||||
.upgrade(ws_service)
|
||||
.finish(|_| future::ok::<_, ()>(Response::NotFound()))
|
||||
});
|
||||
block_on(async {
|
||||
let mut srv = TestServer::start(|| {
|
||||
HttpService::build()
|
||||
.upgrade(actix_service::service_fn(ws_service))
|
||||
.finish(|_| future::ok::<_, ()>(Response::NotFound()))
|
||||
});
|
||||
|
||||
// client service
|
||||
let framed = srv.ws().unwrap();
|
||||
let framed = srv
|
||||
.block_on(framed.send(ws::Message::Text("text".to_string())))
|
||||
.unwrap();
|
||||
let (item, framed) = srv.block_on(framed.into_future()).map_err(|_| ()).unwrap();
|
||||
assert_eq!(item, Some(ws::Frame::Text(Some(BytesMut::from("text")))));
|
||||
// client service
|
||||
let mut framed = srv.ws().await.unwrap();
|
||||
framed
|
||||
.send(ws::Message::Text("text".to_string()))
|
||||
.await
|
||||
.unwrap();
|
||||
let (item, mut framed) = framed.into_future().await;
|
||||
assert_eq!(
|
||||
item.unwrap().unwrap(),
|
||||
ws::Frame::Text(Some(BytesMut::from("text")))
|
||||
);
|
||||
|
||||
let framed = srv
|
||||
.block_on(framed.send(ws::Message::Binary("text".into())))
|
||||
.unwrap();
|
||||
let (item, framed) = srv.block_on(framed.into_future()).map_err(|_| ()).unwrap();
|
||||
assert_eq!(
|
||||
item,
|
||||
Some(ws::Frame::Binary(Some(Bytes::from_static(b"text").into())))
|
||||
);
|
||||
framed
|
||||
.send(ws::Message::Binary("text".into()))
|
||||
.await
|
||||
.unwrap();
|
||||
let (item, mut framed) = framed.into_future().await;
|
||||
assert_eq!(
|
||||
item.unwrap().unwrap(),
|
||||
ws::Frame::Binary(Some(Bytes::from_static(b"text").into()))
|
||||
);
|
||||
|
||||
let framed = srv
|
||||
.block_on(framed.send(ws::Message::Ping("text".into())))
|
||||
.unwrap();
|
||||
let (item, framed) = srv.block_on(framed.into_future()).map_err(|_| ()).unwrap();
|
||||
assert_eq!(item, Some(ws::Frame::Pong("text".to_string().into())));
|
||||
framed.send(ws::Message::Ping("text".into())).await.unwrap();
|
||||
let (item, mut framed) = framed.into_future().await;
|
||||
assert_eq!(
|
||||
item.unwrap().unwrap(),
|
||||
ws::Frame::Pong("text".to_string().into())
|
||||
);
|
||||
|
||||
let framed = srv
|
||||
.block_on(framed.send(ws::Message::Close(Some(ws::CloseCode::Normal.into()))))
|
||||
.unwrap();
|
||||
framed
|
||||
.send(ws::Message::Close(Some(ws::CloseCode::Normal.into())))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let (item, _framed) = srv.block_on(framed.into_future()).map_err(|_| ()).unwrap();
|
||||
assert_eq!(
|
||||
item,
|
||||
Some(ws::Frame::Close(Some(ws::CloseCode::Normal.into())))
|
||||
);
|
||||
let (item, _framed) = framed.into_future().await;
|
||||
assert_eq!(
|
||||
item.unwrap().unwrap(),
|
||||
ws::Frame::Close(Some(ws::CloseCode::Normal.into()))
|
||||
);
|
||||
})
|
||||
}
|
||||
|
Reference in New Issue
Block a user