diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index de8dd537c9..109f7f4681 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -9,9 +9,31 @@ env: RUST_BACKTRACE: 1 jobs: + style: + name: Check Style + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v1 + + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + components: rustfmt + + - name: cargo fmt --check + uses: actions-rs/cargo@v1 + with: + command: fmt + args: --all -- --check + + test: name: Test ${{ matrix.rust }} on ${{ matrix.os }} - + needs: [style] strategy: matrix: rust: diff --git a/.rustfmt.toml b/.rustfmt.toml deleted file mode 100644 index c7ad93bafe..0000000000 --- a/.rustfmt.toml +++ /dev/null @@ -1 +0,0 @@ -disable_all_formatting = true diff --git a/benches/connect.rs b/benches/connect.rs index b9d13198f5..c8ca68a769 100644 --- a/benches/connect.rs +++ b/benches/connect.rs @@ -3,11 +3,11 @@ extern crate test; +use http::Uri; +use hyper::client::connect::HttpConnector; +use hyper::service::Service; use std::net::SocketAddr; use tokio::net::TcpListener; -use hyper::client::connect::{HttpConnector}; -use hyper::service::Service; -use http::Uri; #[bench] fn http_connector(b: &mut test::Bencher) { @@ -17,7 +17,9 @@ fn http_connector(b: &mut test::Bencher) { .basic_scheduler() .build() .expect("rt build"); - let mut listener = rt.block_on(TcpListener::bind(&SocketAddr::from(([127, 0, 0, 1], 0)))).expect("bind"); + let mut listener = rt + .block_on(TcpListener::bind(&SocketAddr::from(([127, 0, 0, 1], 0)))) + .expect("bind"); let addr = listener.local_addr().expect("local_addr"); let dst: Uri = format!("http://{}/", addr).parse().expect("uri parse"); let mut connector = HttpConnector::new(); @@ -28,7 +30,6 @@ fn http_connector(b: &mut test::Bencher) { } }); - b.iter(|| { rt.block_on(async { connector.call(dst.clone()).await.expect("connect"); diff --git a/benches/end_to_end.rs b/benches/end_to_end.rs index 68ee7f053d..281852d8a7 100644 --- a/benches/end_to_end.rs +++ b/benches/end_to_end.rs @@ -7,15 +7,14 @@ use std::net::SocketAddr; use futures_util::future::join_all; -use hyper::{body::HttpBody as _, Body, Method, Request, Response, Server}; use hyper::client::HttpConnector; +use hyper::{body::HttpBody as _, Body, Method, Request, Response, Server}; // HTTP1 #[bench] fn http1_get(b: &mut test::Bencher) { - opts() - .bench(b) + opts().bench(b) } #[bench] @@ -48,9 +47,7 @@ fn http1_body_both_10mb(b: &mut test::Bencher) { #[bench] fn http1_parallel_x10_empty(b: &mut test::Bencher) { - opts() - .parallel(10) - .bench(b) + opts().parallel(10).bench(b) } #[bench] @@ -76,19 +73,13 @@ fn http1_parallel_x10_req_10kb_100_chunks(b: &mut test::Bencher) { #[bench] fn http1_parallel_x10_res_1mb(b: &mut test::Bencher) { let body = &[b'x'; 1024 * 1024 * 1]; - opts() - .parallel(10) - .response_body(body) - .bench(b) + opts().parallel(10).response_body(body).bench(b) } #[bench] fn http1_parallel_x10_res_10mb(b: &mut test::Bencher) { let body = &[b'x'; 1024 * 1024 * 10]; - opts() - .parallel(10) - .response_body(body) - .bench(b) + opts().parallel(10).response_body(body).bench(b) } // HTTP2 @@ -97,9 +88,7 @@ const HTTP2_MAX_WINDOW: u32 = std::u32::MAX >> 1; #[bench] fn http2_get(b: &mut test::Bencher) { - opts() - .http2() - .bench(b) + opts().http2().bench(b) } #[bench] @@ -123,10 +112,7 @@ fn http2_req_100kb(b: &mut test::Bencher) { #[bench] fn http2_parallel_x10_empty(b: &mut test::Bencher) { - opts() - .http2() - .parallel(10) - .bench(b) + opts().http2().parallel(10).bench(b) } #[bench] @@ -293,9 +279,10 @@ impl Opts { let make_request = || { let chunk_cnt = self.request_chunks; let body = if chunk_cnt > 0 { - let (mut tx, body) = Body::channel(); - let chunk = self.request_body.expect("request_chunks means request_body"); + let chunk = self + .request_body + .expect("request_chunks means request_body"); exec.spawn(async move { for _ in 0..chunk_cnt { tx.send_data(chunk.into()).await.expect("send_data"); @@ -303,8 +290,7 @@ impl Opts { }); body } else { - self - .request_body + self.request_body .map(Body::from) .unwrap_or_else(|| Body::empty()) }; @@ -328,14 +314,12 @@ impl Opts { let req = make_request(); rt.block_on(send_request(req)); }); - } else { b.iter(|| { - let futs = (0..self.parallel_cnt) - .map(|_| { - let req = make_request(); - send_request(req) - }); + let futs = (0..self.parallel_cnt).map(|_| { + let req = make_request(); + send_request(req) + }); // Await all spawned futures becoming completed. rt.block_on(join_all(futs)); }); @@ -353,12 +337,16 @@ fn spawn_server(rt: &mut tokio::runtime::Runtime, opts: &Opts) -> SocketAddr { .http2_only(opts.http2) .http2_initial_stream_window_size(opts.http2_stream_window) .http2_initial_connection_window_size(opts.http2_conn_window) - .serve(make_service_fn( move |_| async move { - Ok::<_, hyper::Error>(service_fn(move |req: Request| async move { - let mut req_body = req.into_body(); - while let Some(_chunk) = req_body.data().await {} - Ok::<_, hyper::Error>(Response::new(Body::from(body))) - })) + .serve(make_service_fn(move |_| { + async move { + Ok::<_, hyper::Error>(service_fn(move |req: Request| { + async move { + let mut req_body = req.into_body(); + while let Some(_chunk) = req_body.data().await {} + Ok::<_, hyper::Error>(Response::new(Body::from(body))) + } + })) + } })) }); let addr = srv.local_addr(); @@ -367,5 +355,5 @@ fn spawn_server(rt: &mut tokio::runtime::Runtime, opts: &Opts) -> SocketAddr { panic!("server error: {}", err); } }); - return addr + return addr; } diff --git a/benches/pipeline.rs b/benches/pipeline.rs index 562c373517..40b86e3173 100644 --- a/benches/pipeline.rs +++ b/benches/pipeline.rs @@ -4,14 +4,14 @@ extern crate test; use std::io::{Read, Write}; -use std::net::{TcpStream}; +use std::net::TcpStream; use std::sync::mpsc; use std::time::Duration; use tokio::sync::oneshot; -use hyper::{Body, Response, Server}; use hyper::service::{make_service_fn, service_fn}; +use hyper::{Body, Response, Server}; const PIPELINED_REQUESTS: usize = 16; @@ -25,10 +25,12 @@ fn hello_world(b: &mut test::Bencher) { std::thread::spawn(move || { let addr = "127.0.0.1:0".parse().unwrap(); - let make_svc = make_service_fn(|_| async { - Ok::<_, hyper::Error>(service_fn(|_| async { - Ok::<_, hyper::Error>(Response::new(Body::from("Hello, World!"))) - })) + let make_svc = make_service_fn(|_| { + async { + Ok::<_, hyper::Error>(service_fn(|_| { + async { Ok::<_, hyper::Error>(Response::new(Body::from("Hello, World!"))) } + })) + } }); let mut rt = tokio::runtime::Builder::new() @@ -44,10 +46,9 @@ fn hello_world(b: &mut test::Bencher) { addr_tx.send(srv.local_addr()).unwrap(); - let graceful = srv - .with_graceful_shutdown(async { - until_rx.await.ok(); - }); + let graceful = srv.with_graceful_shutdown(async { + until_rx.await.ok(); + }); rt.block_on(async { if let Err(e) = graceful.await { @@ -66,7 +67,8 @@ fn hello_world(b: &mut test::Bencher) { let total_bytes = { let mut tcp = TcpStream::connect(addr).unwrap(); - tcp.write_all(b"GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n").unwrap(); + tcp.write_all(b"GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n") + .unwrap(); let mut buf = Vec::new(); tcp.read_to_end(&mut buf).unwrap() } * PIPELINED_REQUESTS; @@ -85,4 +87,3 @@ fn hello_world(b: &mut test::Bencher) { assert_eq!(sum, total_bytes); }); } - diff --git a/benches/server.rs b/benches/server.rs index 28f8f21e4d..44e23debd5 100644 --- a/benches/server.rs +++ b/benches/server.rs @@ -11,26 +11,31 @@ use std::time::Duration; use futures_util::{stream, StreamExt}; use tokio::sync::oneshot; -use hyper::{Body, Response, Server}; use hyper::service::{make_service_fn, service_fn}; +use hyper::{Body, Response, Server}; macro_rules! bench_server { - ($b:ident, $header:expr, $body:expr) => ({ + ($b:ident, $header:expr, $body:expr) => {{ let _ = pretty_env_logger::try_init(); let (_until_tx, until_rx) = oneshot::channel::<()>(); let addr = { let (addr_tx, addr_rx) = mpsc::channel(); std::thread::spawn(move || { let addr = "127.0.0.1:0".parse().unwrap(); - let make_svc = make_service_fn(|_| async { - Ok::<_, hyper::Error>(service_fn(|_| async { - Ok::<_, hyper::Error>(Response::builder() - .header($header.0, $header.1) - .header("content-type", "text/plain") - .body($body()) - .unwrap() - ) - })) + let make_svc = make_service_fn(|_| { + async { + Ok::<_, hyper::Error>(service_fn(|_| { + async { + Ok::<_, hyper::Error>( + Response::builder() + .header($header.0, $header.1) + .header("content-type", "text/plain") + .body($body()) + .unwrap(), + ) + } + })) + } }); let mut rt = tokio::runtime::Builder::new() @@ -39,17 +44,13 @@ macro_rules! bench_server { .build() .expect("rt build"); - let srv = rt.block_on(async move { - Server::bind(&addr) - .serve(make_svc) - }); + let srv = rt.block_on(async move { Server::bind(&addr).serve(make_svc) }); addr_tx.send(srv.local_addr()).unwrap(); - let graceful = srv - .with_graceful_shutdown(async { - until_rx.await.ok(); - }); + let graceful = srv.with_graceful_shutdown(async { + until_rx.await.ok(); + }); rt.block_on(async move { if let Err(e) = graceful.await { panic!("server error: {}", e); @@ -62,7 +63,8 @@ macro_rules! bench_server { let total_bytes = { let mut tcp = TcpStream::connect(addr).unwrap(); - tcp.write_all(b"GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n").unwrap(); + tcp.write_all(b"GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n") + .unwrap(); let mut buf = Vec::new(); tcp.read_to_end(&mut buf).unwrap() }; @@ -73,14 +75,15 @@ macro_rules! bench_server { $b.bytes = 35 + total_bytes as u64; $b.iter(|| { - tcp.write_all(b"GET / HTTP/1.1\r\nHost: localhost\r\n\r\n").unwrap(); + tcp.write_all(b"GET / HTTP/1.1\r\nHost: localhost\r\n\r\n") + .unwrap(); let mut sum = 0; while sum < total_bytes { sum += tcp.read(&mut buf).unwrap(); } assert_eq!(sum, total_bytes); }); - }) + }}; } fn body(b: &'static [u8]) -> hyper::Body { @@ -94,7 +97,9 @@ fn throughput_fixedsize_small_payload(b: &mut test::Bencher) { #[bench] fn throughput_fixedsize_large_payload(b: &mut test::Bencher) { - bench_server!(b, ("content-length", "1000000"), || body(&[b'x'; 1_000_000])) + bench_server!(b, ("content-length", "1000000"), || body( + &[b'x'; 1_000_000] + )) } #[bench] @@ -107,12 +112,16 @@ fn throughput_fixedsize_many_chunks(b: &mut test::Bencher) { #[bench] fn throughput_chunked_small_payload(b: &mut test::Bencher) { - bench_server!(b, ("transfer-encoding", "chunked"), || body(b"Hello, World!")) + bench_server!(b, ("transfer-encoding", "chunked"), || body( + b"Hello, World!" + )) } #[bench] fn throughput_chunked_large_payload(b: &mut test::Bencher) { - bench_server!(b, ("transfer-encoding", "chunked"), || body(&[b'x'; 1_000_000])) + bench_server!(b, ("transfer-encoding", "chunked"), || body( + &[b'x'; 1_000_000] + )) } #[bench] @@ -134,14 +143,17 @@ fn raw_tcp_throughput_small_payload(b: &mut test::Bencher) { let mut buf = [0u8; 8192]; while rx.try_recv().is_err() { sock.read(&mut buf).unwrap(); - sock.write_all(b"\ + sock.write_all( + b"\ HTTP/1.1 200 OK\r\n\ Content-Length: 13\r\n\ Content-Type: text/plain; charset=utf-8\r\n\ Date: Fri, 12 May 2017 18:21:45 GMT\r\n\ \r\n\ Hello, World!\ - ").unwrap(); + ", + ) + .unwrap(); } }); @@ -150,7 +162,8 @@ fn raw_tcp_throughput_small_payload(b: &mut test::Bencher) { b.bytes = 130 + 35; b.iter(|| { - tcp.write_all(b"GET / HTTP/1.1\r\nHost: localhost\r\n\r\n").unwrap(); + tcp.write_all(b"GET / HTTP/1.1\r\nHost: localhost\r\n\r\n") + .unwrap(); let n = tcp.read(&mut buf).unwrap(); assert_eq!(n, 130); }); @@ -191,7 +204,8 @@ fn raw_tcp_throughput_large_payload(b: &mut test::Bencher) { b.bytes = expect_read as u64 + 35; b.iter(|| { - tcp.write_all(b"GET / HTTP/1.1\r\nHost: localhost\r\n\r\n").unwrap(); + tcp.write_all(b"GET / HTTP/1.1\r\nHost: localhost\r\n\r\n") + .unwrap(); let mut sum = 0; while sum < expect_read { sum += tcp.read(&mut buf).unwrap(); diff --git a/examples/client.rs b/examples/client.rs index f60990e024..de4e4ec3be 100644 --- a/examples/client.rs +++ b/examples/client.rs @@ -2,7 +2,7 @@ #![warn(rust_2018_idioms)] use std::env; -use hyper::{Client, body::HttpBody as _}; +use hyper::{body::HttpBody as _, Client}; use tokio::io::{self, AsyncWriteExt as _}; // A simple type alias so as to DRY. diff --git a/examples/client_json.rs b/examples/client_json.rs index a22eac18d4..98a79682d8 100644 --- a/examples/client_json.rs +++ b/examples/client_json.rs @@ -4,8 +4,8 @@ #[macro_use] extern crate serde_derive; -use hyper::Client; use futures_util::StreamExt; +use hyper::Client; // A simple type alias so as to DRY. type Result = std::result::Result>; diff --git a/examples/echo.rs b/examples/echo.rs index 891e1600d5..3aab063abb 100644 --- a/examples/echo.rs +++ b/examples/echo.rs @@ -1,22 +1,20 @@ //#![deny(warnings)] -use hyper::{Body, Method, Request, Response, Server, StatusCode}; -use hyper::service::{make_service_fn, service_fn}; use futures_util::{StreamExt, TryStreamExt}; +use hyper::service::{make_service_fn, service_fn}; +use hyper::{Body, Method, Request, Response, Server, StatusCode}; /// This is our service handler. It receives a Request, routes on its /// path, and returns a Future of a Response. async fn echo(mut req: Request) -> Result, hyper::Error> { match (req.method(), req.uri().path()) { // Serve some instructions at / - (&Method::GET, "/") => { - Ok(Response::new(Body::from("Try POSTing data to /echo such as: `curl localhost:3000/echo -XPOST -d 'hello world'`"))) - } + (&Method::GET, "/") => Ok(Response::new(Body::from( + "Try POSTing data to /echo such as: `curl localhost:3000/echo -XPOST -d 'hello world'`", + ))), // Simply echo the body back to the client. - (&Method::POST, "/echo") => { - Ok(Response::new(req.into_body())) - } + (&Method::POST, "/echo") => Ok(Response::new(req.into_body())), // Convert to uppercase before sending back to client using a stream. (&Method::POST, "/echo/uppercase") => { @@ -41,11 +39,7 @@ async fn echo(mut req: Request) -> Result, hyper::Error> { whole_body.extend_from_slice(&chunk?); } - let reversed_body = whole_body - .iter() - .rev() - .cloned() - .collect::>(); + let reversed_body = whole_body.iter().rev().cloned().collect::>(); Ok(Response::new(Body::from(reversed_body))) } @@ -58,19 +52,13 @@ async fn echo(mut req: Request) -> Result, hyper::Error> { } } - #[tokio::main] async fn main() -> Result<(), Box> { let addr = ([127, 0, 0, 1], 3000).into(); - let service = make_service_fn(|_| { - async { - Ok::<_, hyper::Error>(service_fn(echo)) - } - }); + let service = make_service_fn(|_| async { Ok::<_, hyper::Error>(service_fn(echo)) }); - let server = Server::bind(&addr) - .serve(service); + let server = Server::bind(&addr).serve(service); println!("Listening on http://{}", addr); diff --git a/examples/hello.rs b/examples/hello.rs index c75209b4f8..e6c97b69f9 100644 --- a/examples/hello.rs +++ b/examples/hello.rs @@ -2,8 +2,8 @@ use std::convert::Infallible; -use hyper::{Body, Request, Response, Server}; use hyper::service::{make_service_fn, service_fn}; +use hyper::{Body, Request, Response, Server}; async fn hello(_: Request) -> Result, Infallible> { Ok(Response::new(Body::from("Hello World!"))) @@ -19,9 +19,7 @@ pub async fn main() -> Result<(), Box> { // This is the `Service` that will handle the connection. // `service_fn` is a helper to convert a function that // returns a Response into a `Service`. - async { - Ok::<_, Infallible>(service_fn(hello)) - } + async { Ok::<_, Infallible>(service_fn(hello)) } }); let addr = ([127, 0, 0, 1], 3000).into(); diff --git a/examples/multi_server.rs b/examples/multi_server.rs index 6d38478e60..936f695179 100644 --- a/examples/multi_server.rs +++ b/examples/multi_server.rs @@ -1,9 +1,9 @@ #![deny(warnings)] #![warn(rust_2018_idioms)] -use hyper::{Body, Request, Response, Server}; -use hyper::service::{service_fn, make_service_fn}; use futures_util::future::join; +use hyper::service::{make_service_fn, service_fn}; +use hyper::{Body, Request, Response, Server}; static INDEX1: &'static [u8] = b"The 1st service!"; static INDEX2: &'static [u8] = b"The 2nd service!"; @@ -23,19 +23,13 @@ async fn main() -> Result<(), Box> { let addr1 = ([127, 0, 0, 1], 1337).into(); let addr2 = ([127, 0, 0, 1], 1338).into(); - let srv1 = Server::bind(&addr1) - .serve(make_service_fn(|_| { - async { - Ok::<_, hyper::Error>(service_fn(index1)) - } - })); - - let srv2 = Server::bind(&addr2) - .serve(make_service_fn(|_| { - async { - Ok::<_, hyper::Error>(service_fn(index2)) - } - })); + let srv1 = Server::bind(&addr1).serve(make_service_fn(|_| { + async { Ok::<_, hyper::Error>(service_fn(index1)) } + })); + + let srv2 = Server::bind(&addr2).serve(make_service_fn(|_| { + async { Ok::<_, hyper::Error>(service_fn(index2)) } + })); println!("Listening on http://{} and http://{}", addr1, addr2); diff --git a/examples/params.rs b/examples/params.rs index ad938658b8..c2e08e1fd6 100644 --- a/examples/params.rs +++ b/examples/params.rs @@ -1,12 +1,12 @@ // #![deny(warnings)] // FIXME: https://github.com/rust-lang/rust/issues/62411 #![warn(rust_2018_idioms)] +use hyper::service::{make_service_fn, service_fn}; use hyper::{Body, Method, Request, Response, Server, StatusCode}; -use hyper::service::{service_fn, make_service_fn}; +use futures_util::StreamExt; use std::collections::HashMap; use url::form_urlencoded; -use futures_util::StreamExt; static INDEX: &[u8] = b"
Name:
Number:
"; static MISSING: &[u8] = b"Missing field"; @@ -15,9 +15,7 @@ static NOTNUMERIC: &[u8] = b"Number field is not numeric"; // Using service_fn, we can turn this function into a `Service`. async fn param_example(mut req: Request) -> Result, hyper::Error> { match (req.method(), req.uri().path()) { - (&Method::GET, "/") | (&Method::GET, "/post") => { - Ok(Response::new(INDEX.into())) - }, + (&Method::GET, "/") | (&Method::GET, "/post") => Ok(Response::new(INDEX.into())), (&Method::POST, "/post") => { // Concatenate the body... let mut b = Vec::new(); @@ -35,7 +33,9 @@ async fn param_example(mut req: Request) -> Result, hyper:: // form, and the values should be rolled up into a // HashMap>. However in this // example the simpler approach is sufficient. - let params = form_urlencoded::parse(b.as_ref()).into_owned().collect::>(); + let params = form_urlencoded::parse(b.as_ref()) + .into_owned() + .collect::>(); // Validate the request parameters, returning // early if an invalid input is detected. @@ -71,13 +71,11 @@ async fn param_example(mut req: Request) -> Result, hyper:: // needed here, too. let body = format!("Hello {}, your number is {}", name, number); Ok(Response::new(body.into())) - }, - _ => { - Ok(Response::builder() - .status(StatusCode::NOT_FOUND) - .body(Body::empty()) - .unwrap()) } + _ => Ok(Response::builder() + .status(StatusCode::NOT_FOUND) + .body(Body::empty()) + .unwrap()), } } @@ -87,12 +85,9 @@ async fn main() -> Result<(), Box> { let addr = ([127, 0, 0, 1], 1337).into(); - let server = Server::bind(&addr) - .serve(make_service_fn(|_| { - async { - Ok::<_, hyper::Error>(service_fn(param_example)) - } - })); + let server = Server::bind(&addr).serve(make_service_fn(|_| { + async { Ok::<_, hyper::Error>(service_fn(param_example)) } + })); println!("Listening on http://{}", addr); diff --git a/examples/proxy.rs b/examples/proxy.rs index e32360856b..a826737905 100644 --- a/examples/proxy.rs +++ b/examples/proxy.rs @@ -1,7 +1,7 @@ #![deny(warnings)] -use hyper::{Client, Error, Server}; use hyper::service::{make_service_fn, service_fn}; +use hyper::{Client, Error, Server}; use std::net::SocketAddr; #[tokio::main] @@ -19,15 +19,17 @@ async fn main() { // creating a 'service' to handle requests for that specific connection. let make_service = make_service_fn(move |_| { let client = client_main.clone(); - + async move { // This is the `Service` that will handle the connection. // `service_fn` is a helper to convert a function that // returns a Response into a `Service`. Ok::<_, Error>(service_fn(move |mut req| { - let uri_string = format!("http://{}/{}", - out_addr_clone, - req.uri().path_and_query().map(|x| x.as_str()).unwrap_or("")); + let uri_string = format!( + "http://{}/{}", + out_addr_clone, + req.uri().path_and_query().map(|x| x.as_str()).unwrap_or("") + ); let uri = uri_string.parse().unwrap(); *req.uri_mut() = uri; client.request(req) @@ -35,8 +37,7 @@ async fn main() { } }); - let server = Server::bind(&in_addr) - .serve(make_service); + let server = Server::bind(&in_addr).serve(make_service); println!("Listening on http://{}", in_addr); println!("Proxying on http://{}", out_addr); diff --git a/examples/send_file.rs b/examples/send_file.rs index 7ab86c146c..010d190d23 100644 --- a/examples/send_file.rs +++ b/examples/send_file.rs @@ -1,10 +1,10 @@ #![deny(warnings)] -use tokio::io::AsyncReadExt; use tokio::fs::File; +use tokio::io::AsyncReadExt; -use hyper::{Body, Method, Result, Request, Response, Server, StatusCode}; use hyper::service::{make_service_fn, service_fn}; +use hyper::{Body, Method, Request, Response, Result, Server, StatusCode}; static INDEX: &str = "examples/send_file_index.html"; static INTERNAL_SERVER_ERROR: &[u8] = b"Internal Server Error"; @@ -16,12 +16,10 @@ async fn main() { let addr = "127.0.0.1:1337".parse().unwrap(); - let make_service = make_service_fn(|_| async { - Ok::<_, hyper::Error>(service_fn(response_examples)) - }); + let make_service = + make_service_fn(|_| async { Ok::<_, hyper::Error>(service_fn(response_examples)) }); - let server = Server::bind(&addr) - .serve(make_service); + let server = Server::bind(&addr).serve(make_service); println!("Listening on http://{}", addr); @@ -32,16 +30,14 @@ async fn main() { async fn response_examples(req: Request) -> Result> { match (req.method(), req.uri().path()) { - (&Method::GET, "/") | - (&Method::GET, "/index.html") | - (&Method::GET, "/big_file.html") => { + (&Method::GET, "/") | (&Method::GET, "/index.html") | (&Method::GET, "/big_file.html") => { simple_file_send(INDEX).await } (&Method::GET, "/no_file.html") => { // Test what happens when file cannot be be found simple_file_send("this_file_should_not_exist.html").await } - _ => Ok(not_found()) + _ => Ok(not_found()), } } diff --git a/examples/single_threaded.rs b/examples/single_threaded.rs index eb45448862..38a7052ca1 100644 --- a/examples/single_threaded.rs +++ b/examples/single_threaded.rs @@ -3,8 +3,8 @@ use std::cell::Cell; use std::rc::Rc; -use hyper::{Body, Error, Response, Server}; use hyper::service::{make_service_fn, service_fn}; +use hyper::{Body, Error, Response, Server}; fn main() { pretty_env_logger::init(); @@ -22,7 +22,6 @@ fn main() { } async fn run() { - let addr = ([127, 0, 0, 1], 3000).into(); // Using a !Send request counter is fine on 1 thread... @@ -37,18 +36,12 @@ async fn run() { let prev = cnt.get(); cnt.set(prev + 1); let value = cnt.get(); - async move { - Ok::<_, Error>(Response::new(Body::from( - format!("Request #{}", value) - ))) - } + async move { Ok::<_, Error>(Response::new(Body::from(format!("Request #{}", value)))) } })) } }); - let server = Server::bind(&addr) - .executor(LocalExec) - .serve(make_service); + let server = Server::bind(&addr).executor(LocalExec).serve(make_service); println!("Listening on http://{}", addr); diff --git a/examples/state.rs b/examples/state.rs index 0a70dc8e34..cb063b5a9a 100644 --- a/examples/state.rs +++ b/examples/state.rs @@ -1,9 +1,12 @@ #![deny(warnings)] -use std::sync::{Arc, atomic::{AtomicUsize, Ordering}}; +use std::sync::{ + atomic::{AtomicUsize, Ordering}, + Arc, +}; -use hyper::{Body, Error, Response, Server}; use hyper::service::{make_service_fn, service_fn}; +use hyper::{Body, Error, Response, Server}; #[tokio::main] async fn main() { @@ -34,17 +37,12 @@ async fn main() { // Get the current count, and also increment by 1, in a single // atomic operation. let count = counter.fetch_add(1, Ordering::AcqRel); - async move { - Ok::<_, Error>( - Response::new(Body::from(format!("Request #{}", count))) - ) - } + async move { Ok::<_, Error>(Response::new(Body::from(format!("Request #{}", count)))) } })) } }); - let server = Server::bind(&addr) - .serve(make_service); + let server = Server::bind(&addr).serve(make_service); println!("Listening on http://{}", addr); @@ -52,4 +50,3 @@ async fn main() { eprintln!("server error: {}", e); } } - diff --git a/examples/tower_client.rs b/examples/tower_client.rs index ce4a0348c4..5a2a6e78df 100644 --- a/examples/tower_client.rs +++ b/examples/tower_client.rs @@ -1,8 +1,8 @@ #![deny(warnings)] -use hyper::client::service::Connect; use hyper::client::conn::Builder; use hyper::client::connect::HttpConnector; +use hyper::client::service::Connect; use hyper::service::Service; use hyper::{Body, Request}; @@ -14,7 +14,6 @@ async fn main() -> Result<(), Box> { let uri = "http://127.0.0.1:8080".parse::()?; - let mut svc = mk_svc.call(uri.clone()).await?; let body = Body::empty(); diff --git a/examples/tower_server.rs b/examples/tower_server.rs index 76cdda326b..27510c88f8 100644 --- a/examples/tower_server.rs +++ b/examples/tower_server.rs @@ -3,8 +3,8 @@ use std::task::{Context, Poll}; use futures_util::future; -use hyper::{Body, Request, Response, Server}; use hyper::service::Service; +use hyper::{Body, Request, Response, Server}; const ROOT: &'static str = "/"; @@ -58,9 +58,7 @@ async fn main() -> Result<(), Box> { let addr = "127.0.0.1:1337".parse().unwrap(); - - let server = Server::bind(&addr) - .serve(MakeSvc); + let server = Server::bind(&addr).serve(MakeSvc); println!("Listening on http://{}", addr); diff --git a/examples/upgrades.rs b/examples/upgrades.rs index 7de90da73f..0bc75444a4 100644 --- a/examples/upgrades.rs +++ b/examples/upgrades.rs @@ -3,13 +3,13 @@ // Note: `hyper::upgrade` docs link to this upgrade. use std::str; -use tokio::sync::oneshot; use tokio::io::{AsyncReadExt, AsyncWriteExt}; +use tokio::sync::oneshot; -use hyper::{Body, Client, Request, Response, Server, StatusCode}; -use hyper::header::{UPGRADE, HeaderValue}; +use hyper::header::{HeaderValue, UPGRADE}; use hyper::service::{make_service_fn, service_fn}; use hyper::upgrade::Upgraded; +use hyper::{Body, Client, Request, Response, Server, StatusCode}; use std::net::SocketAddr; // A simple type alias so as to DRY. @@ -58,14 +58,15 @@ async fn server_upgrade(req: Request) -> Result> { eprintln!("server foobar io error: {}", e) }; } - Err(e) => eprintln!("upgrade error: {}", e) + Err(e) => eprintln!("upgrade error: {}", e), } }); // Now return a 101 Response saying we agree to the upgrade to some // made-up 'foobar' protocol. *res.status_mut() = StatusCode::SWITCHING_PROTOCOLS; - res.headers_mut().insert(UPGRADE, HeaderValue::from_static("foobar")); + res.headers_mut() + .insert(UPGRADE, HeaderValue::from_static("foobar")); Ok(res) } @@ -102,7 +103,7 @@ async fn client_upgrade_request(addr: SocketAddr) -> Result<()> { eprintln!("client foobar io error: {}", e) }; } - Err(e) => eprintln!("upgrade error: {}", e) + Err(e) => eprintln!("upgrade error: {}", e), } Ok(()) @@ -115,12 +116,10 @@ async fn main() { // unused port. let addr = ([127, 0, 0, 1], 0).into(); - let make_service = make_service_fn(|_| async { - Ok::<_, hyper::Error>(service_fn(server_upgrade)) - }); + let make_service = + make_service_fn(|_| async { Ok::<_, hyper::Error>(service_fn(server_upgrade)) }); - let server = Server::bind(&addr) - .serve(make_service); + let server = Server::bind(&addr).serve(make_service); // We need the assigned address for the client to send it messages. let addr = server.local_addr(); @@ -128,10 +127,9 @@ async fn main() { // For this example, a oneshot is used to signal that after 1 request, // the server should be shutdown. let (tx, rx) = oneshot::channel::<()>(); - let server = server - .with_graceful_shutdown(async move { - rx.await.ok(); - }); + let server = server.with_graceful_shutdown(async move { + rx.await.ok(); + }); // Spawn server on the default executor, // which is usually a thread-pool from tokio default runtime. diff --git a/examples/web_api.rs b/examples/web_api.rs index d7b393f9c0..ccdf2e93a1 100644 --- a/examples/web_api.rs +++ b/examples/web_api.rs @@ -1,9 +1,9 @@ #![deny(warnings)] -use hyper::{Body, Chunk, Client, Method, Request, Response, Server, StatusCode, header}; +use futures_util::{StreamExt, TryStreamExt}; use hyper::client::HttpConnector; use hyper::service::{make_service_fn, service_fn}; -use futures_util::{StreamExt, TryStreamExt}; +use hyper::{header, Body, Chunk, Client, Method, Request, Response, Server, StatusCode}; type GenericError = Box; type Result = std::result::Result; @@ -14,9 +14,7 @@ static NOTFOUND: &[u8] = b"Not Found"; static POST_DATA: &str = r#"{"original": "data"}"#; static URL: &str = "http://127.0.0.1:1337/json_api"; -async fn client_request_response( - client: &Client -) -> Result> { +async fn client_request_response(client: &Client) -> Result> { let req = Request::builder() .method(Method::POST) .uri(URL) @@ -27,9 +25,11 @@ async fn client_request_response( let web_res = client.request(req).await?; // Compare the JSON we sent (before) with what we received (after): let body = Body::wrap_stream(web_res.into_body().map_ok(|b| { - Chunk::from(format!("POST request body: {}
Response: {}", - POST_DATA, - std::str::from_utf8(&b).unwrap())) + Chunk::from(format!( + "POST request body: {}
Response: {}", + POST_DATA, + std::str::from_utf8(&b).unwrap() + )) })); Ok(Response::new(body)) @@ -57,40 +57,27 @@ async fn api_post_response(mut req: Request) -> Result> { async fn api_get_response() -> Result> { let data = vec!["foo", "bar"]; let res = match serde_json::to_string(&data) { - Ok(json) => { - Response::builder() - .header(header::CONTENT_TYPE, "application/json") - .body(Body::from(json)) - .unwrap() - } - Err(_) => { - Response::builder() - .status(StatusCode::INTERNAL_SERVER_ERROR) - .body(INTERNAL_SERVER_ERROR.into()) - .unwrap() - } + Ok(json) => Response::builder() + .header(header::CONTENT_TYPE, "application/json") + .body(Body::from(json)) + .unwrap(), + Err(_) => Response::builder() + .status(StatusCode::INTERNAL_SERVER_ERROR) + .body(INTERNAL_SERVER_ERROR.into()) + .unwrap(), }; Ok(res) } async fn response_examples( req: Request, - client: Client + client: Client, ) -> Result> { match (req.method(), req.uri().path()) { - (&Method::GET, "/") | - (&Method::GET, "/index.html") => { - Ok(Response::new(INDEX.into())) - }, - (&Method::GET, "/test.html") => { - client_request_response(&client).await - }, - (&Method::POST, "/json_api") => { - api_post_response(req).await - }, - (&Method::GET, "/json_api") => { - api_get_response().await - } + (&Method::GET, "/") | (&Method::GET, "/index.html") => Ok(Response::new(INDEX.into())), + (&Method::GET, "/test.html") => client_request_response(&client).await, + (&Method::POST, "/json_api") => api_post_response(req).await, + (&Method::GET, "/json_api") => api_get_response().await, _ => { // Return 404 not found response. Ok(Response::builder() @@ -121,8 +108,7 @@ async fn main() -> Result<()> { } }); - let server = Server::bind(&addr) - .serve(new_service); + let server = Server::bind(&addr).serve(new_service); println!("Listening on http://{}", addr); diff --git a/src/body/body.rs b/src/body/body.rs index 7e49a1dd51..23ca0282af 100644 --- a/src/body/body.rs +++ b/src/body/body.rs @@ -4,15 +4,15 @@ use std::error::Error as StdError; use std::fmt; use bytes::Bytes; -use futures_core::Stream; // for mpsc::Receiver use futures_channel::{mpsc, oneshot}; +use futures_core::Stream; // for mpsc::Receiver #[cfg(feature = "stream")] use futures_util::TryStreamExt; -use http_body::{SizeHint, Body as HttpBody}; use http::HeaderMap; +use http_body::{Body as HttpBody, SizeHint}; -use crate::common::{Future, Never, Pin, Poll, task}; use super::Chunk; +use crate::common::{task, Future, Never, Pin, Poll}; use crate::upgrade::OnUpgrade; type BodySender = mpsc::Sender>; @@ -44,7 +44,9 @@ enum Kind { // // See https://github.com/rust-lang/rust/issues/57017 #[cfg(feature = "stream")] - Wrapped(Pin>> + Send + Sync>>), + Wrapped( + Pin>> + Send + Sync>>, + ), } struct Extra { @@ -161,8 +163,7 @@ impl Body { /// /// See [the `upgrade` module](::upgrade) for more. pub fn on_upgrade(self) -> OnUpgrade { - self - .extra + self.extra .map(|ex| ex.on_upgrade) .unwrap_or_else(OnUpgrade::none) } @@ -193,54 +194,44 @@ impl Body { } fn take_delayed_eof(&mut self) -> Option { - self - .extra + self.extra .as_mut() .and_then(|extra| extra.delayed_eof.take()) } fn extra_mut(&mut self) -> &mut Extra { - self - .extra - .get_or_insert_with(|| Box::new(Extra { + self.extra.get_or_insert_with(|| { + Box::new(Extra { delayed_eof: None, on_upgrade: OnUpgrade::none(), - })) + }) + }) } fn poll_eof(&mut self, cx: &mut task::Context<'_>) -> Poll>> { match self.take_delayed_eof() { - Some(DelayEof::NotEof(mut delay)) => { - match self.poll_inner(cx) { - ok @ Poll::Ready(Some(Ok(..))) | - ok @ Poll::Pending => { - self.extra_mut().delayed_eof = Some(DelayEof::NotEof(delay)); - ok - }, - Poll::Ready(None) => match Pin::new(&mut delay).poll(cx) { - Poll::Ready(Ok(never)) => match never {}, - Poll::Pending => { - self.extra_mut().delayed_eof = Some(DelayEof::Eof(delay)); - Poll::Pending - }, - Poll::Ready(Err(_done)) => { - Poll::Ready(None) - }, - }, - Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(e))), + Some(DelayEof::NotEof(mut delay)) => match self.poll_inner(cx) { + ok @ Poll::Ready(Some(Ok(..))) | ok @ Poll::Pending => { + self.extra_mut().delayed_eof = Some(DelayEof::NotEof(delay)); + ok } - }, - Some(DelayEof::Eof(mut delay)) => { - match Pin::new(&mut delay).poll(cx) { + Poll::Ready(None) => match Pin::new(&mut delay).poll(cx) { Poll::Ready(Ok(never)) => match never {}, Poll::Pending => { self.extra_mut().delayed_eof = Some(DelayEof::Eof(delay)); Poll::Pending - }, - Poll::Ready(Err(_done)) => { - Poll::Ready(None) - }, + } + Poll::Ready(Err(_done)) => Poll::Ready(None), + }, + Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(e))), + }, + Some(DelayEof::Eof(mut delay)) => match Pin::new(&mut delay).poll(cx) { + Poll::Ready(Ok(never)) => match never {}, + Poll::Pending => { + self.extra_mut().delayed_eof = Some(DelayEof::Eof(delay)); + Poll::Pending } + Poll::Ready(Err(_done)) => Poll::Ready(None), }, None => self.poll_inner(cx), } @@ -268,25 +259,23 @@ impl Body { } None => Poll::Ready(None), } - }, + } Kind::H2 { recv: ref mut h2, .. } => match ready!(h2.poll_data(cx)) { Some(Ok(bytes)) => { let _ = h2.flow_control().release_capacity(bytes.len()); Poll::Ready(Some(Ok(Chunk::from(bytes)))) - }, + } Some(Err(e)) => Poll::Ready(Some(Err(crate::Error::new_body(e)))), None => Poll::Ready(None), }, #[cfg(feature = "stream")] - Kind::Wrapped(ref mut s) => { - match ready!(s.as_mut().poll_next(cx)) { - Some(res) => Poll::Ready(Some(res.map_err(crate::Error::new_body))), - None => Poll::Ready(None), - } - } + Kind::Wrapped(ref mut s) => match ready!(s.as_mut().poll_next(cx)) { + Some(res) => Poll::Ready(Some(res.map_err(crate::Error::new_body))), + None => Poll::Ready(None), + }, } } @@ -311,13 +300,21 @@ impl HttpBody for Body { type Data = Chunk; type Error = crate::Error; - fn poll_data(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll>> { + fn poll_data( + mut self: Pin<&mut Self>, + cx: &mut task::Context<'_>, + ) -> Poll>> { self.poll_eof(cx) } - fn poll_trailers(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll, Self::Error>> { + fn poll_trailers( + mut self: Pin<&mut Self>, + cx: &mut task::Context<'_>, + ) -> Poll, Self::Error>> { match self.kind { - Kind::H2 { recv: ref mut h2, .. } => match ready!(h2.poll_trailers(cx)) { + Kind::H2 { + recv: ref mut h2, .. + } => match ready!(h2.poll_trailers(cx)) { Ok(t) => Poll::Ready(Ok(t)), Err(e) => Poll::Ready(Err(crate::Error::new_h2(e))), }, @@ -341,10 +338,8 @@ impl HttpBody for Body { let mut hint = SizeHint::default(); hint.set_exact(val.len() as u64); hint - }, - Kind::Once(None) => { - SizeHint::default() - }, + } + Kind::Once(None) => SizeHint::default(), #[cfg(feature = "stream")] Kind::Wrapped(..) => SizeHint::default(), Kind::Chan { content_length, .. } | Kind::H2 { content_length, .. } => { @@ -355,7 +350,7 @@ impl HttpBody for Body { } hint - }, + } } } } @@ -393,14 +388,12 @@ impl Stream for Body { } } - /// # Optional /// /// This function requires enabling the `stream` feature in your /// `Cargo.toml`. #[cfg(feature = "stream")] -impl - From>> + Send + Sync>> +impl From>> + Send + Sync>> for Body { #[inline] @@ -487,13 +480,17 @@ impl Sender { Poll::Pending => (), // fallthrough } - self.tx.poll_ready(cx).map_err(|_| crate::Error::new_closed()) + self.tx + .poll_ready(cx) + .map_err(|_| crate::Error::new_closed()) } /// Send data on this channel when it is ready. pub async fn send_data(&mut self, chunk: Chunk) -> crate::Result<()> { futures_util::future::poll_fn(|cx| self.poll_ready(cx)).await?; - self.tx.try_send(Ok(chunk)).map_err(|_| crate::Error::new_closed()) + self.tx + .try_send(Ok(chunk)) + .map_err(|_| crate::Error::new_closed()) } /// Try to send data on this channel. diff --git a/src/body/chunk.rs b/src/body/chunk.rs index 4a1680e653..aa3bd10c36 100644 --- a/src/body/chunk.rs +++ b/src/body/chunk.rs @@ -19,7 +19,6 @@ pub struct IntoIter { inner: ::IntoIter, } - impl Chunk { /// Converts this `Chunk` directly into the `Bytes` type without copies. /// @@ -82,9 +81,7 @@ impl From<&'static str> for Chunk { impl From for Chunk { #[inline] fn from(bytes: Bytes) -> Chunk { - Chunk { - bytes: bytes, - } + Chunk { bytes: bytes } } } @@ -176,4 +173,3 @@ mod tests { }) } } - diff --git a/src/body/mod.rs b/src/body/mod.rs index 2f1f983235..0fd3170a7a 100644 --- a/src/body/mod.rs +++ b/src/body/mod.rs @@ -59,4 +59,3 @@ fn _assert_send_sync() { _assert_send::(); _assert_sync::(); } - diff --git a/src/body/payload.rs b/src/body/payload.rs index 86fa385e9d..9ca2a35877 100644 --- a/src/body/payload.rs +++ b/src/body/payload.rs @@ -3,7 +3,7 @@ use std::error::Error as StdError; use bytes::Buf; use http::HeaderMap; -use crate::common::{Pin, Poll, task}; +use crate::common::{task, Pin, Poll}; use http_body::{Body as HttpBody, SizeHint}; /// This trait represents a streaming body of a `Request` or `Response`. @@ -21,14 +21,20 @@ pub trait Payload: sealed::Sealed + Send + 'static { /// /// Similar to `Stream::poll_next`, this yields `Some(Data)` until /// the body ends, when it yields `None`. - fn poll_data(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll>>; + fn poll_data( + self: Pin<&mut Self>, + cx: &mut task::Context<'_>, + ) -> Poll>>; /// Poll for an optional **single** `HeaderMap` of trailers. /// /// This should **only** be called after `poll_data` has ended. /// /// Note: Trailers aren't currently used for HTTP/1, only for HTTP/2. - fn poll_trailers(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll, Self::Error>> { + fn poll_trailers( + self: Pin<&mut Self>, + cx: &mut task::Context<'_>, + ) -> Poll, Self::Error>> { drop(cx); Poll::Ready(Ok(None)) } @@ -61,7 +67,6 @@ pub trait Payload: sealed::Sealed + Send + 'static { } } - impl Payload for T where T: HttpBody + Send + 'static, @@ -71,11 +76,17 @@ where type Data = T::Data; type Error = T::Error; - fn poll_data(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll>> { + fn poll_data( + self: Pin<&mut Self>, + cx: &mut task::Context<'_>, + ) -> Poll>> { HttpBody::poll_data(self, cx) } - fn poll_trailers(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll, Self::Error>> { + fn poll_trailers( + self: Pin<&mut Self>, + cx: &mut task::Context<'_>, + ) -> Poll, Self::Error>> { HttpBody::poll_trailers(self, cx) } @@ -127,5 +138,3 @@ impl Payload for Box { } } */ - - diff --git a/src/client/conn.rs b/src/client/conn.rs index c443235362..a43f3bd791 100644 --- a/src/client/conn.rs +++ b/src/client/conn.rs @@ -17,19 +17,14 @@ use pin_project::{pin_project, project}; use tokio::io::{AsyncRead, AsyncWrite}; use tower_service::Service; +use super::dispatch; use crate::body::Payload; -use crate::common::{BoxSendFuture, Exec, Executor, Future, Pin, Poll, task}; -use crate::upgrade::Upgraded; +use crate::common::{task, BoxSendFuture, Exec, Executor, Future, Pin, Poll}; use crate::proto; -use super::dispatch; +use crate::upgrade::Upgraded; use crate::{Body, Request, Response}; -type Http1Dispatcher = proto::dispatch::Dispatcher< - proto::dispatch::Client, - B, - T, - R, ->; +type Http1Dispatcher = proto::dispatch::Dispatcher, B, T, R>; #[pin_project] enum ProtoClient @@ -46,18 +41,16 @@ where const DEFAULT_HTTP2_CONN_WINDOW: u32 = 1024 * 1024 * 5; // 5mb const DEFAULT_HTTP2_STREAM_WINDOW: u32 = 1024 * 1024 * 2; // 2mb - - /// Returns a handshake future over some IO. /// /// This is a shortcut for `Builder::new().handshake(io)`. -pub async fn handshake(io: T) -> crate::Result<(SendRequest, Connection)> +pub async fn handshake( + io: T, +) -> crate::Result<(SendRequest, Connection)> where T: AsyncRead + AsyncWrite + Unpin + Send + 'static, { - Builder::new() - .handshake(io) - .await + Builder::new().handshake(io).await } /// The sender side of an established connection. @@ -65,7 +58,6 @@ pub struct SendRequest { dispatch: dispatch::Sender, Response>, } - /// A future that processes all HTTP state for the IO object. /// /// In most cases, this should just be spawned into an executor, so that it @@ -79,7 +71,6 @@ where inner: Option>, } - /// A builder to configure an HTTP connection. /// /// After setting options, the builder is used to create a handshake future. @@ -99,7 +90,7 @@ pub struct Builder { /// Yields a `Response` if successful. #[must_use = "futures do nothing unless polled"] pub struct ResponseFuture { - inner: ResponseFutureState + inner: ResponseFutureState, } enum ResponseFutureState { @@ -139,8 +130,7 @@ pub(super) struct Http2SendRequest { // ===== impl SendRequest -impl SendRequest -{ +impl SendRequest { /// Polls to determine whether this sender can be used yet for a request. /// /// If the associated connection is closed, this returns an Error. @@ -148,7 +138,7 @@ impl SendRequest self.dispatch.poll_ready(cx) } - pub(super) fn when_ready(self) -> impl Future> { + pub(super) fn when_ready(self) -> impl Future> { let mut me = Some(self); future::poll_fn(move |cx| { ready!(me.as_mut().unwrap().poll_ready(cx))?; @@ -218,9 +208,7 @@ where /// ``` pub fn send_request(&mut self, req: Request) -> ResponseFuture { let inner = match self.dispatch.send(req) { - Ok(rx) => { - ResponseFutureState::Waiting(rx) - }, + Ok(rx) => ResponseFutureState::Waiting(rx), Err(_req) => { debug!("connection was not ready"); let err = crate::Error::new_canceled().with("connection was not ready"); @@ -228,12 +216,13 @@ where } }; - ResponseFuture { - inner, - } + ResponseFuture { inner } } - pub(crate) fn send_request_retryable(&mut self, req: Request) -> impl Future, (crate::Error, Option>)>> + Unpin + pub(crate) fn send_request_retryable( + &mut self, + req: Request, + ) -> impl Future, (crate::Error, Option>)>> + Unpin where B: Send, { @@ -247,7 +236,7 @@ where Err(_) => panic!("dispatch dropped without returning error"), } })) - }, + } Err(req) => { debug!("connection was not ready"); let err = crate::Error::new_canceled().with("connection was not ready"); @@ -259,7 +248,8 @@ where impl Service> for SendRequest where - B: Payload + 'static, { + B: Payload + 'static, +{ type Response = Response; type Error = crate::Error; type Future = ResponseFuture; @@ -275,8 +265,7 @@ where impl fmt::Debug for SendRequest { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("SendRequest") - .finish() + f.debug_struct("SendRequest").finish() } } @@ -296,7 +285,10 @@ impl Http2SendRequest where B: Payload + 'static, { - pub(super) fn send_request_retryable(&mut self, req: Request) -> impl Future, (crate::Error, Option>)>> + pub(super) fn send_request_retryable( + &mut self, + req: Request, + ) -> impl Future, (crate::Error, Option>)>> where B: Send, { @@ -310,7 +302,7 @@ where Err(_) => panic!("dispatch dropped without returning error"), } })) - }, + } Err(req) => { debug!("connection was not ready"); let err = crate::Error::new_canceled().with("connection was not ready"); @@ -322,8 +314,7 @@ where impl fmt::Debug for Http2SendRequest { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Http2SendRequest") - .finish() + f.debug_struct("Http2SendRequest").finish() } } @@ -374,18 +365,14 @@ where /// to work with this function; or use the `without_shutdown` wrapper. pub fn poll_without_shutdown(&mut self, cx: &mut task::Context<'_>) -> Poll> { match self.inner.as_mut().expect("already upgraded") { - &mut ProtoClient::H1(ref mut h1) => { - h1.poll_without_shutdown(cx) - }, - &mut ProtoClient::H2(ref mut h2) => { - Pin::new(h2).poll(cx).map_ok(|_| ()) - } + &mut ProtoClient::H1(ref mut h1) => h1.poll_without_shutdown(cx), + &mut ProtoClient::H2(ref mut h2) => Pin::new(h2).poll(cx).map_ok(|_| ()), } } /// Prevent shutdown of the underlying IO object at the end of service the request, /// instead run `into_parts`. This is a convenience wrapper over `poll_without_shutdown`. - pub fn without_shutdown(self) -> impl Future>> { + pub fn without_shutdown(self) -> impl Future>> { let mut conn = Some(self); future::poll_fn(move |cx| -> Poll>> { ready!(conn.as_mut().unwrap().poll_without_shutdown(cx))?; @@ -404,9 +391,7 @@ where fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll { match ready!(Pin::new(self.inner.as_mut().unwrap()).poll(cx))? { - proto::Dispatched::Shutdown => { - Poll::Ready(Ok(())) - }, + proto::Dispatched::Shutdown => Poll::Ready(Ok(())), proto::Dispatched::Upgrade(pending) => { let h1 = match mem::replace(&mut self.inner, None) { Some(ProtoClient::H1(h1)) => h1, @@ -427,8 +412,7 @@ where B: Payload + 'static, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Connection") - .finish() + f.debug_struct("Connection").finish() } } @@ -519,7 +503,10 @@ impl Builder { /// Passing `None` will do nothing. /// /// If not set, hyper will use a default. - pub fn http2_initial_connection_window_size(&mut self, sz: impl Into>) -> &mut Self { + pub fn http2_initial_connection_window_size( + &mut self, + sz: impl Into>, + ) -> &mut Self { if let Some(sz) = sz.into() { self.h2_builder.initial_connection_window_size(sz); } @@ -527,7 +514,10 @@ impl Builder { } /// Constructs a connection with the configured options and IO. - pub fn handshake(&self, io: T) -> impl Future, Connection)>> + pub fn handshake( + &self, + io: T, + ) -> impl Future, Connection)>> where T: AsyncRead + AsyncWrite + Unpin + Send + 'static, B: Payload + 'static, @@ -563,12 +553,8 @@ impl Builder { }; Ok(( - SendRequest { - dispatch: tx, - }, - Connection { - inner: Some(proto), - }, + SendRequest { dispatch: tx }, + Connection { inner: Some(proto) }, )) } } @@ -588,7 +574,7 @@ impl Future for ResponseFuture { // this is definite bug if it happens, but it shouldn't happen! Err(_canceled) => panic!("dispatch dropped without returning error"), }) - }, + } ResponseFutureState::Error(ref mut err) => { Poll::Ready(Err(err.take().expect("polled after ready"))) } @@ -598,8 +584,7 @@ impl Future for ResponseFuture { impl fmt::Debug for ResponseFuture { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("ResponseFuture") - .finish() + f.debug_struct("ResponseFuture").finish() } } @@ -628,7 +613,6 @@ where trait AssertSend: Send {} trait AssertSendSync: Send + Sync {} - #[doc(hidden)] impl AssertSendSync for SendRequest {} @@ -637,7 +621,8 @@ impl AssertSend for Connection where T: AsyncRead + AsyncWrite + Send + 'static, B: Payload + 'static, -{} +{ +} #[doc(hidden)] impl AssertSendSync for Connection @@ -645,11 +630,11 @@ where T: AsyncRead + AsyncWrite + Send + 'static, B: Payload + 'static, B::Data: Send + Sync + 'static, -{} +{ +} #[doc(hidden)] impl AssertSendSync for Builder {} #[doc(hidden)] impl AssertSend for ResponseFuture {} - diff --git a/src/client/connect/dns.rs b/src/client/connect/dns.rs index 3b8c44eacf..2898c59253 100644 --- a/src/client/connect/dns.rs +++ b/src/client/connect/dns.rs @@ -22,11 +22,11 @@ //! }); //! ``` use std::error::Error; +use std::future::Future; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs}; +use std::pin::Pin; use std::str::FromStr; use std::task::{self, Poll}; -use std::pin::Pin; -use std::future::Future; use std::{fmt, io, vec}; use tokio::task::JoinHandle; @@ -394,7 +394,8 @@ mod tests { let dst = ::http::Uri::from_static("http://[::1]:8080/"); let mut addrs = - IpAddrs::try_parse(dst.host().expect("host"), dst.port_u16().expect("port")).expect("try_parse"); + IpAddrs::try_parse(dst.host().expect("host"), dst.port_u16().expect("port")) + .expect("try_parse"); let expected = "[::1]:8080".parse::().expect("expected"); diff --git a/src/client/connect/http.rs b/src/client/connect/http.rs index 4daeeca3c9..08a0876784 100644 --- a/src/client/connect/http.rs +++ b/src/client/connect/http.rs @@ -1,12 +1,12 @@ use std::error::Error as StdError; -use std::future::Future; -use std::marker::PhantomData; -use std::pin::Pin; -use std::task::{self, Poll}; use std::fmt; +use std::future::Future; use std::io; +use std::marker::PhantomData; use std::net::{IpAddr, SocketAddr}; +use std::pin::Pin; use std::sync::Arc; +use std::task::{self, Poll}; use std::time::Duration; use futures_util::future::Either; @@ -20,7 +20,6 @@ use super::dns::{self, resolve, GaiResolver, Resolve}; use super::{Connected, Connection}; //#[cfg(feature = "runtime")] use super::dns::TokioThreadpoolGaiResolver; - /// A connector for the `http` scheme. /// /// Performs DNS resolution in a thread pool, and then connects over TCP. @@ -256,10 +255,7 @@ impl HttpConnector where R: Resolve, { - async fn call_async( - &mut self, - dst: Uri, - ) -> Result { + async fn call_async(&mut self, dst: Uri) -> Result { trace!( "Http::connect; scheme={:?}, host={:?}, port={:?}", dst.scheme(), @@ -292,7 +288,13 @@ where }; let port = match dst.port() { Some(port) => port.as_u16(), - None => if dst.scheme() == Some(&Scheme::HTTPS) { 443 } else { 80 }, + None => { + if dst.scheme() == Some(&Scheme::HTTPS) { + 443 + } else { + 80 + } + } }; let config = &self.config; @@ -348,9 +350,7 @@ impl Connection for TcpStream { fn connected(&self) -> Connected { let connected = Connected::new(); if let Ok(remote_addr) = self.peer_addr() { - connected.extra(HttpInfo { - remote_addr, - }) + connected.extra(HttpInfo { remote_addr }) } else { connected } @@ -389,7 +389,6 @@ impl Future for HttpConnecting { } } - // Not publicly exported (so missing_docs doesn't trigger). pub struct ConnectError { msg: Box, @@ -531,14 +530,7 @@ impl ConnectingTcpRemote { let mut err = None; for addr in &mut self.addrs { debug!("connecting to {}", addr); - match connect( - &addr, - local_addr, - reuse_address, - self.connect_timeout, - )? - .await - { + match connect(&addr, local_addr, reuse_address, self.connect_timeout)?.await { Ok(tcp) => { debug!("connected to {:?}", tcp.peer_addr().ok()); return Ok(tcp); @@ -606,13 +598,9 @@ impl ConnectingTcp { .. } = self; match self.fallback { - None => { - self.preferred - .connect(local_addr, reuse_address) - .await - } + None => self.preferred.connect(local_addr, reuse_address).await, Some(mut fallback) => { - let preferred_fut = self.preferred.connect(local_addr, reuse_address); + let preferred_fut = self.preferred.connect(local_addr, reuse_address); futures_util::pin_mut!(preferred_fut); let fallback_fut = fallback.remote.connect(local_addr, reuse_address); @@ -652,10 +640,7 @@ mod tests { use super::super::sealed::Connect; use super::HttpConnector; - async fn connect( - connector: C, - dst: Uri, - ) -> Result + async fn connect(connector: C, dst: Uri) -> Result where C: Connect, { @@ -795,7 +780,6 @@ mod tests { continue; } - let (start, stream) = rt .block_on(async move { let addrs = hosts diff --git a/src/client/connect/mod.rs b/src/client/connect/mod.rs index 0d53395285..65a690361b 100644 --- a/src/client/connect/mod.rs +++ b/src/client/connect/mod.rs @@ -7,11 +7,14 @@ //! - Types to build custom connectors. use std::fmt; -use ::http::{Response}; +use ::http::Response; -#[cfg(feature = "tcp")] pub mod dns; -#[cfg(feature = "tcp")] mod http; -#[cfg(feature = "tcp")] pub use self::http::{HttpConnector, HttpInfo}; +#[cfg(feature = "tcp")] +pub mod dns; +#[cfg(feature = "tcp")] +mod http; +#[cfg(feature = "tcp")] +pub use self::http::{HttpConnector, HttpInfo}; /// Describes a type returned by a connector. pub trait Connection { @@ -115,8 +118,7 @@ impl Clone for Extra { impl fmt::Debug for Extra { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Extra") - .finish() + f.debug_struct("Extra").finish() } } @@ -133,7 +135,7 @@ struct ExtraEnvelope(T); impl ExtraInner for ExtraEnvelope where - T: Clone + Send + Sync + 'static + T: Clone + Send + Sync + 'static, { fn clone_box(&self) -> Box { Box::new(self.clone()) @@ -154,7 +156,7 @@ impl Clone for ExtraChain { impl ExtraInner for ExtraChain where - T: Clone + Send + Sync + 'static + T: Clone + Send + Sync + 'static, { fn clone_box(&self) -> Box { Box::new(self.clone()) @@ -172,8 +174,8 @@ pub(super) mod sealed { use ::http::Uri; use tokio::io::{AsyncRead, AsyncWrite}; + use super::Connection; use crate::common::{Future, Unpin}; - use super::{Connection}; /// Connect to a destination, returning an IO transport. /// @@ -193,14 +195,14 @@ pub(super) mod sealed { /// An error occured when trying to connect. type Error: Into>; /// A Future that will resolve to the connected Transport. - type Future: Future>; + type Future: Future>; #[doc(hidden)] fn connect(self, internal_only: Internal, dst: Uri) -> Self::Future; } impl Connect for S where - S: tower_service::Service + Send, + S: tower_service::Service + Send, S::Error: Into>, S::Future: Unpin + Send, T: AsyncRead + AsyncWrite + Connection + Unpin + Send + 'static, @@ -215,11 +217,12 @@ pub(super) mod sealed { impl Sealed for S where - S: tower_service::Service + Send, + S: tower_service::Service + Send, S::Error: Into>, S::Future: Unpin + Send, T: AsyncRead + AsyncWrite + Connection + Unpin + Send + 'static, - {} + { + } pub trait Sealed {} #[allow(missing_debug_implementations)] @@ -228,7 +231,7 @@ pub(super) mod sealed { #[cfg(test)] mod tests { - use super::{Connected}; + use super::Connected; #[derive(Clone, Debug, PartialEq)] struct Ex1(usize); @@ -241,18 +244,13 @@ mod tests { #[test] fn test_connected_extra() { - let c1 = Connected::new() - .extra(Ex1(41)); + let c1 = Connected::new().extra(Ex1(41)); let mut res1 = crate::Response::new(crate::Body::empty()); assert_eq!(res1.extensions().get::(), None); - c1 - .extra - .as_ref() - .expect("c1 extra") - .set(&mut res1); + c1.extra.as_ref().expect("c1 extra").set(&mut res1); assert_eq!(res1.extensions().get::(), Some(&Ex1(41))); } @@ -273,11 +271,7 @@ mod tests { assert_eq!(res1.extensions().get::(), None); assert_eq!(res1.extensions().get::(), None); - c1 - .extra - .as_ref() - .expect("c1 extra") - .set(&mut res1); + c1.extra.as_ref().expect("c1 extra").set(&mut res1); assert_eq!(res1.extensions().get::(), Some(&Ex1(45))); assert_eq!(res1.extensions().get::(), Some(&Ex2("zoom"))); @@ -291,11 +285,7 @@ mod tests { let mut res2 = crate::Response::new(crate::Body::empty()); - c2 - .extra - .as_ref() - .expect("c2 extra") - .set(&mut res2); + c2.extra.as_ref().expect("c2 extra").set(&mut res2); assert_eq!(res2.extensions().get::(), Some(&Ex1(99))); assert_eq!(res2.extensions().get::(), Some(&Ex2("hiccup"))); diff --git a/src/client/dispatch.rs b/src/client/dispatch.rs index ecd453e629..5ab8a257bb 100644 --- a/src/client/dispatch.rs +++ b/src/client/dispatch.rs @@ -1,8 +1,8 @@ -use futures_core::Stream; use futures_channel::{mpsc, oneshot}; +use futures_core::Stream; use futures_util::future; -use crate::common::{Future, Pin, Poll, task}; +use crate::common::{task, Future, Pin, Poll}; pub type RetryPromise = oneshot::Receiver)>>; pub type Promise = oneshot::Receiver>; @@ -52,7 +52,8 @@ pub struct UnboundedSender { impl Sender { pub fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll> { - self.giver.poll_want(cx) + self.giver + .poll_want(cx) .map_err(|_| crate::Error::new_closed()) } @@ -82,7 +83,8 @@ impl Sender { return Err(val); } let (tx, rx) = oneshot::channel(); - self.inner.unbounded_send(Envelope(Some((val, Callback::Retry(tx))))) + self.inner + .unbounded_send(Envelope(Some((val, Callback::Retry(tx))))) .map(move |_| rx) .map_err(|e| e.into_inner().0.take().expect("envelope not dropped").0) } @@ -92,7 +94,8 @@ impl Sender { return Err(val); } let (tx, rx) = oneshot::channel(); - self.inner.unbounded_send(Envelope(Some((val, Callback::NoRetry(tx))))) + self.inner + .unbounded_send(Envelope(Some((val, Callback::NoRetry(tx))))) .map(move |_| rx) .map_err(|e| e.into_inner().0.take().expect("envelope not dropped").0) } @@ -116,7 +119,8 @@ impl UnboundedSender { pub fn try_send(&mut self, val: T) -> Result, T> { let (tx, rx) = oneshot::channel(); - self.inner.unbounded_send(Envelope(Some((val, Callback::Retry(tx))))) + self.inner + .unbounded_send(Envelope(Some((val, Callback::Retry(tx))))) .map(move |_| rx) .map_err(|e| e.into_inner().0.take().expect("envelope not dropped").0) } @@ -137,15 +141,18 @@ pub struct Receiver { } impl Receiver { - pub(crate) fn poll_next(&mut self, cx: &mut task::Context<'_>) -> Poll)>> { + pub(crate) fn poll_next( + &mut self, + cx: &mut task::Context<'_>, + ) -> Poll)>> { match Pin::new(&mut self.inner).poll_next(cx) { - Poll::Ready(item) => Poll::Ready(item.map(|mut env| { - env.0.take().expect("envelope not dropped") - })), + Poll::Ready(item) => { + Poll::Ready(item.map(|mut env| env.0.take().expect("envelope not dropped"))) + } Poll::Pending => { self.taker.want(); Poll::Pending - }, + } } } @@ -176,7 +183,10 @@ struct Envelope(Option<(T, Callback)>); impl Drop for Envelope { fn drop(&mut self) { if let Some((val, cb)) = self.0.take() { - let _ = cb.send(Err((crate::Error::new_canceled().with("connection closed"), Some(val)))); + let _ = cb.send(Err(( + crate::Error::new_canceled().with("connection closed"), + Some(val), + ))); } } } @@ -205,7 +215,7 @@ impl Callback { match self { Callback::Retry(tx) => { let _ = tx.send(val); - }, + } Callback::NoRetry(tx) => { let _ = tx.send(val.map_err(|e| e.0)); } @@ -214,29 +224,25 @@ impl Callback { pub(crate) fn send_when( self, - mut when: impl Future)>> + Unpin, - ) -> impl Future { + mut when: impl Future)>> + Unpin, + ) -> impl Future { let mut cb = Some(self); // "select" on this callback being canceled, and the future completing future::poll_fn(move |cx| { match Pin::new(&mut when).poll(cx) { Poll::Ready(Ok(res)) => { - cb.take() - .expect("polled after complete") - .send(Ok(res)); + cb.take().expect("polled after complete").send(Ok(res)); Poll::Ready(()) - }, + } Poll::Pending => { // check if the callback is canceled ready!(cb.as_mut().unwrap().poll_canceled(cx)); trace!("send_when canceled"); Poll::Ready(()) - }, + } Poll::Ready(Err(err)) => { - cb.take() - .expect("polled after complete") - .send(Err(err)); + cb.take().expect("polled after complete").send(Err(err)); Poll::Ready(()) } } @@ -253,7 +259,7 @@ mod tests { use std::pin::Pin; use std::task::{Context, Poll}; - use super::{Callback, channel, Receiver}; + use super::{channel, Callback, Receiver}; #[derive(Debug)] struct Custom(i32); @@ -271,14 +277,14 @@ mod tests { impl Future for PollOnce<'_, F> where - F: Future + Unpin + F: Future + Unpin, { type Output = Option<()>; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { match Pin::new(&mut self.0).poll(cx) { Poll::Ready(_) => Poll::Ready(Some(())), - Poll::Pending => Poll::Ready(None) + Poll::Pending => Poll::Ready(None), } } } @@ -357,7 +363,7 @@ mod tests { let poll_once = PollOnce(&mut rx); let opt = poll_once.await; if opt.is_none() { - break + break; } } }); diff --git a/src/client/mod.rs b/src/client/mod.rs index 1054ec2882..f53cef554d 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -64,17 +64,18 @@ use std::sync::Arc; use std::time::Duration; use futures_channel::oneshot; -use futures_util::future::{self, FutureExt as _, TryFutureExt as _, Either}; -use http::{Method, Request, Response, Uri, Version}; +use futures_util::future::{self, Either, FutureExt as _, TryFutureExt as _}; use http::header::{HeaderValue, HOST}; use http::uri::Scheme; +use http::{Method, Request, Response, Uri, Version}; -use crate::body::{Body, Payload}; -use crate::common::{lazy as hyper_lazy, BoxSendFuture, Executor, Lazy, Future, Pin, Poll, task}; -use self::connect::{Alpn, sealed::Connect, Connected, Connection}; +use self::connect::{sealed::Connect, Alpn, Connected, Connection}; use self::pool::{Key as PoolKey, Pool, Poolable, Pooled, Reservation}; +use crate::body::{Body, Payload}; +use crate::common::{lazy as hyper_lazy, task, BoxSendFuture, Executor, Future, Lazy, Pin, Poll}; -#[cfg(feature = "tcp")] pub use self::connect::HttpConnector; +#[cfg(feature = "tcp")] +pub use self::connect::HttpConnector; pub mod conn; pub mod connect; @@ -104,7 +105,7 @@ struct Config { /// This is returned by `Client::request` (and `Client::get`). #[must_use = "futures do nothing unless polled"] pub struct ResponseFuture { - inner: Pin>> + Send>>, + inner: Pin>> + Send>>, } // ===== impl Client ===== @@ -157,11 +158,12 @@ impl Client<(), Body> { } impl Client -where C: Connect + Clone + Send + Sync + 'static, - C::Transport: Unpin + Send + 'static, - C::Future: Unpin + Send + 'static, - B: Payload + Unpin + Send + 'static, - B::Data: Send + Unpin, +where + C: Connect + Clone + Send + Sync + 'static, + C::Transport: Unpin + Send + 'static, + C::Future: Unpin + Send + 'static, + B: Payload + Unpin + Send + 'static, + B::Data: Send + Unpin, { /// Send a `GET` request to the supplied `Uri`. /// @@ -223,13 +225,19 @@ where C: Connect + Clone + Send + Sync + 'static, let is_http_connect = req.method() == &Method::CONNECT; match req.version() { Version::HTTP_11 => (), - Version::HTTP_10 => if is_http_connect { - warn!("CONNECT is not allowed for HTTP/1.0"); - return ResponseFuture::new(Box::new(future::err(crate::Error::new_user_unsupported_request_method()))); - }, - other_h2 @ Version::HTTP_2 => if self.config.ver != Ver::Http2 { - return ResponseFuture::error_version(other_h2); - }, + Version::HTTP_10 => { + if is_http_connect { + warn!("CONNECT is not allowed for HTTP/1.0"); + return ResponseFuture::new(Box::new(future::err( + crate::Error::new_user_unsupported_request_method(), + ))); + } + } + other_h2 @ Version::HTTP_2 => { + if self.config.ver != Ver::Http2 { + return ResponseFuture::error_version(other_h2); + } + } // completely unsupported HTTP version (like HTTP/0.9)! other => return ResponseFuture::error_version(other), }; @@ -245,7 +253,11 @@ where C: Connect + Clone + Send + Sync + 'static, ResponseFuture::new(Box::new(self.retryably_send_request(req, pool_key))) } - fn retryably_send_request(&self, req: Request, pool_key: PoolKey) -> impl Future>> { + fn retryably_send_request( + &self, + req: Request, + pool_key: PoolKey, + ) -> impl Future>> { let client = self.clone(); let uri = req.uri().clone(); @@ -265,7 +277,10 @@ where C: Connect + Clone + Send + Sync + 'static, return Poll::Ready(Err(reason)); } - trace!("unstarted request canceled, trying again (reason={:?})", reason); + trace!( + "unstarted request canceled, trying again (reason={:?})", + reason + ); *req.uri_mut() = uri.clone(); send_fut = client.send_request(req, pool_key.clone()); } @@ -273,7 +288,11 @@ where C: Connect + Clone + Send + Sync + 'static, }) } - fn send_request(&self, mut req: Request, pool_key: PoolKey) -> impl Future, ClientError>> + Unpin { + fn send_request( + &self, + mut req: Request, + pool_key: PoolKey, + ) -> impl Future, ClientError>> + Unpin { let conn = self.connection_for(req.uri().clone(), pool_key); let set_host = self.config.set_host; @@ -282,18 +301,16 @@ where C: Connect + Clone + Send + Sync + 'static, if pooled.is_http1() { if set_host { let uri = req.uri().clone(); - req - .headers_mut() - .entry(HOST) - .or_insert_with(|| { - let hostname = uri.host().expect("authority implies host"); - if let Some(port) = uri.port() { - let s = format!("{}:{}", hostname, port); - HeaderValue::from_str(&s) - } else { - HeaderValue::from_str(hostname) - }.expect("uri host is valid header value") - }); + req.headers_mut().entry(HOST).or_insert_with(|| { + let hostname = uri.host().expect("authority implies host"); + if let Some(port) = uri.port() { + let s = format!("{}:{}", hostname, port); + HeaderValue::from_str(&s) + } else { + HeaderValue::from_str(hostname) + } + .expect("uri host is valid header value") + }); } // CONNECT always sends authority-form, so check it first... @@ -306,10 +323,13 @@ where C: Connect + Clone + Send + Sync + 'static, }; } else if req.method() == &Method::CONNECT { debug!("client does not support CONNECT requests over HTTP2"); - return Either::Left(future::err(ClientError::Normal(crate::Error::new_user_unsupported_request_method()))); + return Either::Left(future::err(ClientError::Normal( + crate::Error::new_user_unsupported_request_method(), + ))); } - let fut = pooled.send_request_retryable(req) + let fut = pooled + .send_request_retryable(req) .map_err(ClientError::map_with_reused(pooled.is_reused())); // If the Connector included 'extra' info, add to Response... @@ -332,51 +352,46 @@ where C: Connect + Clone + Send + Sync + 'static, return Either::Right(Either::Left(fut)); } - Either::Right(Either::Right(fut - .map_ok(move |mut res| { - // If pooled is HTTP/2, we can toss this reference immediately. - // - // when pooled is dropped, it will try to insert back into the - // pool. To delay that, spawn a future that completes once the - // sender is ready again. - // - // This *should* only be once the related `Connection` has polled - // for a new request to start. - // - // It won't be ready if there is a body to stream. - if pooled.is_http2() || !pooled.is_pool_enabled() || pooled.is_ready() { - drop(pooled); - } else if !res.body().is_end_stream() { - let (delayed_tx, delayed_rx) = oneshot::channel(); - res.body_mut().delayed_eof(delayed_rx); - let on_idle = future::poll_fn(move |cx| { - pooled.poll_ready(cx) - }) - .map(move |_| { - // At this point, `pooled` is dropped, and had a chance - // to insert into the pool (if conn was idle) - drop(delayed_tx); - }); - - executor.execute(on_idle); - } else { - // There's no body to delay, but the connection isn't - // ready yet. Only re-insert when it's ready - let on_idle = future::poll_fn(move |cx| { - pooled.poll_ready(cx) - }) - .map(|_| ()); + Either::Right(Either::Right(fut.map_ok(move |mut res| { + // If pooled is HTTP/2, we can toss this reference immediately. + // + // when pooled is dropped, it will try to insert back into the + // pool. To delay that, spawn a future that completes once the + // sender is ready again. + // + // This *should* only be once the related `Connection` has polled + // for a new request to start. + // + // It won't be ready if there is a body to stream. + if pooled.is_http2() || !pooled.is_pool_enabled() || pooled.is_ready() { + drop(pooled); + } else if !res.body().is_end_stream() { + let (delayed_tx, delayed_rx) = oneshot::channel(); + res.body_mut().delayed_eof(delayed_rx); + let on_idle = future::poll_fn(move |cx| pooled.poll_ready(cx)).map(move |_| { + // At this point, `pooled` is dropped, and had a chance + // to insert into the pool (if conn was idle) + drop(delayed_tx); + }); + + executor.execute(on_idle); + } else { + // There's no body to delay, but the connection isn't + // ready yet. Only re-insert when it's ready + let on_idle = future::poll_fn(move |cx| pooled.poll_ready(cx)).map(|_| ()); - executor.execute(on_idle); - } - res - }))) + executor.execute(on_idle); + } + res + }))) }) } - fn connection_for(&self, uri: Uri, pool_key: PoolKey) - -> impl Future>, ClientError>> - { + fn connection_for( + &self, + uri: Uri, + pool_key: PoolKey, + ) -> impl Future>, ClientError>> { // This actually races 2 different futures to try to get a ready // connection the fastest, and to reduce connection churn. // @@ -395,67 +410,66 @@ where C: Connect + Clone + Send + Sync + 'static, let executor = self.conn_builder.exec.clone(); // The order of the `select` is depended on below... - future::select(checkout, connect) - .then(move |either| match either { - // Checkout won, connect future may have been started or not. - // - // If it has, let it finish and insert back into the pool, - // so as to not waste the socket... - Either::Left((Ok(checked_out), connecting)) => { - // This depends on the `select` above having the correct - // order, such that if the checkout future were ready - // immediately, the connect future will never have been - // started. - // - // If it *wasn't* ready yet, then the connect future will - // have been started... - if connecting.started() { - let bg = connecting - .map_err(|err| { - trace!("background connect error: {}", err); - }) - .map(|_pooled| { - // dropping here should just place it in - // the Pool for us... - }); - // An execute error here isn't important, we're just trying - // to prevent a waste of a socket... - let _ = executor.execute(bg); - } - Either::Left(future::ok(checked_out)) - }, - // Connect won, checkout can just be dropped. - Either::Right((Ok(connected), _checkout)) => { - Either::Left(future::ok(connected)) - }, - // Either checkout or connect could get canceled: - // - // 1. Connect is canceled if this is HTTP/2 and there is - // an outstanding HTTP/2 connecting task. - // 2. Checkout is canceled if the pool cannot deliver an - // idle connection reliably. + future::select(checkout, connect).then(move |either| match either { + // Checkout won, connect future may have been started or not. + // + // If it has, let it finish and insert back into the pool, + // so as to not waste the socket... + Either::Left((Ok(checked_out), connecting)) => { + // This depends on the `select` above having the correct + // order, such that if the checkout future were ready + // immediately, the connect future will never have been + // started. // - // In both cases, we should just wait for the other future. - Either::Left((Err(err), connecting)) => Either::Right(Either::Left({ - if err.is_canceled() { - Either::Left(connecting.map_err(ClientError::Normal)) - } else { - Either::Right(future::err(ClientError::Normal(err))) - } - })), - Either::Right((Err(err), checkout)) => Either::Right(Either::Right({ - if err.is_canceled() { - Either::Left(checkout.map_err(ClientError::Normal)) - } else { - Either::Right(future::err(ClientError::Normal(err))) - } - })), - }) + // If it *wasn't* ready yet, then the connect future will + // have been started... + if connecting.started() { + let bg = connecting + .map_err(|err| { + trace!("background connect error: {}", err); + }) + .map(|_pooled| { + // dropping here should just place it in + // the Pool for us... + }); + // An execute error here isn't important, we're just trying + // to prevent a waste of a socket... + let _ = executor.execute(bg); + } + Either::Left(future::ok(checked_out)) + } + // Connect won, checkout can just be dropped. + Either::Right((Ok(connected), _checkout)) => Either::Left(future::ok(connected)), + // Either checkout or connect could get canceled: + // + // 1. Connect is canceled if this is HTTP/2 and there is + // an outstanding HTTP/2 connecting task. + // 2. Checkout is canceled if the pool cannot deliver an + // idle connection reliably. + // + // In both cases, we should just wait for the other future. + Either::Left((Err(err), connecting)) => Either::Right(Either::Left({ + if err.is_canceled() { + Either::Left(connecting.map_err(ClientError::Normal)) + } else { + Either::Right(future::err(ClientError::Normal(err))) + } + })), + Either::Right((Err(err), checkout)) => Either::Right(Either::Right({ + if err.is_canceled() { + Either::Left(checkout.map_err(ClientError::Normal)) + } else { + Either::Right(future::err(ClientError::Normal(err))) + } + })), + }) } - fn connect_to(&self, uri: Uri, pool_key: PoolKey) - -> impl Lazy>>> + Unpin - { + fn connect_to( + &self, + uri: Uri, + pool_key: PoolKey, + ) -> impl Lazy>>> + Unpin { let executor = self.conn_builder.exec.clone(); let pool = self.pool.clone(); let mut conn_builder = self.conn_builder.clone(); @@ -472,68 +486,82 @@ where C: Connect + Clone + Send + Sync + 'static, let connecting = match pool.connecting(&pool_key, ver) { Some(lock) => lock, None => { - let canceled = crate::Error::new_canceled().with("HTTP/2 connection in progress"); + let canceled = + crate::Error::new_canceled().with("HTTP/2 connection in progress"); return Either::Right(future::err(canceled)); } }; - Either::Left(connector.connect(connect::sealed::Internal, dst) - .map_err(crate::Error::new_connect) - .and_then(move |io| { - let connected = io.connected(); - // If ALPN is h2 and we aren't http2_only already, - // then we need to convert our pool checkout into - // a single HTTP2 one. - let connecting = if connected.alpn == Alpn::H2 && !is_ver_h2 { - match connecting.alpn_h2(&pool) { - Some(lock) => { - trace!("ALPN negotiated h2, updating pool"); - lock - }, - None => { - // Another connection has already upgraded, - // the pool checkout should finish up for us. - let canceled = crate::Error::new_canceled().with("ALPN upgraded to HTTP/2"); - return Either::Right(future::err(canceled)); + Either::Left( + connector + .connect(connect::sealed::Internal, dst) + .map_err(crate::Error::new_connect) + .and_then(move |io| { + let connected = io.connected(); + // If ALPN is h2 and we aren't http2_only already, + // then we need to convert our pool checkout into + // a single HTTP2 one. + let connecting = if connected.alpn == Alpn::H2 && !is_ver_h2 { + match connecting.alpn_h2(&pool) { + Some(lock) => { + trace!("ALPN negotiated h2, updating pool"); + lock + } + None => { + // Another connection has already upgraded, + // the pool checkout should finish up for us. + let canceled = crate::Error::new_canceled() + .with("ALPN upgraded to HTTP/2"); + return Either::Right(future::err(canceled)); + } } - } - } else { - connecting - }; - let is_h2 = is_ver_h2 || connected.alpn == Alpn::H2; - Either::Left(Box::pin(conn_builder - .http2_only(is_h2) - .handshake(io) - .and_then(move |(tx, conn)| { - trace!("handshake complete, spawning background dispatcher task"); - executor.execute(conn.map_err(|e| { - debug!("client connection error: {}", e) - }).map(|_| ())); - - // Wait for 'conn' to ready up before we - // declare this tx as usable - tx.when_ready() - }) - .map_ok(move |tx| { - pool.pooled(connecting, PoolClient { - conn_info: connected, - tx: if is_h2 { - PoolTx::Http2(tx.into_http2()) - } else { - PoolTx::Http1(tx) - }, - }) - }))) - })) + } else { + connecting + }; + let is_h2 = is_ver_h2 || connected.alpn == Alpn::H2; + Either::Left(Box::pin( + conn_builder + .http2_only(is_h2) + .handshake(io) + .and_then(move |(tx, conn)| { + trace!( + "handshake complete, spawning background dispatcher task" + ); + executor.execute( + conn.map_err(|e| debug!("client connection error: {}", e)) + .map(|_| ()), + ); + + // Wait for 'conn' to ready up before we + // declare this tx as usable + tx.when_ready() + }) + .map_ok(move |tx| { + pool.pooled( + connecting, + PoolClient { + conn_info: connected, + tx: if is_h2 { + PoolTx::Http2(tx.into_http2()) + } else { + PoolTx::Http1(tx) + }, + }, + ) + }), + )) + }), + ) }) } } impl tower_service::Service> for Client -where C: Connect + Clone + Send + Sync + 'static, - C::Transport: Unpin + Send + 'static, - C::Future: Unpin + Send + 'static, - B: Payload + Unpin + Send + 'static, - B::Data: Send + Unpin, +where + C: Connect + Clone + Send + Sync + 'static, + C::Transport: Unpin + Send + 'static, + C::Future: Unpin + Send + 'static, + B: Payload + Unpin + Send + 'static, + B::Data: Send + Unpin, { type Response = Response; type Error = crate::Error; @@ -561,23 +589,22 @@ impl Clone for Client { impl fmt::Debug for Client { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Client") - .finish() + f.debug_struct("Client").finish() } } // ===== impl ResponseFuture ===== impl ResponseFuture { - fn new(fut: Box>> + Send>) -> Self { - Self { - inner: fut.into(), - } + fn new(fut: Box>> + Send>) -> Self { + Self { inner: fut.into() } } fn error_version(ver: Version) -> Self { warn!("Request has unsupported version \"{:?}\"", ver); - ResponseFuture::new(Box::new(future::err(crate::Error::new_user_unsupported_version()))) + ResponseFuture::new(Box::new(future::err( + crate::Error::new_user_unsupported_version(), + ))) } } @@ -644,7 +671,10 @@ impl PoolClient { } impl PoolClient { - fn send_request_retryable(&mut self, req: Request) -> impl Future, (crate::Error, Option>)>> + fn send_request_retryable( + &mut self, + req: Request, + ) -> impl Future, (crate::Error, Option>)>> where B: Send, { @@ -668,12 +698,10 @@ where fn reserve(self) -> Reservation { match self.tx { - PoolTx::Http1(tx) => { - Reservation::Unique(PoolClient { - conn_info: self.conn_info, - tx: PoolTx::Http1(tx), - }) - }, + PoolTx::Http1(tx) => Reservation::Unique(PoolClient { + conn_info: self.conn_info, + tx: PoolTx::Http1(tx), + }), PoolTx::Http2(tx) => { let b = PoolClient { conn_info: self.conn_info.clone(), @@ -703,13 +731,11 @@ enum ClientError { connection_reused: bool, req: Request, reason: crate::Error, - } + }, } impl ClientError { - fn map_with_reused(conn_reused: bool) - -> impl Fn((crate::Error, Option>)) -> Self - { + fn map_with_reused(conn_reused: bool) -> impl Fn((crate::Error, Option>)) -> Self { move |(err, orig_req)| { if let Some(req) = orig_req { ClientError::Canceled { @@ -737,7 +763,7 @@ fn origin_form(uri: &mut Uri) { let mut parts = ::http::uri::Parts::default(); parts.path_and_query = Some(path.clone()); Uri::from_parts(parts).expect("path is valid uri") - }, + } _none_or_just_slash => { debug_assert!(Uri::default() == "/"); Uri::default() @@ -748,7 +774,10 @@ fn origin_form(uri: &mut Uri) { fn absolute_form(uri: &mut Uri) { debug_assert!(uri.scheme().is_some(), "absolute_form needs a scheme"); - debug_assert!(uri.authority().is_some(), "absolute_form needs an authority"); + debug_assert!( + uri.authority().is_some(), + "absolute_form needs an authority" + ); // If the URI is to HTTPS, and the connector claimed to be a proxy, // then it *should* have tunneled, and so we don't want to send // absolute-form in that case. @@ -763,10 +792,7 @@ fn authority_form(uri: &mut Uri) { // `https://hyper.rs` would parse with `/` path, don't // annoy people about that... if path != "/" { - warn!( - "HTTP/1.1 CONNECT request stripping path: {:?}", - path - ); + warn!("HTTP/1.1 CONNECT request stripping path: {:?}", path); } } } @@ -775,7 +801,7 @@ fn authority_form(uri: &mut Uri) { let mut parts = ::http::uri::Parts::default(); parts.authority = Some(auth.clone()); Uri::from_parts(parts).expect("authority is valid") - }, + } None => { unreachable!("authority_form with relative uri"); } @@ -785,9 +811,7 @@ fn authority_form(uri: &mut Uri) { fn extract_domain(uri: &mut Uri, is_http_connect: bool) -> crate::Result { let uri_clone = uri.clone(); match (uri_clone.scheme(), uri_clone.authority()) { - (Some(scheme), Some(auth)) => { - Ok(format!("{}://{}", scheme, auth)) - } + (Some(scheme), Some(auth)) => Ok(format!("{}://{}", scheme, auth)), (None, Some(auth)) if is_http_connect => { let scheme = match auth.port_u16() { Some(443) => { @@ -797,10 +821,10 @@ fn extract_domain(uri: &mut Uri, is_http_connect: bool) -> crate::Result _ => { set_scheme(uri, Scheme::HTTP); "http" - }, + } }; Ok(format!("{}://{}", scheme, auth)) - }, + } _ => { debug!("Client requires absolute-form URIs, received: {:?}", uri); Err(crate::Error::new_user_absolute_uri_required()) @@ -809,7 +833,10 @@ fn extract_domain(uri: &mut Uri, is_http_connect: bool) -> crate::Result } fn set_scheme(uri: &mut Uri, scheme: Scheme) { - debug_assert!(uri.scheme().is_none(), "set_scheme expects no existing scheme"); + debug_assert!( + uri.scheme().is_none(), + "set_scheme expects no existing scheme" + ); let old = mem::replace(uri, Uri::default()); let mut parts: ::http::uri::Parts = old.into(); parts.scheme = Some(scheme); @@ -946,11 +973,7 @@ impl Builder { /// /// Default is false. pub fn http2_only(&mut self, val: bool) -> &mut Self { - self.client_config.ver = if val { - Ver::Http2 - } else { - Ver::Auto - }; + self.client_config.ver = if val { Ver::Http2 } else { Ver::Auto }; self } @@ -963,7 +986,8 @@ impl Builder { /// /// [spec]: https://http2.github.io/http2-spec/#SETTINGS_INITIAL_WINDOW_SIZE pub fn http2_initial_stream_window_size(&mut self, sz: impl Into>) -> &mut Self { - self.conn_builder.http2_initial_stream_window_size(sz.into()); + self.conn_builder + .http2_initial_stream_window_size(sz.into()); self } @@ -972,8 +996,12 @@ impl Builder { /// Passing `None` will do nothing. /// /// If not set, hyper will use a default. - pub fn http2_initial_connection_window_size(&mut self, sz: impl Into>) -> &mut Self { - self.conn_builder.http2_initial_connection_window_size(sz.into()); + pub fn http2_initial_connection_window_size( + &mut self, + sz: impl Into>, + ) -> &mut Self { + self.conn_builder + .http2_initial_connection_window_size(sz.into()); self } diff --git a/src/client/pool.rs b/src/client/pool.rs index 68296f62e1..8f365aef80 100644 --- a/src/client/pool.rs +++ b/src/client/pool.rs @@ -10,8 +10,8 @@ use futures_channel::oneshot; #[cfg(feature = "runtime")] use tokio::time::{Duration, Instant, Interval}; -use crate::common::{Exec, Future, Pin, Poll, Unpin, task}; use super::Ver; +use crate::common::{task, Exec, Future, Pin, Poll, Unpin}; // FIXME: allow() required due to `impl Trait` leaking types to this lint #[allow(missing_debug_implementations)] @@ -96,7 +96,7 @@ pub(super) struct Config { impl Pool { pub fn new(config: Config, __exec: &Exec) -> Pool { let inner = if config.enabled { - Some(Arc::new(Mutex::new(PoolInner { + Some(Arc::new(Mutex::new(PoolInner { connecting: HashSet::new(), idle: HashMap::new(), #[cfg(feature = "runtime")] @@ -106,14 +106,12 @@ impl Pool { #[cfg(feature = "runtime")] exec: __exec.clone(), timeout: config.keep_alive_timeout, - }))) + }))) } else { None }; - Pool { - inner, - } + Pool { inner } } fn is_enabled(&self) -> bool { @@ -174,12 +172,7 @@ impl Pool { #[cfg(test)] fn locked(&self) -> ::std::sync::MutexGuard<'_, PoolInner> { - self - .inner - .as_ref() - .expect("enabled") - .lock() - .expect("lock") + self.inner.as_ref().expect("enabled").lock().expect("lock") } /* Used in client/tests.rs... @@ -216,13 +209,13 @@ impl Pool { // Shared reservations don't need a reference to the pool, // since the pool always keeps a copy. (to_return, WeakOpt::none()) - }, + } Reservation::Unique(value) => { // Unique reservations must take a reference to the pool // since they hope to reinsert once the reservation is // completed (value, WeakOpt::downgrade(enabled)) - }, + } } } else { // If pool is not enabled, skip all the things... @@ -236,7 +229,7 @@ impl Pool { key: connecting.key.clone(), is_reused: false, pool: pool_ref, - value: Some(value) + value: Some(value), } } @@ -299,10 +292,8 @@ impl<'a, T: Poolable + 'a> IdlePopper<'a, T> { value: to_reinsert, }); to_checkout - }, - Reservation::Unique(unique) => { - unique } + Reservation::Unique(unique) => unique, }; return Some(Idle { @@ -332,7 +323,7 @@ impl PoolInner { Reservation::Shared(to_keep, to_send) => { value = Some(to_keep); to_send - }, + } Reservation::Unique(uniq) => uniq, }; match tx.send(reserved) { @@ -342,7 +333,7 @@ impl PoolInner { } else { continue; } - }, + } Err(e) => { value = Some(e); } @@ -361,10 +352,7 @@ impl PoolInner { Some(value) => { // borrow-check scope... { - let idle_list = self - .idle - .entry(key.clone()) - .or_insert(Vec::new()); + let idle_list = self.idle.entry(key.clone()).or_insert(Vec::new()); if self.max_idle_per_host <= idle_list.len() { trace!("max idle per host for {:?}, dropping connection", key); return; @@ -390,10 +378,7 @@ impl PoolInner { /// but the lock is going away, so clean up. fn connected(&mut self, key: &Key) { let existed = self.connecting.remove(key); - debug_assert!( - existed, - "Connecting dropped, key not in pool.connecting" - ); + debug_assert!(existed, "Connecting dropped, key not in pool.connecting"); // cancel any waiters. if there are any, it's because // this Connecting task didn't complete successfully. // those waiters would never receive a connection. @@ -412,7 +397,7 @@ impl PoolInner { self.idle_interval_ref = Some(tx); (dur, rx) } else { - return + return; } }; @@ -434,9 +419,7 @@ impl PoolInner { fn clean_waiters(&mut self, key: &Key) { let mut remove_waiters = false; if let Some(waiters) = self.waiters.get_mut(key) { - waiters.retain(|tx| { - !tx.is_canceled() - }); + waiters.retain(|tx| !tx.is_canceled()); remove_waiters = waiters.is_empty(); } if remove_waiters { @@ -547,9 +530,7 @@ impl Drop for Pooled { impl fmt::Debug for Pooled { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Pooled") - .field("key", &self.key) - .finish() + f.debug_struct("Pooled").field("key", &self.key).finish() } } @@ -567,7 +548,10 @@ pub(super) struct Checkout { } impl Checkout { - fn poll_waiter(&mut self, cx: &mut task::Context<'_>) -> Poll>>> { + fn poll_waiter( + &mut self, + cx: &mut task::Context<'_>, + ) -> Poll>>> { static CANCELED: &str = "pool checkout failed"; if let Some(mut rx) = self.waiter.take() { match Pin::new(&mut rx).poll(cx) { @@ -577,12 +561,14 @@ impl Checkout { } else { Poll::Ready(Some(Err(crate::Error::new_canceled().with(CANCELED)))) } - }, + } Poll::Pending => { self.waiter = Some(rx); Poll::Pending - }, - Poll::Ready(Err(_canceled)) => Poll::Ready(Some(Err(crate::Error::new_canceled().with(CANCELED)))), + } + Poll::Ready(Err(_canceled)) => { + Poll::Ready(Some(Err(crate::Error::new_canceled().with(CANCELED)))) + } } } else { Poll::Ready(None) @@ -593,20 +579,19 @@ impl Checkout { let entry = { let mut inner = self.pool.inner.as_ref()?.lock().unwrap(); let expiration = Expiration::new(inner.timeout); - let maybe_entry = inner.idle.get_mut(&self.key) - .and_then(|list| { - trace!("take? {:?}: expiration = {:?}", self.key, expiration.0); - // A block to end the mutable borrow on list, - // so the map below can check is_empty() - { - let popper = IdlePopper { - key: &self.key, - list, - }; - popper.pop(&expiration) - } - .map(|e| (e, list.is_empty())) - }); + let maybe_entry = inner.idle.get_mut(&self.key).and_then(|list| { + trace!("take? {:?}: expiration = {:?}", self.key, expiration.0); + // A block to end the mutable borrow on list, + // so the map below can check is_empty() + { + let popper = IdlePopper { + key: &self.key, + list, + }; + popper.pop(&expiration) + } + .map(|e| (e, list.is_empty())) + }); let (entry, empty) = if let Some((e, empty)) = maybe_entry { (Some(e), empty) @@ -764,9 +749,7 @@ impl WeakOpt { } fn upgrade(&self) -> Option> { - self.0 - .as_ref() - .and_then(Weak::upgrade) + self.0.as_ref().and_then(Weak::upgrade) } } @@ -776,8 +759,8 @@ mod tests { use std::task::Poll; use std::time::Duration; - use crate::common::{Exec, Future, Pin, task}; - use super::{Connecting, Key, Poolable, Pool, Reservation, WeakOpt}; + use super::{Connecting, Key, Pool, Poolable, Reservation, WeakOpt}; + use crate::common::{task, Exec, Future, Pin}; /// Test unique reservations. #[derive(Debug, PartialEq, Eq)] @@ -809,7 +792,8 @@ mod tests { } fn pool_max_idle_no_timer(max_idle: usize) -> Pool { - let pool = Pool::new(super::Config { + let pool = Pool::new( + super::Config { enabled: true, keep_alive_timeout: Some(Duration::from_millis(100)), max_idle_per_host: max_idle, @@ -838,7 +822,8 @@ mod tests { struct PollOnce<'a, F>(&'a mut F); impl Future for PollOnce<'_, F> - where F: Future> + Unpin + where + F: Future> + Unpin, { type Output = Option<()>; @@ -846,7 +831,7 @@ mod tests { match Pin::new(&mut self.0).poll(cx) { Poll::Ready(Ok(_)) => Poll::Ready(Some(())), Poll::Ready(Err(_)) => Poll::Ready(Some(())), - Poll::Pending => Poll::Ready(None) + Poll::Pending => Poll::Ready(None), } } } @@ -875,7 +860,10 @@ mod tests { pool.pooled(c(key.clone()), Uniq(5)); pool.pooled(c(key.clone()), Uniq(99)); - assert_eq!(pool.locked().idle.get(&key).map(|entries| entries.len()), Some(3)); + assert_eq!( + pool.locked().idle.get(&key).map(|entries| entries.len()), + Some(3) + ); tokio::time::delay_for(pool.locked().timeout.unwrap()).await; let mut checkout = pool.checkout(key.clone()); @@ -895,7 +883,10 @@ mod tests { pool.pooled(c(key.clone()), Uniq(99)); // pooled and dropped 3, max_idle should only allow 2 - assert_eq!(pool.locked().idle.get(&key).map(|entries| entries.len()), Some(2)); + assert_eq!( + pool.locked().idle.get(&key).map(|entries| entries.len()), + Some(2) + ); } #[cfg(feature = "runtime")] @@ -904,7 +895,8 @@ mod tests { let _ = pretty_env_logger::try_init(); tokio::time::pause(); - let pool = Pool::new(super::Config { + let pool = Pool::new( + super::Config { enabled: true, keep_alive_timeout: Some(Duration::from_millis(10)), max_idle_per_host: ::std::usize::MAX, @@ -918,7 +910,10 @@ mod tests { pool.pooled(c(key.clone()), Uniq(5)); pool.pooled(c(key.clone()), Uniq(99)); - assert_eq!(pool.locked().idle.get(&key).map(|entries| entries.len()), Some(3)); + assert_eq!( + pool.locked().idle.get(&key).map(|entries| entries.len()), + Some(3) + ); // Let the timer tick passed the expiration... tokio::time::advance(Duration::from_millis(30)).await; @@ -937,17 +932,15 @@ mod tests { let key = Arc::new("foo".to_string()); let pooled = pool.pooled(c(key.clone()), Uniq(41)); - let checkout = join( - pool.checkout(key), - async { - // the checkout future will park first, - // and then this lazy future will be polled, which will insert - // the pooled back into the pool - // - // this test makes sure that doing so will unpark the checkout - drop(pooled); - }, - ).map(|(entry, _)| entry); + let checkout = join(pool.checkout(key), async { + // the checkout future will park first, + // and then this lazy future will be polled, which will insert + // the pooled back into the pool + // + // this test makes sure that doing so will unpark the checkout + drop(pooled); + }) + .map(|(entry, _)| entry); assert_eq!(*checkout.await.unwrap(), Uniq(41)); } @@ -1001,10 +994,13 @@ mod tests { fn pooled_drop_if_closed_doesnt_reinsert() { let pool = pool_no_timer(); let key = Arc::new("localhost:12345".to_string()); - pool.pooled(c(key.clone()), CanClose { - val: 57, - closed: true, - }); + pool.pooled( + c(key.clone()), + CanClose { + val: 57, + closed: true, + }, + ); assert!(!pool.locked().idle.contains_key(&key)); } diff --git a/src/client/service.rs b/src/client/service.rs index d85d3107b6..ef3a9babb2 100644 --- a/src/client/service.rs +++ b/src/client/service.rs @@ -2,12 +2,16 @@ //! //! This module provides `Connect` which hook-ins into the Tower ecosystem. -use std::marker::PhantomData; -use std::future::Future; use std::error::Error as StdError; +use std::future::Future; +use std::marker::PhantomData; -use crate::{common::{Poll, task, Pin}, body::Payload, service::{MakeConnection, Service}}; -use super::conn::{SendRequest, Builder}; +use super::conn::{Builder, SendRequest}; +use crate::{ + body::Payload, + common::{task, Pin, Poll}, + service::{MakeConnection, Service}, +}; /// Creates a connection via `SendRequest`. /// @@ -18,7 +22,7 @@ use super::conn::{SendRequest, Builder}; pub struct Connect { inner: C, builder: Builder, - _pd: PhantomData + _pd: PhantomData, } impl Connect { @@ -28,7 +32,7 @@ impl Connect { Self { inner, builder, - _pd: PhantomData + _pd: PhantomData, } } } @@ -44,10 +48,13 @@ where { type Response = SendRequest; type Error = crate::Error; - type Future = Pin> + Send + 'static>>; + type Future = + Pin> + Send + 'static>>; fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll> { - self.inner.poll_ready(cx).map_err(|e| crate::Error::new(crate::error::Kind::Connect).with(e.into())) + self.inner + .poll_ready(cx) + .map_err(|e| crate::Error::new(crate::error::Kind::Connect).with(e.into())) } fn call(&mut self, req: T) -> Self::Future { @@ -56,18 +63,16 @@ where let fut = async move { match io.await { - Ok(io) => { - match builder.handshake(io).await { - Ok((sr, conn)) => { - builder.exec.execute(async move { - if let Err(e) = conn.await { - debug!("connection error: {:?}", e); - } - }); - Ok(sr) - }, - Err(e) => Err(e) + Ok(io) => match builder.handshake(io).await { + Ok((sr, conn)) => { + builder.exec.execute(async move { + if let Err(e) = conn.await { + debug!("connection error: {:?}", e); + } + }); + Ok(sr) } + Err(e) => Err(e), }, Err(e) => { let err = crate::Error::new(crate::error::Kind::Connect).with(e.into()); diff --git a/src/common/drain.rs b/src/common/drain.rs index 20442e22c0..7abb9f9ded 100644 --- a/src/common/drain.rs +++ b/src/common/drain.rs @@ -1,9 +1,9 @@ use std::mem; -use tokio::sync::{mpsc, watch}; use pin_project::pin_project; +use tokio::sync::{mpsc, watch}; -use super::{Future, Never, Poll, Pin, task}; +use super::{task, Future, Never, Pin, Poll}; // Sentinel value signaling that the watch is still open #[derive(Clone, Copy)] @@ -21,10 +21,7 @@ pub fn channel() -> (Signal, Watch) { drained_rx, _tx: tx, }, - Watch { - drained_tx, - rx, - }, + Watch { drained_tx, rx }, ) } @@ -107,17 +104,14 @@ where Poll::Ready(None) => { // Drain has been triggered! on_drain(me.future.as_mut()); - }, - Poll::Ready(Some(_/*State::Open*/)) | - Poll::Pending => { + } + Poll::Ready(Some(_ /*State::Open*/)) | Poll::Pending => { *me.state = State::Watch(on_drain); return me.future.poll(cx); - }, + } } - }, - State::Draining => { - return me.future.poll(cx) - }, + } + State::Draining => return me.future.poll(cx), } } } @@ -236,4 +230,3 @@ mod tests { }); } } - diff --git a/src/common/exec.rs b/src/common/exec.rs index ecba0b2348..94ad4610a2 100644 --- a/src/common/exec.rs +++ b/src/common/exec.rs @@ -3,7 +3,7 @@ use std::future::Future; use std::pin::Pin; use std::sync::Arc; -use crate::body::{Payload, Body}; +use crate::body::{Body, Payload}; use crate::proto::h2::server::H2Stream; use crate::server::conn::spawn_all::{NewSvcTask, Watcher}; use crate::service::HttpService; @@ -22,7 +22,7 @@ pub trait NewSvcExec, E, W: Watcher>: Clone fn execute_new_svc(&mut self, fut: NewSvcTask); } -pub type BoxSendFuture = Pin + Send>>; +pub type BoxSendFuture = Pin + Send>>; // Either the user provides an executor for background tasks, or we use // `tokio::spawn`. @@ -37,7 +37,7 @@ pub enum Exec { impl Exec { pub(crate) fn execute(&self, fut: F) where - F: Future + Send + 'static, + F: Future + Send + 'static, { match *self { Exec::Default => { @@ -50,22 +50,20 @@ impl Exec { // If no runtime, we need an executor! panic!("executor must be set") } - }, + } Exec::Executor(ref e) => { e.execute(Box::pin(fut)); - }, + } } } } impl fmt::Debug for Exec { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Exec") - .finish() + f.debug_struct("Exec").finish() } } - impl H2Exec for Exec where H2Stream: Future + Send + 'static, @@ -78,7 +76,7 @@ where impl NewSvcExec for Exec where - NewSvcTask: Future + Send + 'static, + NewSvcTask: Future + Send + 'static, S: HttpService, W: Watcher, { @@ -92,7 +90,7 @@ where impl H2Exec for E where E: Executor> + Clone, - H2Stream: Future, + H2Stream: Future, B: Payload, { fn execute_h2stream(&mut self, fut: H2Stream) { @@ -103,7 +101,7 @@ where impl NewSvcExec for E where E: Executor> + Clone, - NewSvcTask: Future, + NewSvcTask: Future, S: HttpService, W: Watcher, { @@ -111,4 +109,3 @@ where self.execute(fut) } } - diff --git a/src/common/io/rewind.rs b/src/common/io/rewind.rs index 2cf0712938..9acbe325c7 100644 --- a/src/common/io/rewind.rs +++ b/src/common/io/rewind.rs @@ -1,10 +1,10 @@ -use std::{cmp, io}; use std::marker::Unpin; +use std::{cmp, io}; use bytes::{Buf, Bytes}; use tokio::io::{AsyncRead, AsyncWrite}; -use crate::common::{Pin, Poll, task}; +use crate::common::{task, Pin, Poll}; /// Combine a buffer with an IO, rewinding reads to use the buffer. #[derive(Debug)] @@ -47,7 +47,11 @@ where self.inner.prepare_uninitialized_buffer(buf) } - fn poll_read(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &mut [u8]) -> Poll> { + fn poll_read( + mut self: Pin<&mut Self>, + cx: &mut task::Context<'_>, + buf: &mut [u8], + ) -> Poll> { if let Some(mut prefix) = self.pre.take() { // If there are no remaining bytes, let the bytes get dropped. if prefix.len() > 0 { @@ -69,7 +73,11 @@ impl AsyncWrite for Rewind where T: AsyncWrite + Unpin, { - fn poll_write(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &[u8]) -> Poll> { + fn poll_write( + mut self: Pin<&mut Self>, + cx: &mut task::Context<'_>, + buf: &[u8], + ) -> Poll> { Pin::new(&mut self.inner).poll_write(cx, buf) } @@ -82,7 +90,11 @@ where } #[inline] - fn poll_write_buf(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &mut B) -> Poll> { + fn poll_write_buf( + mut self: Pin<&mut Self>, + cx: &mut task::Context<'_>, + buf: &mut B, + ) -> Poll> { Pin::new(&mut self.inner).poll_write_buf(cx, buf) } } @@ -91,36 +103,27 @@ where mod tests { // FIXME: re-implement tests with `async/await`, this import should // trigger a warning to remind us + use super::Rewind; use bytes::Bytes; use tokio::io::AsyncReadExt; - use super::Rewind; #[tokio::test] async fn partial_rewind() { let underlying = [104, 101, 108, 108, 111]; - let mock = tokio_test::io::Builder::new() - .read(&underlying) - .build(); + let mock = tokio_test::io::Builder::new().read(&underlying).build(); let mut stream = Rewind::new(mock); // Read off some bytes, ensure we filled o1 let mut buf = [0; 2]; - stream - .read_exact(&mut buf) - .await - .expect("read1"); - + stream.read_exact(&mut buf).await.expect("read1"); // Rewind the stream so that it is as if we never read in the first place. stream.rewind(Bytes::copy_from_slice(&buf[..])); let mut buf = [0; 5]; - stream - .read_exact(&mut buf) - .await - .expect("read1"); + stream.read_exact(&mut buf).await.expect("read1"); // At this point we should have read everything that was in the MockStream assert_eq!(&buf, &underlying); @@ -130,26 +133,17 @@ mod tests { async fn full_rewind() { let underlying = [104, 101, 108, 108, 111]; - let mock = tokio_test::io::Builder::new() - .read(&underlying) - .build(); + let mock = tokio_test::io::Builder::new().read(&underlying).build(); let mut stream = Rewind::new(mock); let mut buf = [0; 5]; - stream - .read_exact(&mut buf) - .await - .expect("read1"); - + stream.read_exact(&mut buf).await.expect("read1"); // Rewind the stream so that it is as if we never read in the first place. stream.rewind(Bytes::copy_from_slice(&buf[..])); let mut buf = [0; 5]; - stream - .read_exact(&mut buf) - .await - .expect("read1"); + stream.read_exact(&mut buf).await.expect("read1"); } } diff --git a/src/common/lazy.rs b/src/common/lazy.rs index e8d38bc4b1..67359d2642 100644 --- a/src/common/lazy.rs +++ b/src/common/lazy.rs @@ -1,6 +1,6 @@ use std::mem; -use super::{Future, Pin, Poll, task}; +use super::{task, Future, Pin, Poll}; pub(crate) trait Started: Future { fn started(&self) -> bool; @@ -19,7 +19,7 @@ where // FIXME: allow() required due to `impl Trait` leaking types to this lint #[allow(missing_debug_implementations)] pub(crate) struct Lazy { - inner: Inner + inner: Inner, } enum Inner { @@ -36,8 +36,7 @@ where fn started(&self) -> bool { match self.inner { Inner::Init(_) => false, - Inner::Fut(_) | - Inner::Empty => true, + Inner::Fut(_) | Inner::Empty => true, } } } @@ -61,7 +60,7 @@ where let ret = Pin::new(&mut fut).poll(cx); self.inner = Inner::Fut(fut); ret - }, + } _ => unreachable!("lazy state wrong"), } } @@ -69,4 +68,3 @@ where // The closure `F` is never pinned impl Unpin for Lazy {} - diff --git a/src/common/mod.rs b/src/common/mod.rs index 727fa89d6a..28169a2f5c 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -1,10 +1,10 @@ macro_rules! ready { - ($e:expr) => ( + ($e:expr) => { match $e { ::std::task::Poll::Ready(v) => v, ::std::task::Poll::Pending => return ::std::task::Poll::Pending, } - ) + }; } pub(crate) mod drain; @@ -14,16 +14,11 @@ mod lazy; mod never; pub(crate) mod task; -pub(crate) use self::exec::{BoxSendFuture, Exec}; pub use self::exec::Executor; +pub(crate) use self::exec::{BoxSendFuture, Exec}; pub(crate) use self::lazy::{lazy, Started as Lazy}; pub use self::never::Never; pub(crate) use self::task::Poll; // group up types normally needed for `Future` -pub(crate) use std::{ - future::Future, - marker::Unpin, - pin::Pin, -}; - +pub(crate) use std::{future::Future, marker::Unpin, pin::Pin}; diff --git a/src/common/never.rs b/src/common/never.rs index c44c9adb97..f4fdb95ddd 100644 --- a/src/common/never.rs +++ b/src/common/never.rs @@ -19,4 +19,3 @@ impl Error for Never { match *self {} } } - diff --git a/src/common/task.rs b/src/common/task.rs index aca869e6ef..bfccfe3bfe 100644 --- a/src/common/task.rs +++ b/src/common/task.rs @@ -1,5 +1,5 @@ -pub(crate) use std::task::{Context, Poll}; use super::Never; +pub(crate) use std::task::{Context, Poll}; /// A function to help "yield" a future, such that it is re-scheduled immediately. /// diff --git a/src/error.rs b/src/error.rs index a903153cb5..7cbcebceeb 100644 --- a/src/error.rs +++ b/src/error.rs @@ -140,10 +140,7 @@ impl Error { pub(crate) fn new(kind: Kind) -> Error { Error { - inner: Box::new(ErrorImpl { - kind, - cause: None, - }), + inner: Box::new(ErrorImpl { kind, cause: None }), } } @@ -162,9 +159,7 @@ impl Error { let mut cause = self.source(); while let Some(err) = cause { if let Some(h2_err) = err.downcast_ref::() { - return h2_err - .reason() - .unwrap_or(h2::Reason::INTERNAL_ERROR); + return h2_err.reason().unwrap_or(h2::Reason::INTERNAL_ERROR); } cause = err.source(); } @@ -335,7 +330,9 @@ impl StdError for Error { Kind::User(User::UnexpectedHeader) => "user sent unexpected header", Kind::User(User::UnsupportedVersion) => "request has unsupported HTTP version", Kind::User(User::UnsupportedRequestMethod) => "request has unsupported HTTP method", - Kind::User(User::UnsupportedStatusCode) => "response has 1xx status code, not supported by server", + Kind::User(User::UnsupportedStatusCode) => { + "response has 1xx status code, not supported by server" + } Kind::User(User::AbsoluteUriRequired) => "client requires absolute-form URIs", Kind::User(User::NoUpgrade) => "no upgrade available", Kind::User(User::ManualUpgrade) => "upgrade expected but low level API in use", @@ -343,8 +340,7 @@ impl StdError for Error { } fn source(&self) -> Option<&(dyn StdError + 'static)> { - self - .inner + self.inner .cause .as_ref() .map(|cause| &**cause as &(dyn StdError + 'static)) @@ -361,10 +357,10 @@ impl From for Error { impl From for Parse { fn from(err: httparse::Error) -> Parse { match err { - httparse::Error::HeaderName | - httparse::Error::HeaderValue | - httparse::Error::NewLine | - httparse::Error::Token => Parse::Header, + httparse::Error::HeaderName + | httparse::Error::HeaderValue + | httparse::Error::NewLine + | httparse::Error::Token => Parse::Header, httparse::Error::Status => Parse::Status, httparse::Error::TooManyHeaders => Parse::TooLarge, httparse::Error::Version => Parse::Version, @@ -403,8 +399,8 @@ impl AssertSendSync for Error {} #[cfg(test)] mod tests { - use std::mem; use super::*; + use std::mem; #[test] fn error_size_of() { diff --git a/src/headers.rs b/src/headers.rs index 4ae91d5a61..ba1b881b70 100644 --- a/src/headers.rs +++ b/src/headers.rs @@ -1,7 +1,7 @@ use bytes::BytesMut; -use http::HeaderMap; -use http::header::{CONTENT_LENGTH, TRANSFER_ENCODING}; use http::header::{HeaderValue, OccupiedEntry, ValueIter}; +use http::header::{CONTENT_LENGTH, TRANSFER_ENCODING}; +use http::HeaderMap; pub fn connection_keep_alive(value: &HeaderValue) -> bool { connection_has(value, "keep-alive") @@ -23,10 +23,7 @@ fn connection_has(value: &HeaderValue, needle: &str) -> bool { } pub fn content_length_parse(value: &HeaderValue) -> Option { - value - .to_str() - .ok() - .and_then(|s| s.parse().ok()) + value.to_str().ok().and_then(|s| s.parse().ok()) } pub fn content_length_parse_all(headers: &HeaderMap) -> Option { @@ -38,23 +35,20 @@ pub fn content_length_parse_all_values(values: ValueIter<'_, HeaderValue>) -> Op // be alright if they all contain the same value, and all parse // correctly. If not, then it's an error. - let folded = values - .fold(None, |prev, line| match prev { - Some(Ok(prev)) => { - Some(line - .to_str() - .map_err(|_| ()) - .and_then(|s| s.parse().map_err(|_| ())) - .and_then(|n| if prev == n { Ok(n) } else { Err(()) })) - }, - None => { - Some(line - .to_str() - .map_err(|_| ()) - .and_then(|s| s.parse().map_err(|_| ()))) - }, - Some(Err(())) => Some(Err(())), - }); + let folded = values.fold(None, |prev, line| match prev { + Some(Ok(prev)) => Some( + line.to_str() + .map_err(|_| ()) + .and_then(|s| s.parse().map_err(|_| ())) + .and_then(|n| if prev == n { Ok(n) } else { Err(()) }), + ), + None => Some( + line.to_str() + .map_err(|_| ()) + .and_then(|s| s.parse().map_err(|_| ())), + ), + Some(Err(())) => Some(Err(())), + }); if let Some(Ok(n)) = folded { Some(n) diff --git a/src/lib.rs b/src/lib.rs index a86bdb45ff..ad5d8846eb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,38 +29,31 @@ //! TCP (using tokio). //! - `stream` (*enabled by default*): Provides `futures::Stream` capabilities. -#[doc(hidden)] pub use http; -#[macro_use] extern crate log; +#[doc(hidden)] +pub use http; +#[macro_use] +extern crate log; #[cfg(all(test, feature = "nightly"))] extern crate test; -pub use http::{ - header, - HeaderMap, - Method, - Request, - Response, - StatusCode, - Uri, - Version, -}; +pub use http::{header, HeaderMap, Method, Request, Response, StatusCode, Uri, Version}; -pub use crate::client::Client; -pub use crate::error::{Result, Error}; pub use crate::body::{Body, Chunk}; +pub use crate::client::Client; +pub use crate::error::{Error, Result}; pub use crate::server::Server; #[macro_use] mod common; -#[cfg(test)] -mod mock; pub mod body; pub mod client; pub mod error; mod headers; +#[cfg(test)] +mod mock; mod proto; +pub mod rt; pub mod server; pub mod service; -pub mod rt; pub mod upgrade; diff --git a/src/proto/h1/conn.rs b/src/proto/h1/conn.rs index 471df9ca29..6cfb2eb736 100644 --- a/src/proto/h1/conn.rs +++ b/src/proto/h1/conn.rs @@ -3,16 +3,16 @@ use std::io::{self}; use std::marker::PhantomData; use bytes::{Buf, Bytes}; -use http::{HeaderMap, Method, Version}; use http::header::{HeaderValue, CONNECTION}; +use http::{HeaderMap, Method, Version}; use tokio::io::{AsyncRead, AsyncWrite}; -use crate::Chunk; -use crate::common::{Pin, Poll, Unpin, task}; -use crate::proto::{BodyLength, DecodedLength, MessageHead}; +use super::io::Buffered; +use super::{/*Decode,*/ Decoder, Encode, EncodedBuf, Encoder, Http1Transaction, ParseContext,}; +use crate::common::{task, Pin, Poll, Unpin}; use crate::headers::connection_keep_alive; -use super::io::{Buffered}; -use super::{EncodedBuf, Encode, Encoder, /*Decode,*/ Decoder, Http1Transaction, ParseContext}; +use crate::proto::{BodyLength, DecodedLength, MessageHead}; +use crate::Chunk; const H2_PREFACE: &'static [u8] = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"; @@ -26,13 +26,14 @@ const H2_PREFACE: &'static [u8] = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"; pub(crate) struct Conn { io: Buffered>, state: State, - _marker: PhantomData + _marker: PhantomData, } impl Conn -where I: AsyncRead + AsyncWrite + Unpin, - B: Buf, - T: Http1Transaction, +where + I: AsyncRead + AsyncWrite + Unpin, + B: Buf, + T: Http1Transaction, { pub fn new(io: I) -> Conn { Conn { @@ -107,7 +108,7 @@ where I: AsyncRead + AsyncWrite + Unpin, _ => true, } } - }, + } _ => false, } } @@ -129,14 +130,20 @@ where I: AsyncRead + AsyncWrite + Unpin, read_buf.len() >= 24 && read_buf[..24] == *H2_PREFACE } - pub fn poll_read_head(&mut self, cx: &mut task::Context<'_>) -> Poll, DecodedLength, bool)>>> { + pub fn poll_read_head( + &mut self, + cx: &mut task::Context<'_>, + ) -> Poll, DecodedLength, bool)>>> { debug_assert!(self.can_read_head()); trace!("Conn::read_head"); - let msg = match ready!(self.io.parse::(cx, ParseContext { - cached_headers: &mut self.state.cached_headers, - req_method: &mut self.state.method, - })) { + let msg = match ready!(self.io.parse::( + cx, + ParseContext { + cached_headers: &mut self.state.cached_headers, + req_method: &mut self.state.method, + } + )) { Ok(msg) => msg, Err(e) => return self.on_read_head_error(e), }; @@ -179,11 +186,14 @@ where I: AsyncRead + AsyncWrite + Unpin, let was_mid_parse = e.is_parse() || !self.io.read_buf().is_empty(); if was_mid_parse || must_error { // We check if the buf contains the h2 Preface - debug!("parse error ({}) with {} bytes", e, self.io.read_buf().len()); + debug!( + "parse error ({}) with {} bytes", + e, + self.io.read_buf().len() + ); match self.on_parse_error(e) { Ok(()) => Poll::Pending, // XXX: wat? Err(e) => Poll::Ready(Some(Err(e))), - } } else { debug!("read eof"); @@ -192,7 +202,10 @@ where I: AsyncRead + AsyncWrite + Unpin, } } - pub fn poll_read_body(&mut self, cx: &mut task::Context<'_>) -> Poll>> { + pub fn poll_read_body( + &mut self, + cx: &mut task::Context<'_>, + ) -> Poll>> { debug_assert!(self.can_read_body()); let (reading, ret) = match self.state.reading { @@ -201,11 +214,14 @@ where I: AsyncRead + AsyncWrite + Unpin, Poll::Ready(Ok(slice)) => { let (reading, chunk) = if decoder.is_eof() { debug!("incoming body completed"); - (Reading::KeepAlive, if !slice.is_empty() { - Some(Ok(Chunk::from(slice))) - } else { - None - }) + ( + Reading::KeepAlive, + if !slice.is_empty() { + Some(Ok(Chunk::from(slice))) + } else { + None + }, + ) } else if slice.is_empty() { error!("incoming body unexpectedly ended"); // This should be unreachable, since all 3 decoders @@ -216,14 +232,14 @@ where I: AsyncRead + AsyncWrite + Unpin, return Poll::Ready(Some(Ok(Chunk::from(slice)))); }; (reading, Poll::Ready(chunk)) - }, + } Poll::Pending => return Poll::Pending, Poll::Ready(Err(e)) => { debug!("incoming body decode error: {}", e); (Reading::Closed, Poll::Ready(Some(Err(e)))) - }, + } } - }, + } _ => unreachable!("read_body invalid state: {:?}", self.state.reading), }; @@ -287,7 +303,10 @@ where I: AsyncRead + AsyncWrite + Unpin, return ret; } - debug!("received unexpected {} bytes on an idle connection", num_read); + debug!( + "received unexpected {} bytes on an idle connection", + num_read + ); Poll::Ready(Err(crate::Error::new_unexpected_message())) } @@ -318,30 +337,23 @@ where I: AsyncRead + AsyncWrite + Unpin, trace!("force_io_read; io error = {:?}", e); self.state.close(); e - })) + })) } - fn maybe_notify(&mut self, cx: &mut task::Context<'_>) { // its possible that we returned NotReady from poll() without having // exhausted the underlying Io. We would have done this when we // determined we couldn't keep reading until we knew how writing // would finish. - - match self.state.reading { - Reading::Body(..) | - Reading::KeepAlive | - Reading::Closed => return, + Reading::Body(..) | Reading::KeepAlive | Reading::Closed => return, Reading::Init => (), }; match self.state.writing { Writing::Body(..) => return, - Writing::Init | - Writing::KeepAlive | - Writing::Closed => (), + Writing::Init | Writing::KeepAlive | Writing::Closed => (), } if !self.io.is_read_blocked() { @@ -357,11 +369,11 @@ where I: AsyncRead + AsyncWrite + Unpin, } return; } - }, + } Poll::Pending => { trace!("maybe_notify; read_from_io blocked"); - return - }, + return; + } Poll::Ready(Err(e)) => { trace!("maybe_notify; read_from_io error: {}", e); self.state.close(); @@ -382,21 +394,19 @@ where I: AsyncRead + AsyncWrite + Unpin, if !T::should_read_first() { match self.state.reading { Reading::Closed => return false, - _ => {}, + _ => {} } } match self.state.writing { Writing::Init => true, - _ => false + _ => false, } } pub fn can_write_body(&self) -> bool { match self.state.writing { Writing::Body(..) => true, - Writing::Init | - Writing::KeepAlive | - Writing::Closed => false, + Writing::Init | Writing::KeepAlive | Writing::Closed => false, } } @@ -417,7 +427,9 @@ where I: AsyncRead + AsyncWrite + Unpin, } pub fn write_full_msg(&mut self, head: MessageHead, body: B) { - if let Some(encoder) = self.encode_head(head, Some(BodyLength::Known(body.remaining() as u64))) { + if let Some(encoder) = + self.encode_head(head, Some(BodyLength::Known(body.remaining() as u64))) + { let is_last = encoder.is_last(); // Make sure we don't write a body if we weren't actually allowed // to do so, like because its a HEAD request. @@ -432,7 +444,11 @@ where I: AsyncRead + AsyncWrite + Unpin, } } - fn encode_head(&mut self, mut head: MessageHead, body: Option) -> Option { + fn encode_head( + &mut self, + mut head: MessageHead, + body: Option, + ) -> Option { debug_assert!(self.can_write_head()); if !T::should_read_first() { @@ -442,24 +458,27 @@ where I: AsyncRead + AsyncWrite + Unpin, self.enforce_version(&mut head); let buf = self.io.headers_buf(); - match T::encode(Encode { - head: &mut head, - body, - keep_alive: self.state.wants_keep_alive(), - req_method: &mut self.state.method, - title_case_headers: self.state.title_case_headers, - }, buf) { + match T::encode( + Encode { + head: &mut head, + body, + keep_alive: self.state.wants_keep_alive(), + req_method: &mut self.state.method, + title_case_headers: self.state.title_case_headers, + }, + buf, + ) { Ok(encoder) => { debug_assert!(self.state.cached_headers.is_none()); debug_assert!(head.headers.is_empty()); self.state.cached_headers = Some(head.headers); Some(encoder) - }, + } Err(err) => { self.state.error = Some(err); self.state.writing = Writing::Closed; None - }, + } } } @@ -478,10 +497,12 @@ where I: AsyncRead + AsyncWrite + Unpin, Version::HTTP_10 => self.state.disable_keep_alive(), // If response is version 1.1 and keep-alive is wanted, add // Connection: keep-alive header when not present - Version::HTTP_11 => if self.state.wants_keep_alive() { - head.headers - .insert(CONNECTION, HeaderValue::from_static("keep-alive")); - }, + Version::HTTP_11 => { + if self.state.wants_keep_alive() { + head.headers + .insert(CONNECTION, HeaderValue::from_static("keep-alive")); + } + } _ => (), } } @@ -490,7 +511,6 @@ where I: AsyncRead + AsyncWrite + Unpin, // If we know the remote speaks an older version, we try to fix up any messages // to work with our older peer. fn enforce_version(&mut self, head: &mut MessageHead) { - match self.state.version { Version::HTTP_10 => { // Fixes response or connection when keep-alive header is not present @@ -498,7 +518,7 @@ where I: AsyncRead + AsyncWrite + Unpin, // If the remote only knows HTTP/1.0, we should force ourselves // to do only speak HTTP/1.0 as well. head.version = Version::HTTP_10; - }, + } _ => { // If the remote speaks HTTP/1.1, then it *should* be fine with // both HTTP/1.0 and HTTP/1.1 from us. So again, we just let @@ -525,7 +545,7 @@ where I: AsyncRead + AsyncWrite + Unpin, } else { return; } - }, + } _ => unreachable!("write_body invalid state: {:?}", self.state.writing), }; @@ -545,7 +565,7 @@ where I: AsyncRead + AsyncWrite + Unpin, } else { Writing::Closed } - }, + } _ => unreachable!("write_body invalid state: {:?}", self.state.writing), }; @@ -568,15 +588,14 @@ where I: AsyncRead + AsyncWrite + Unpin, } else { Writing::KeepAlive } - }, + } Err(_not_eof) => Writing::Closed, } - }, + } _ => return, }; self.state.writing = state; - } // When we get a parse error, depending on what side we are, we might be able @@ -585,11 +604,10 @@ where I: AsyncRead + AsyncWrite + Unpin, // - Client: there is nothing we can do // - Server: if Response hasn't been written yet, we can send a 4xx response fn on_parse_error(&mut self, err: crate::Error) -> crate::Result<()> { - match self.state.writing { Writing::Init => { if self.has_h2_prefix() { - return Err(crate::Error::new_version_h2()) + return Err(crate::Error::new_version_h2()); } if let Some(msg) = T::on_error(&err) { // Drop the cached headers so as to not trigger a debug @@ -619,7 +637,7 @@ where I: AsyncRead + AsyncWrite + Unpin, Ok(()) => { trace!("shut down IO complete"); Poll::Ready(Ok(())) - }, + } Err(e) => { debug!("error shutting down IO: {}", e); Poll::Ready(Err(e)) @@ -741,9 +759,7 @@ impl fmt::Debug for Writing { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { Writing::Init => f.write_str("Init"), - Writing::Body(ref enc) => f.debug_tuple("Body") - .field(enc) - .finish(), + Writing::Body(ref enc) => f.debug_tuple("Body").field(enc).finish(), Writing::KeepAlive => f.write_str("KeepAlive"), Writing::Closed => f.write_str("Closed"), } @@ -824,15 +840,18 @@ impl State { if let KA::Busy = self.keep_alive.status() { self.idle::(); } else { - trace!("try_keep_alive({}): could keep-alive, but status = {:?}", T::LOG, self.keep_alive); + trace!( + "try_keep_alive({}): could keep-alive, but status = {:?}", + T::LOG, + self.keep_alive + ); self.close(); } - }, - (&Reading::Closed, &Writing::KeepAlive) | - (&Reading::KeepAlive, &Writing::Closed) => { + } + (&Reading::Closed, &Writing::KeepAlive) | (&Reading::KeepAlive, &Writing::Closed) => { self.close() } - _ => () + _ => (), } } @@ -880,14 +899,14 @@ impl State { fn is_read_closed(&self) -> bool { match self.reading { Reading::Closed => true, - _ => false + _ => false, } } fn is_write_closed(&self) -> bool { match self.writing { Writing::Closed => true, - _ => false + _ => false, } } @@ -929,11 +948,10 @@ mod tests { let mut headers = x.0.headers; headers.clear(); conn.state.cached_headers = Some(headers); - }, - f => panic!("expected Ready(Some(Ok(..))): {:?}", f) + } + f => panic!("expected Ready(Some(Ok(..))): {:?}", f), } - conn.io.read_buf_mut().reserve(1); unsafe { conn.io.read_buf_mut().set_len(len); diff --git a/src/proto/h1/date.rs b/src/proto/h1/date.rs index abaa3f9c60..3e972d6e00 100644 --- a/src/proto/h1/date.rs +++ b/src/proto/h1/date.rs @@ -24,8 +24,7 @@ pub(crate) fn update_and_header_value() -> HeaderValue { CACHED.with(|cache| { let mut cache = cache.borrow_mut(); cache.check(); - HeaderValue::from_bytes(cache.buffer()) - .expect("Date format should be valid HeaderValue") + HeaderValue::from_bytes(cache.buffer()).expect("Date format should be valid HeaderValue") }) } diff --git a/src/proto/h1/decode.rs b/src/proto/h1/decode.rs index a36f38d7b4..cdebd7a9c0 100644 --- a/src/proto/h1/decode.rs +++ b/src/proto/h1/decode.rs @@ -1,16 +1,16 @@ use std::error::Error as StdError; use std::fmt; -use std::usize; use std::io; +use std::usize; use bytes::Bytes; -use crate::common::{Poll, task}; +use crate::common::{task, Poll}; use super::io::MemRead; -use super::{DecodedLength}; +use super::DecodedLength; -use self::Kind::{Length, Chunked, Eof}; +use self::Kind::{Chunked, Eof, Length}; /// Decoders to handle different Transfer-Encodings. /// @@ -64,15 +64,21 @@ impl Decoder { // constructors pub fn length(x: u64) -> Decoder { - Decoder { kind: Kind::Length(x) } + Decoder { + kind: Kind::Length(x), + } } pub fn chunked() -> Decoder { - Decoder { kind: Kind::Chunked(ChunkedState::Size, 0) } + Decoder { + kind: Kind::Chunked(ChunkedState::Size, 0), + } } pub fn eof() -> Decoder { - Decoder { kind: Kind::Eof(false) } + Decoder { + kind: Kind::Eof(false), + } } pub(super) fn new(len: DecodedLength) -> Self { @@ -87,14 +93,16 @@ impl Decoder { pub fn is_eof(&self) -> bool { match self.kind { - Length(0) | - Chunked(ChunkedState::End, _) | - Eof(true) => true, + Length(0) | Chunked(ChunkedState::End, _) | Eof(true) => true, _ => false, } } - pub fn decode(&mut self, cx: &mut task::Context<'_>, body: &mut R) -> Poll> { + pub fn decode( + &mut self, + cx: &mut task::Context<'_>, + body: &mut R, + ) -> Poll> { trace!("decode; state={:?}", self.kind); match self.kind { Length(ref mut remaining) => { @@ -107,7 +115,10 @@ impl Decoder { if num > *remaining { *remaining = 0; } else if num == 0 { - return Poll::Ready(Err(io::Error::new(io::ErrorKind::UnexpectedEof, IncompleteBody))); + return Poll::Ready(Err(io::Error::new( + io::ErrorKind::UnexpectedEof, + IncompleteBody, + ))); } else { *remaining -= num; } @@ -146,13 +157,10 @@ impl Decoder { #[cfg(test)] async fn decode_fut(&mut self, body: &mut R) -> Result { - futures_util::future::poll_fn(move |cx| { - self.decode(cx, body) - }).await + futures_util::future::poll_fn(move |cx| self.decode(cx, body)).await } } - impl fmt::Debug for Decoder { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&self.kind, f) @@ -172,12 +180,13 @@ macro_rules! byte ( ); impl ChunkedState { - fn step(&self, - cx: &mut task::Context<'_>, - body: &mut R, - size: &mut u64, - buf: &mut Option) - -> Poll> { + fn step( + &self, + cx: &mut task::Context<'_>, + body: &mut R, + size: &mut u64, + buf: &mut Option, + ) -> Poll> { use self::ChunkedState::*; match *self { Size => ChunkedState::read_size(cx, body, size), @@ -192,7 +201,11 @@ impl ChunkedState { End => Poll::Ready(Ok(ChunkedState::End)), } } - fn read_size(cx: &mut task::Context<'_>, rdr: &mut R, size: &mut u64) -> Poll> { + fn read_size( + cx: &mut task::Context<'_>, + rdr: &mut R, + size: &mut u64, + ) -> Poll> { trace!("Read chunk hex size"); let radix = 16; match byte!(rdr, cx) { @@ -212,33 +225,45 @@ impl ChunkedState { b';' => return Poll::Ready(Ok(ChunkedState::Extension)), b'\r' => return Poll::Ready(Ok(ChunkedState::SizeLf)), _ => { - return Poll::Ready(Err(io::Error::new(io::ErrorKind::InvalidInput, - "Invalid chunk size line: Invalid Size"))); + return Poll::Ready(Err(io::Error::new( + io::ErrorKind::InvalidInput, + "Invalid chunk size line: Invalid Size", + ))); } } Poll::Ready(Ok(ChunkedState::Size)) } - fn read_size_lws(cx: &mut task::Context<'_>, rdr: &mut R) -> Poll> { + fn read_size_lws( + cx: &mut task::Context<'_>, + rdr: &mut R, + ) -> Poll> { trace!("read_size_lws"); match byte!(rdr, cx) { // LWS can follow the chunk size, but no more digits can come b'\t' | b' ' => Poll::Ready(Ok(ChunkedState::SizeLws)), b';' => Poll::Ready(Ok(ChunkedState::Extension)), b'\r' => Poll::Ready(Ok(ChunkedState::SizeLf)), - _ => { - Poll::Ready(Err(io::Error::new(io::ErrorKind::InvalidInput, - "Invalid chunk size linear white space"))) - } + _ => Poll::Ready(Err(io::Error::new( + io::ErrorKind::InvalidInput, + "Invalid chunk size linear white space", + ))), } } - fn read_extension(cx: &mut task::Context<'_>, rdr: &mut R) -> Poll> { + fn read_extension( + cx: &mut task::Context<'_>, + rdr: &mut R, + ) -> Poll> { trace!("read_extension"); match byte!(rdr, cx) { b'\r' => Poll::Ready(Ok(ChunkedState::SizeLf)), _ => Poll::Ready(Ok(ChunkedState::Extension)), // no supported extensions } } - fn read_size_lf(cx: &mut task::Context<'_>, rdr: &mut R, size: u64) -> Poll> { + fn read_size_lf( + cx: &mut task::Context<'_>, + rdr: &mut R, + size: u64, + ) -> Poll> { trace!("Chunk size is {:?}", size); match byte!(rdr, cx) { b'\n' => { @@ -248,15 +273,20 @@ impl ChunkedState { debug!("incoming chunked header: {0:#X} ({0} bytes)", size); Poll::Ready(Ok(ChunkedState::Body)) } - }, - _ => Poll::Ready(Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk size LF"))), + } + _ => Poll::Ready(Err(io::Error::new( + io::ErrorKind::InvalidInput, + "Invalid chunk size LF", + ))), } } - fn read_body(cx: &mut task::Context<'_>, rdr: &mut R, - rem: &mut u64, - buf: &mut Option) - -> Poll> { + fn read_body( + cx: &mut task::Context<'_>, + rdr: &mut R, + rem: &mut u64, + buf: &mut Option, + ) -> Poll> { trace!("Chunked read, remaining={:?}", rem); // cap remaining bytes at the max capacity of usize @@ -271,7 +301,10 @@ impl ChunkedState { if count == 0 { *rem = 0; - return Poll::Ready(Err(io::Error::new(io::ErrorKind::UnexpectedEof, IncompleteBody))); + return Poll::Ready(Err(io::Error::new( + io::ErrorKind::UnexpectedEof, + IncompleteBody, + ))); } *buf = Some(slice); *rem -= count as u64; @@ -282,29 +315,53 @@ impl ChunkedState { Poll::Ready(Ok(ChunkedState::BodyCr)) } } - fn read_body_cr(cx: &mut task::Context<'_>, rdr: &mut R) -> Poll> { + fn read_body_cr( + cx: &mut task::Context<'_>, + rdr: &mut R, + ) -> Poll> { match byte!(rdr, cx) { b'\r' => Poll::Ready(Ok(ChunkedState::BodyLf)), - _ => Poll::Ready(Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk body CR"))), + _ => Poll::Ready(Err(io::Error::new( + io::ErrorKind::InvalidInput, + "Invalid chunk body CR", + ))), } } - fn read_body_lf(cx: &mut task::Context<'_>, rdr: &mut R) -> Poll> { + fn read_body_lf( + cx: &mut task::Context<'_>, + rdr: &mut R, + ) -> Poll> { match byte!(rdr, cx) { b'\n' => Poll::Ready(Ok(ChunkedState::Size)), - _ => Poll::Ready(Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk body LF"))), + _ => Poll::Ready(Err(io::Error::new( + io::ErrorKind::InvalidInput, + "Invalid chunk body LF", + ))), } } - fn read_end_cr(cx: &mut task::Context<'_>, rdr: &mut R) -> Poll> { + fn read_end_cr( + cx: &mut task::Context<'_>, + rdr: &mut R, + ) -> Poll> { match byte!(rdr, cx) { b'\r' => Poll::Ready(Ok(ChunkedState::EndLf)), - _ => Poll::Ready(Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk end CR"))), + _ => Poll::Ready(Err(io::Error::new( + io::ErrorKind::InvalidInput, + "Invalid chunk end CR", + ))), } } - fn read_end_lf(cx: &mut task::Context<'_>, rdr: &mut R) -> Poll> { + fn read_end_lf( + cx: &mut task::Context<'_>, + rdr: &mut R, + ) -> Poll> { match byte!(rdr, cx) { b'\n' => Poll::Ready(Ok(ChunkedState::End)), - _ => Poll::Ready(Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk end LF"))), + _ => Poll::Ready(Err(io::Error::new( + io::ErrorKind::InvalidInput, + "Invalid chunk end LF", + ))), } } } @@ -326,10 +383,10 @@ impl StdError for IncompleteBody { #[cfg(test)] mod tests { - use std::time::Duration; + use super::*; use std::pin::Pin; + use std::time::Duration; use tokio::io::AsyncRead; - use super::*; impl<'a> MemRead for &'a [u8] { fn read_mem(&mut self, _: &mut task::Context<'_>, len: usize) -> Poll> { @@ -363,19 +420,18 @@ mod tests { use crate::mock::AsyncIo; */ - #[tokio::test] async fn test_read_chunk_size() { - use std::io::ErrorKind::{UnexpectedEof, InvalidInput}; + use std::io::ErrorKind::{InvalidInput, UnexpectedEof}; async fn read(s: &str) -> u64 { let mut state = ChunkedState::Size; let rdr = &mut s.as_bytes(); let mut size = 0; loop { - let result = futures_util::future::poll_fn(|cx| { - state.step(cx, rdr, &mut size, &mut None) - }).await; + let result = + futures_util::future::poll_fn(|cx| state.step(cx, rdr, &mut size, &mut None)) + .await; let desc = format!("read_size failed for {:?}", s); state = result.expect(desc.as_str()); if state == ChunkedState::Body || state == ChunkedState::EndCr { @@ -390,14 +446,19 @@ mod tests { let rdr = &mut s.as_bytes(); let mut size = 0; loop { - let result = futures_util::future::poll_fn(|cx| { - state.step(cx, rdr, &mut size, &mut None) - }).await; + let result = + futures_util::future::poll_fn(|cx| state.step(cx, rdr, &mut size, &mut None)) + .await; state = match result { Ok(s) => s, Err(e) => { - assert!(expected_err == e.kind(), "Reading {:?}, expected {:?}, but got {:?}", - s, expected_err, e.kind()); + assert!( + expected_err == e.kind(), + "Reading {:?}, expected {:?}, but got {:?}", + s, + expected_err, + e.kind() + ); return; } }; @@ -462,7 +523,10 @@ mod tests { #[tokio::test] async fn test_read_chunked_single_read() { let mut mock_buf = &b"10\r\n1234567890abcdef\r\n0\r\n"[..]; - let buf = Decoder::chunked().decode_fut(&mut mock_buf).await.expect("decode"); + let buf = Decoder::chunked() + .decode_fut(&mut mock_buf) + .await + .expect("decode"); assert_eq!(16, buf.len()); let result = String::from_utf8(buf.as_ref().to_vec()).expect("decode String"); assert_eq!("1234567890abcdef", &result); @@ -490,10 +554,7 @@ mod tests { // perform an async read using a custom buffer size and causing a blocking // read at the specified byte - async fn read_async(mut decoder: Decoder, - content: &[u8], - block_at: usize) - -> String { + async fn read_async(mut decoder: Decoder, content: &[u8], block_at: usize) -> String { let mut outs = Vec::new(); let mut ins = if block_at == 0 { diff --git a/src/proto/h1/dispatch.rs b/src/proto/h1/dispatch.rs index ca1920315d..534cb4233c 100644 --- a/src/proto/h1/dispatch.rs +++ b/src/proto/h1/dispatch.rs @@ -4,10 +4,13 @@ use bytes::{Buf, Bytes}; use http::{Request, Response, StatusCode}; use tokio::io::{AsyncRead, AsyncWrite}; -use crate::body::{Body, Payload}; -use crate::common::{Future, Never, Poll, Pin, Unpin, task}; -use crate::proto::{BodyLength, DecodedLength, Conn, Dispatched, MessageHead, RequestHead, RequestLine, ResponseHead}; use super::Http1Transaction; +use crate::body::{Body, Payload}; +use crate::common::{task, Future, Never, Pin, Poll, Unpin}; +use crate::proto::{ + BodyLength, Conn, DecodedLength, Dispatched, MessageHead, RequestHead, RequestLine, + ResponseHead, +}; use crate::service::HttpService; pub(crate) struct Dispatcher { @@ -23,7 +26,10 @@ pub(crate) trait Dispatch { type PollBody; type PollError; type RecvItem; - fn poll_msg(&mut self, cx: &mut task::Context<'_>) -> Poll>>; + fn poll_msg( + &mut self, + cx: &mut task::Context<'_>, + ) -> Poll>>; fn recv_msg(&mut self, msg: crate::Result<(Self::RecvItem, Body)>) -> crate::Result<()>; fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll>; fn should_poll(&self) -> bool; @@ -44,7 +50,11 @@ type ClientRx = crate::client::dispatch::Receiver, Response> impl Dispatcher where - D: Dispatch, PollBody=Bs, RecvItem=MessageHead> + Unpin, + D: Dispatch< + PollItem = MessageHead, + PollBody = Bs, + RecvItem = MessageHead, + > + Unpin, D::PollError: Into>, I: AsyncRead + AsyncWrite + Unpin, T: Http1Transaction + Unpin, @@ -77,7 +87,10 @@ where /// /// This is useful for old-style HTTP upgrades, but ignores /// newer-style upgrade API. - pub(crate) fn poll_without_shutdown(&mut self, cx: &mut task::Context<'_>) -> Poll> + pub(crate) fn poll_without_shutdown( + &mut self, + cx: &mut task::Context<'_>, + ) -> Poll> where Self: Unpin, { @@ -88,7 +101,11 @@ where }) } - fn poll_catch(&mut self, cx: &mut task::Context<'_>, should_shutdown: bool) -> Poll> { + fn poll_catch( + &mut self, + cx: &mut task::Context<'_>, + should_shutdown: bool, + ) -> Poll> { Poll::Ready(ready!(self.poll_inner(cx, should_shutdown)).or_else(|e| { // An error means we're shutting down either way. // We just try to give the error to the user, @@ -99,7 +116,11 @@ where })) } - fn poll_inner(&mut self, cx: &mut task::Context<'_>, should_shutdown: bool) -> Poll> { + fn poll_inner( + &mut self, + cx: &mut task::Context<'_>, + should_shutdown: bool, + ) -> Poll> { T::update_date(); ready!(self.poll_loop(cx))?; @@ -161,7 +182,7 @@ where Poll::Pending => { self.body_tx = Some(body); return Poll::Pending; - }, + } Poll::Ready(Err(_canceled)) => { // user doesn't care about the body // so we should stop reading @@ -171,22 +192,20 @@ where } } match self.conn.poll_read_body(cx) { - Poll::Ready(Some(Ok(chunk))) => { - match body.try_send_data(chunk) { - Ok(()) => { - self.body_tx = Some(body); - }, - Err(_canceled) => { - if self.conn.can_read_body() { - trace!("body receiver dropped before eof, closing"); - self.conn.close_read(); - } + Poll::Ready(Some(Ok(chunk))) => match body.try_send_data(chunk) { + Ok(()) => { + self.body_tx = Some(body); + } + Err(_canceled) => { + if self.conn.can_read_body() { + trace!("body receiver dropped before eof, closing"); + self.conn.close_read(); } } }, Poll::Ready(None) => { // just drop, the body will close automatically - }, + } Poll::Pending => { self.body_tx = Some(body); return Poll::Pending; @@ -223,14 +242,14 @@ where let (tx, rx) = Body::new_channel(other.into_opt()); self.body_tx = Some(tx); rx - }, + } }; if wants_upgrade { body.set_on_upgrade(self.conn.on_upgrade()); } self.dispatch.recv_msg(Ok((head, body)))?; Poll::Ready(Ok(())) - }, + } Some(Err(err)) => { debug!("read_head error: {}", err); self.dispatch.recv_msg(Err(err))?; @@ -239,7 +258,7 @@ where // not as a second error. self.close(); Poll::Ready(Ok(())) - }, + } None => { // read eof, the write side will have been closed too unless // allow_read_close was set to true, in which case just do @@ -257,7 +276,10 @@ where loop { if self.is_closing { return Poll::Ready(Ok(())); - } else if self.body_rx.is_none() && self.conn.can_write_head() && self.dispatch.should_poll() { + } else if self.body_rx.is_none() + && self.conn.can_write_head() + && self.dispatch.should_poll() + { if let Some(msg) = ready!(self.dispatch.poll_msg(cx)) { let (head, mut body) = msg.map_err(crate::Error::new_user_service)?; @@ -274,7 +296,9 @@ where self.body_rx.set(None); None } else { - let btype = body.size_hint().exact() + let btype = body + .size_hint() + .exact() .map(BodyLength::Known) .or_else(|| Some(BodyLength::Unknown)); self.body_rx.set(Some(body)); @@ -289,7 +313,9 @@ where ready!(self.poll_flush(cx))?; } else { // A new scope is needed :( - if let (Some(mut body), clear_body) = OptGuard::new(self.body_rx.as_mut()).guard_mut() { + if let (Some(mut body), clear_body) = + OptGuard::new(self.body_rx.as_mut()).guard_mut() + { debug_assert!(!*clear_body, "opt guard defaults to keeping body"); if !self.conn.can_write_body() { trace!( @@ -357,8 +383,8 @@ where // a client that cannot read may was well be done. true } else { - let write_done = self.conn.is_write_closed() || - (!self.dispatch.should_poll() && self.body_rx.is_none()); + let write_done = self.conn.is_write_closed() + || (!self.dispatch.should_poll() && self.body_rx.is_none()); read_done && write_done } } @@ -366,7 +392,11 @@ where impl Future for Dispatcher where - D: Dispatch, PollBody=Bs, RecvItem=MessageHead> + Unpin, + D: Dispatch< + PollItem = MessageHead, + PollBody = Bs, + RecvItem = MessageHead, + > + Unpin, D::PollError: Into>, I: AsyncRead + AsyncWrite + Unpin, T: Http1Transaction + Unpin, @@ -427,7 +457,7 @@ impl, B> Unpin for Server {} impl Dispatch for Server where - S: HttpService, + S: HttpService, S::Error: Into>, Bs: Payload, { @@ -436,7 +466,10 @@ where type PollError = S::Error; type RecvItem = RequestHead; - fn poll_msg(&mut self, cx: &mut task::Context<'_>) -> Poll>> { + fn poll_msg( + &mut self, + cx: &mut task::Context<'_>, + ) -> Poll>> { let ret = if let Some(ref mut fut) = self.in_flight.as_mut().as_pin_mut() { let resp = ready!(fut.as_mut().poll(cx)?); let (parts, body) = resp.into_parts(); @@ -471,11 +504,10 @@ where if self.in_flight.is_some() { Poll::Pending } else { - self.service.poll_ready(cx) - .map_err(|_e| { - // FIXME: return error value. - trace!("service closed"); - }) + self.service.poll_ready(cx).map_err(|_e| { + // FIXME: return error value. + trace!("service closed"); + }) } } @@ -486,7 +518,6 @@ where // ===== impl Client ===== - impl Client { pub fn new(rx: ClientRx) -> Client { Client { @@ -506,7 +537,10 @@ where type PollError = Never; type RecvItem = ResponseHead; - fn poll_msg(&mut self, cx: &mut task::Context<'_>) -> Poll>> { + fn poll_msg( + &mut self, + cx: &mut task::Context<'_>, + ) -> Poll>> { debug_assert!(!self.rx_closed); match self.rx.poll_next(cx) { Poll::Ready(Some((req, mut cb))) => { @@ -515,7 +549,7 @@ where Poll::Ready(()) => { trace!("request canceled"); Poll::Ready(None) - }, + } Poll::Pending => { let (parts, body) = req.into_parts(); let head = RequestHead { @@ -527,13 +561,13 @@ where Poll::Ready(Some(Ok((head, body)))) } } - }, + } Poll::Ready(None) => { // user has dropped sender handle trace!("client tx closed"); self.rx_closed = true; Poll::Ready(None) - }, + } Poll::Pending => Poll::Pending, } } @@ -554,7 +588,7 @@ where // full message! Err(crate::Error::new_unexpected_message()) } - }, + } Err(err) => { if let Some(cb) = self.callback.take() { let _ = cb.send(Err((err, None))); @@ -583,7 +617,7 @@ where Poll::Ready(()) => { trace!("callback receiver has dropped"); Poll::Ready(Err(())) - }, + } Poll::Pending => Poll::Ready(Ok(())), }, None => Poll::Ready(Err(())), @@ -597,18 +631,16 @@ where #[cfg(test)] mod tests { - use std::time::Duration; use super::*; use crate::proto::h1::ClientTransaction; + use std::time::Duration; #[test] fn client_read_bytes_before_writing_request() { let _ = pretty_env_logger::try_init(); tokio_test::task::spawn(()).enter(|cx, _| { - - let (io, mut handle) = tokio_test::io::Builder::new() - .build_with_handle(); + let (io, mut handle) = tokio_test::io::Builder::new().build_with_handle(); // Block at 0 for now, but we will release this response before // the request is ready to write later... @@ -624,7 +656,9 @@ mod tests { // handle.read(b"HTTP/1.1 200 OK\r\n\r\n"); - let mut res_rx = tx.try_send(crate::Request::new(crate::Body::empty())).unwrap(); + let mut res_rx = tx + .try_send(crate::Request::new(crate::Body::empty())) + .unwrap(); tokio_test::assert_ready_ok!(Pin::new(&mut dispatcher).poll(cx)); let err = tokio_test::assert_ready_ok!(Pin::new(&mut res_rx).poll(cx)) diff --git a/src/proto/h1/encode.rs b/src/proto/h1/encode.rs index 241ebeefe2..810926bd7f 100644 --- a/src/proto/h1/encode.rs +++ b/src/proto/h1/encode.rs @@ -1,8 +1,8 @@ use std::fmt; use std::io::IoSlice; -use bytes::Buf; use bytes::buf::ext::{BufExt, Chain, Take}; +use bytes::Buf; use super::io::WriteBuf; @@ -68,7 +68,7 @@ impl Encoder { pub fn is_eof(&self) -> bool { match self.kind { Kind::Length(0) => true, - _ => false + _ => false, } } @@ -105,7 +105,7 @@ impl Encoder { .chain(msg) .chain(b"\r\n" as &'static [u8]); BufKind::Chunked(buf) - }, + } Kind::Length(ref mut remaining) => { trace!("sized write, len = {}", len); if len as u64 > *remaining { @@ -116,15 +116,13 @@ impl Encoder { *remaining -= len as u64; BufKind::Exact(msg) } - }, + } Kind::CloseDelimited => { trace!("close delimited write {}B", len); BufKind::Exact(msg) } }; - EncodedBuf { - kind, - } + EncodedBuf { kind } } pub(super) fn encode_and_end(&self, msg: B, dst: &mut WriteBuf>) -> bool @@ -142,7 +140,7 @@ impl Encoder { .chain(b"\r\n0\r\n\r\n" as &'static [u8]); dst.buffer(buf); !self.is_last - }, + } Kind::Length(remaining) => { use std::cmp::Ordering; @@ -151,17 +149,17 @@ impl Encoder { Ordering::Equal => { dst.buffer(msg); !self.is_last - }, + } Ordering::Greater => { dst.buffer(msg.take(remaining as usize)); !self.is_last - }, + } Ordering::Less => { dst.buffer(msg); false } } - }, + } Kind::CloseDelimited => { trace!("close delimited write {}B", len); dst.buffer(msg); @@ -180,10 +178,13 @@ impl Encoder { B: Buf, { debug_assert!(msg.remaining() > 0, "encode() called with empty buf"); - debug_assert!(match self.kind { - Kind::Length(len) => len == msg.remaining() as u64, - _ => true, - }, "danger_full_buf length mismatches"); + debug_assert!( + match self.kind { + Kind::Length(len) => len == msg.remaining() as u64, + _ => true, + }, + "danger_full_buf length mismatches" + ); match self.kind { Kind::Chunked => { @@ -193,10 +194,10 @@ impl Encoder { .chain(msg) .chain(b"\r\n0\r\n\r\n" as &'static [u8]); dst.buffer(buf); - }, + } _ => { dst.buffer(msg); - }, + } } } } @@ -246,7 +247,6 @@ where } } - #[cfg(target_pointer_width = "32")] const USIZE_BYTES: usize = 4; @@ -271,8 +271,7 @@ impl ChunkSize { pos: 0, len: 0, }; - write!(&mut size, "{:X}\r\n", len) - .expect("CHUNK_SIZE_MAX_BYTES should fit any usize"); + write!(&mut size, "{:X}\r\n", len).expect("CHUNK_SIZE_MAX_BYTES should fit any usize"); size } } @@ -285,7 +284,7 @@ impl Buf for ChunkSize { #[inline] fn bytes(&self) -> &[u8] { - &self.bytes[self.pos.into() .. self.len.into()] + &self.bytes[self.pos.into()..self.len.into()] } #[inline] @@ -307,7 +306,8 @@ impl fmt::Debug for ChunkSize { impl fmt::Write for ChunkSize { fn write_str(&mut self, num: &str) -> fmt::Result { use std::io::Write; - (&mut self.bytes[self.len.into()..]).write(num.as_bytes()) + (&mut self.bytes[self.len.into()..]) + .write(num.as_bytes()) .expect("&mut [u8].write() cannot error"); self.len += num.len() as u8; // safe because bytes is never bigger than 256 Ok(()) @@ -340,7 +340,7 @@ impl From, StaticBuf>> for EncodedBuf { #[cfg(test)] mod tests { - use bytes::{BufMut}; + use bytes::BufMut; use super::super::io::Cursor; use super::Encoder; @@ -364,7 +364,10 @@ mod tests { let end = encoder.end::>>().unwrap().unwrap(); dst.put(end); - assert_eq!(dst, b"7\r\nfoo bar\r\nD\r\nbaz quux herp\r\n0\r\n\r\n".as_ref()); + assert_eq!( + dst, + b"7\r\nfoo bar\r\nD\r\nbaz quux herp\r\n0\r\n\r\n".as_ref() + ); } #[test] @@ -373,12 +376,10 @@ mod tests { let mut encoder = Encoder::length(max_len as u64); let mut dst = Vec::new(); - let msg1 = b"foo bar".as_ref(); let buf1 = encoder.encode(msg1); dst.put(buf1); - assert_eq!(dst, b"foo bar"); assert!(!encoder.is_eof()); encoder.end::<()>().unwrap_err(); @@ -398,12 +399,10 @@ mod tests { let mut encoder = Encoder::close_delimited(); let mut dst = Vec::new(); - let msg1 = b"foo bar".as_ref(); let buf1 = encoder.encode(msg1); dst.put(buf1); - assert_eq!(dst, b"foo bar"); assert!(!encoder.is_eof()); encoder.end::<()>().unwrap_err(); diff --git a/src/proto/h1/io.rs b/src/proto/h1/io.rs index 75f5f0deee..02f5a70773 100644 --- a/src/proto/h1/io.rs +++ b/src/proto/h1/io.rs @@ -7,8 +7,8 @@ use std::io::{self, IoSlice}; use bytes::{Buf, BufMut, Bytes, BytesMut}; use tokio::io::{AsyncRead, AsyncWrite}; -use crate::common::{Pin, Poll, Unpin, task}; use super::{Http1Transaction, ParseContext, ParsedMessage}; +use crate::common::{task, Pin, Poll, Unpin}; /// The initial buffer size allocated before trying to read from IO. pub(crate) const INIT_BUFFER_SIZE: usize = 8192; @@ -140,34 +140,40 @@ where } } - pub(super) fn parse(&mut self, cx: &mut task::Context<'_>, parse_ctx: ParseContext<'_>) - -> Poll>> + pub(super) fn parse( + &mut self, + cx: &mut task::Context<'_>, + parse_ctx: ParseContext<'_>, + ) -> Poll>> where S: Http1Transaction, { loop { - match S::parse(&mut self.read_buf, ParseContext { - cached_headers: parse_ctx.cached_headers, - req_method: parse_ctx.req_method, - })? { + match S::parse( + &mut self.read_buf, + ParseContext { + cached_headers: parse_ctx.cached_headers, + req_method: parse_ctx.req_method, + }, + )? { Some(msg) => { debug!("parsed {} headers", msg.head.headers.len()); return Poll::Ready(Ok(msg)); - }, + } None => { let max = self.read_buf_strategy.max(); if self.read_buf.len() >= max { debug!("max_buf_size ({}) reached, closing", max); return Poll::Ready(Err(crate::Error::new_too_large())); } - }, + } } match ready!(self.poll_read_from_io(cx)).map_err(crate::Error::new_io)? { 0 => { trace!("parse eof"); return Poll::Ready(Err(crate::Error::new_incomplete())); } - _ => {}, + _ => {} } } } @@ -180,10 +186,10 @@ where } match Pin::new(&mut self.io).poll_read_buf(cx, &mut self.read_buf) { Poll::Ready(Ok(n)) => { - debug!("read {} bytes", n); - self.read_buf_strategy.record(n); - Poll::Ready(Ok(n)) - }, + debug!("read {} bytes", n); + self.read_buf_strategy.record(n); + Poll::Ready(Ok(n)) + } Poll::Pending => { self.read_blocked = true; Poll::Pending @@ -215,12 +221,16 @@ where _ => (), } loop { - let n = ready!(Pin::new(&mut self.io).poll_write_buf(cx, &mut self.write_buf.auto()))?; + let n = + ready!(Pin::new(&mut self.io).poll_write_buf(cx, &mut self.write_buf.auto()))?; debug!("flushed {} bytes", n); if self.write_buf.remaining() == 0 { break; } else if n == 0 { - trace!("write returned zero, but {} bytes remaining", self.write_buf.remaining()); + trace!( + "write returned zero, but {} bytes remaining", + self.write_buf.remaining() + ); return Poll::Ready(Err(io::ErrorKind::WriteZero.into())); } } @@ -241,7 +251,10 @@ where self.write_buf.headers.reset(); break; } else if n == 0 { - trace!("write returned zero, but {} bytes remaining", self.write_buf.remaining()); + trace!( + "write returned zero, but {} bytes remaining", + self.write_buf.remaining() + ); return Poll::Ready(Err(io::ErrorKind::WriteZero.into())); } } @@ -283,7 +296,7 @@ enum ReadStrategy { Adaptive { decrease_now: bool, next: usize, - max: usize + max: usize, }, Exact(usize), } @@ -313,7 +326,12 @@ impl ReadStrategy { fn record(&mut self, bytes_read: usize) { match *self { - ReadStrategy::Adaptive { ref mut decrease_now, ref mut next, max, .. } => { + ReadStrategy::Adaptive { + ref mut decrease_now, + ref mut next, + max, + .. + } => { if bytes_read >= *next { *next = cmp::min(incr_power_of_two(*next), max); *decrease_now = false; @@ -334,7 +352,7 @@ impl ReadStrategy { *decrease_now = false; } } - }, + } _ => (), } } @@ -428,7 +446,6 @@ impl WriteBuf { } } - impl WriteBuf where B: Buf, @@ -460,22 +477,19 @@ where }; buf.advance(adv); } - }, + } WriteStrategy::Auto | WriteStrategy::Queue => { self.queue.bufs.push_back(buf.into()); - }, + } } } fn can_buffer(&self) -> bool { match self.strategy { - WriteStrategy::Flatten => { - self.remaining() < self.max_buf_size - }, + WriteStrategy::Flatten => self.remaining() < self.max_buf_size, WriteStrategy::Auto | WriteStrategy::Queue => { - self.queue.bufs.len() < MAX_BUF_LIST_BUFFERS - && self.remaining() < self.max_buf_size - }, + self.queue.bufs.len() < MAX_BUF_LIST_BUFFERS && self.remaining() < self.max_buf_size + } } } @@ -587,7 +601,6 @@ impl<'a, B: Buf + 'a> Drop for WriteBufAuto<'a, B> { } } - #[derive(Debug)] enum WriteStrategy { Auto, @@ -599,7 +612,6 @@ struct BufDeque { bufs: VecDeque, } - impl BufDeque { fn new() -> BufDeque { BufDeque { @@ -611,9 +623,7 @@ impl BufDeque { impl Buf for BufDeque { #[inline] fn remaining(&self) -> usize { - self.bufs.iter() - .map(|buf| buf.remaining()) - .sum() + self.bufs.iter().map(|buf| buf.remaining()).sum() } #[inline] @@ -683,9 +693,11 @@ mod tests { // First, let's just check that the Mock would normally return an // error on an unexpected write, even if the buffer is empty... let mut mock = Mock::new().build(); - futures_util::future::poll_fn(|cx| Pin::new(&mut mock).poll_write_buf(cx, &mut Cursor::new(&[]))) - .await - .expect_err("should be a broken pipe"); + futures_util::future::poll_fn(|cx| { + Pin::new(&mut mock).poll_write_buf(cx, &mut Cursor::new(&[])) + }) + .await + .expect_err("should be a broken pipe"); // underlying io will return the logic error upon write, // so we are testing that the io_buf does not trigger a write @@ -716,11 +728,17 @@ mod tests { cached_headers: &mut None, req_method: &mut None, }; - assert!(buffered.parse::(cx, parse_ctx).is_pending()); + assert!(buffered + .parse::(cx, parse_ctx) + .is_pending()); Poll::Ready(()) - }).await; + }) + .await; - assert_eq!(buffered.read_buf, b"HTTP/1.1 200 OK\r\nServer: hyper\r\n"[..]); + assert_eq!( + buffered.read_buf, + b"HTTP/1.1 200 OK\r\nServer: hyper\r\n"[..] + ); } #[test] @@ -756,12 +774,20 @@ mod tests { assert_eq!(strategy.next(), 16384); strategy.record(1); - assert_eq!(strategy.next(), 16384, "first smaller record doesn't decrement yet"); + assert_eq!( + strategy.next(), + 16384, + "first smaller record doesn't decrement yet" + ); strategy.record(8192); assert_eq!(strategy.next(), 16384, "record was with range"); strategy.record(1); - assert_eq!(strategy.next(), 16384, "in-range record should make this the 'first' again"); + assert_eq!( + strategy.next(), + 16384, + "in-range record should make this the 'first' again" + ); strategy.record(1); assert_eq!(strategy.next(), 8192, "second smaller record decrements"); @@ -779,10 +805,18 @@ mod tests { assert_eq!(strategy.next(), 16384); strategy.record(8193); - assert_eq!(strategy.next(), 16384, "first smaller record doesn't decrement yet"); + assert_eq!( + strategy.next(), + 16384, + "first smaller record doesn't decrement yet" + ); strategy.record(8193); - assert_eq!(strategy.next(), 16384, "with current step does not decrement"); + assert_eq!( + strategy.next(), + 16384, + "with current step does not decrement" + ); } #[test] diff --git a/src/proto/h1/mod.rs b/src/proto/h1/mod.rs index 65cea1391d..39efb8e7b8 100644 --- a/src/proto/h1/mod.rs +++ b/src/proto/h1/mod.rs @@ -1,11 +1,11 @@ use bytes::BytesMut; use http::{HeaderMap, Method}; -use crate::proto::{MessageHead, BodyLength, DecodedLength}; +use crate::proto::{BodyLength, DecodedLength, MessageHead}; pub(crate) use self::conn::Conn; -pub(crate) use self::dispatch::Dispatcher; pub use self::decode::Decoder; +pub(crate) use self::dispatch::Dispatcher; pub use self::encode::{EncodedBuf, Encoder}; pub use self::io::Cursor; //TODO: move out of h1::io pub use self::io::MINIMUM_MAX_BUFFER_SIZE; @@ -18,7 +18,6 @@ mod encode; mod io; mod role; - pub(crate) type ServerTransaction = role::Server; pub(crate) type ClientTransaction = role::Client; @@ -75,4 +74,3 @@ pub(crate) struct Encode<'a, T> { req_method: &'a mut Option, title_case_headers: bool, } - diff --git a/src/proto/h1/role.rs b/src/proto/h1/role.rs index 5c44590342..1adf708103 100644 --- a/src/proto/h1/role.rs +++ b/src/proto/h1/role.rs @@ -5,38 +5,42 @@ use std::fmt::{self, Write}; use std::mem; -use bytes::{BytesMut}; +use bytes::BytesMut; use http::header::{self, Entry, HeaderName, HeaderValue}; use http::{HeaderMap, Method, StatusCode, Version}; use crate::error::Parse; use crate::headers; -use crate::proto::{BodyLength, DecodedLength, MessageHead, RequestLine, RequestHead}; -use crate::proto::h1::{Encode, Encoder, Http1Transaction, ParseResult, ParseContext, ParsedMessage, date}; +use crate::proto::h1::{ + date, Encode, Encoder, Http1Transaction, ParseContext, ParseResult, ParsedMessage, +}; +use crate::proto::{BodyLength, DecodedLength, MessageHead, RequestHead, RequestLine}; const MAX_HEADERS: usize = 100; const AVERAGE_HEADER_SIZE: usize = 30; // totally scientific macro_rules! header_name { - ($bytes:expr) => ({ + ($bytes:expr) => {{ #[cfg(debug_assertions)] { match HeaderName::from_bytes($bytes) { Ok(name) => name, - Err(_) => panic!("illegal header name from httparse: {:?}", ::bytes::Bytes::copy_from_slice($bytes)), + Err(_) => panic!( + "illegal header name from httparse: {:?}", + ::bytes::Bytes::copy_from_slice($bytes) + ), } } #[cfg(not(debug_assertions))] { - HeaderName::from_bytes($bytes) - .expect("header name validated by httparse") + HeaderName::from_bytes($bytes).expect("header name validated by httparse") } - }); + }}; } macro_rules! header_value { - ($bytes:expr) => ({ + ($bytes:expr) => {{ #[cfg(debug_assertions)] { let __hvb: ::bytes::Bytes = $bytes; @@ -49,11 +53,9 @@ macro_rules! header_value { #[cfg(not(debug_assertions))] { // Unsafe: httparse already validated header value - unsafe { - HeaderValue::from_maybe_shared_unchecked($bytes) - } + unsafe { HeaderValue::from_maybe_shared_unchecked($bytes) } } - }); + }}; } // There are 2 main roles, Client and Server. @@ -86,7 +88,11 @@ impl Http1Transaction for Server { let mut headers_indices: [HeaderIndices; MAX_HEADERS] = unsafe { mem::uninitialized() }; { let mut headers: [httparse::Header<'_>; MAX_HEADERS] = unsafe { mem::uninitialized() }; - trace!("Request.parse([Header; {}], [u8; {}])", headers.len(), buf.len()); + trace!( + "Request.parse([Header; {}], [u8; {}])", + headers.len(), + buf.len() + ); let mut req = httparse::Request::new(&mut headers); let bytes = buf.as_ref(); match req.parse(bytes) { @@ -95,7 +101,7 @@ impl Http1Transaction for Server { len = parsed_len; subject = RequestLine( Method::from_bytes(req.method.unwrap().as_bytes())?, - req.path.unwrap().parse()? + req.path.unwrap().parse()?, ); version = if req.version.unwrap() == 1 { keep_alive = true; @@ -111,18 +117,20 @@ impl Http1Transaction for Server { headers_len = req.headers.len(); } Ok(httparse::Status::Partial) => return Ok(None), - Err(err) => return Err(match err { - // if invalid Token, try to determine if for method or path - httparse::Error::Token => { - if req.method.is_none() { - Parse::Method - } else { - debug_assert!(req.path.is_none()); - Parse::Uri + Err(err) => { + return Err(match err { + // if invalid Token, try to determine if for method or path + httparse::Error::Token => { + if req.method.is_none() { + Parse::Method + } else { + debug_assert!(req.path.is_none()); + Parse::Uri + } } - }, - other => other.into(), - }), + other => other.into(), + }); + } } }; @@ -137,7 +145,6 @@ impl Http1Transaction for Server { // 6. Length 0. // 7. (irrelevant to Request) - let mut decoder = DecodedLength::ZERO; let mut expect_continue = false; let mut con_len = None; @@ -145,9 +152,7 @@ impl Http1Transaction for Server { let mut is_te_chunked = false; let mut wants_upgrade = subject.0 == Method::CONNECT; - let mut headers = ctx.cached_headers - .take() - .unwrap_or_else(HeaderMap::new); + let mut headers = ctx.cached_headers.take().unwrap_or_else(HeaderMap::new); headers.reserve(headers_len); @@ -170,20 +175,20 @@ impl Http1Transaction for Server { is_te_chunked = true; decoder = DecodedLength::CHUNKED; } - }, + } header::CONTENT_LENGTH => { if is_te { continue; } - let len = value.to_str() + let len = value + .to_str() .map_err(|_| Parse::Header) .and_then(|s| s.parse().map_err(|_| Parse::Header))?; if let Some(prev) = con_len { if prev != len { debug!( "multiple Content-Length headers with different values: [{}, {}]", - prev, - len, + prev, len, ); return Err(Parse::Header); } @@ -192,25 +197,24 @@ impl Http1Transaction for Server { } decoder = DecodedLength::checked_new(len)?; con_len = Some(len); - }, + } header::CONNECTION => { // keep_alive was previously set to default for Version if keep_alive { // HTTP/1.1 keep_alive = !headers::connection_close(&value); - } else { // HTTP/1.0 keep_alive = headers::connection_keep_alive(&value); } - }, + } header::EXPECT => { expect_continue = value.as_bytes() == b"100-continue"; - }, + } header::UPGRADE => { // Upgrades are only allowed with HTTP/1.1 wants_upgrade = is_http_11; - }, + } _ => (), } @@ -238,14 +242,20 @@ impl Http1Transaction for Server { })) } - fn encode(mut msg: Encode<'_, Self::Outgoing>, mut dst: &mut Vec) -> crate::Result { + fn encode( + mut msg: Encode<'_, Self::Outgoing>, + mut dst: &mut Vec, + ) -> crate::Result { trace!( "Server::encode status={:?}, body={:?}, req_method={:?}", msg.head.subject, msg.body, msg.req_method ); - debug_assert!(!msg.title_case_headers, "no server config for title case headers"); + debug_assert!( + !msg.title_case_headers, + "no server config for title case headers" + ); let mut wrote_len = false; @@ -289,14 +299,21 @@ impl Http1Transaction for Server { Version::HTTP_2 => { warn!("response with HTTP2 version coerced to HTTP/1.1"); extend(dst, b"HTTP/1.1 "); - }, + } other => panic!("unexpected response version: {:?}", other), } extend(dst, msg.head.subject.as_str().as_bytes()); extend(dst, b" "); // a reason MUST be written, as many parsers will expect it. - extend(dst, msg.head.subject.canonical_reason().unwrap_or("").as_bytes()); + extend( + dst, + msg.head + .subject + .canonical_reason() + .unwrap_or("") + .as_bytes(), + ); extend(dst, b"\r\n"); } @@ -308,11 +325,11 @@ impl Http1Transaction for Server { let mut prev_con_len = None; macro_rules! handle_is_name_written { - () => ({ + () => {{ if is_name_written { // we need to clean up and write the newline debug_assert_ne!( - &dst[dst.len() - 2 ..], + &dst[dst.len() - 2..], b"\r\n", "previous header wrote newline but set is_name_written" ); @@ -323,7 +340,7 @@ impl Http1Transaction for Server { extend(dst, b"\r\n"); } } - }) + }}; } 'headers: for (opt_name, value) in msg.head.headers.drain() { @@ -369,7 +386,7 @@ impl Http1Transaction for Server { is_name_written = true; } continue 'headers; - }, + } Some(BodyLength::Unknown) => { // The Payload impl didn't know how long the // body is, but a length header was included. @@ -379,7 +396,10 @@ impl Http1Transaction for Server { if let Some(len) = headers::content_length_parse(&value) { if let Some(prev) = prev_con_len { if prev != len { - warn!("multiple Content-Length values found: [{}, {}]", prev, len); + warn!( + "multiple Content-Length values found: [{}, {}]", + prev, len + ); rewind(dst); return Err(crate::Error::new_user_header()); } @@ -400,7 +420,7 @@ impl Http1Transaction for Server { rewind(dst); return Err(crate::Error::new_user_header()); } - }, + } None => { // We have no body to actually send, // but the headers claim a content-length. @@ -412,14 +432,17 @@ impl Http1Transaction for Server { debug_assert_eq!(encoder, Encoder::length(0)); } else { if value.as_bytes() != b"0" { - warn!("content-length value found, but empty body provided: {:?}", value); + warn!( + "content-length value found, but empty body provided: {:?}", + value + ); } continue 'headers; } } } wrote_len = true; - }, + } header::TRANSFER_ENCODING => { if wrote_len && !is_name_written { warn!("unexpected transfer-encoding found, canceling"); @@ -427,7 +450,9 @@ impl Http1Transaction for Server { return Err(crate::Error::new_user_header()); } // check that we actually can send a chunked body... - if msg.head.version == Version::HTTP_10 || !Server::can_chunked(msg.req_method, msg.head.subject) { + if msg.head.version == Version::HTTP_10 + || !Server::can_chunked(msg.req_method, msg.head.subject) + { continue; } wrote_len = true; @@ -445,7 +470,7 @@ impl Http1Transaction for Server { extend(dst, value.as_bytes()); } continue 'headers; - }, + } header::CONNECTION => { if !is_last { if headers::connection_close(&value) { @@ -461,10 +486,10 @@ impl Http1Transaction for Server { extend(dst, value.as_bytes()); } continue 'headers; - }, + } header::DATE => { wrote_date = true; - }, + } _ => (), } //TODO: this should perhaps instead combine them into @@ -487,20 +512,21 @@ impl Http1Transaction for Server { if !wrote_len { encoder = match msg.body { Some(BodyLength::Unknown) => { - if msg.head.version == Version::HTTP_10 || !Server::can_chunked(msg.req_method, msg.head.subject) { + if msg.head.version == Version::HTTP_10 + || !Server::can_chunked(msg.req_method, msg.head.subject) + { Encoder::close_delimited() } else { extend(dst, b"transfer-encoding: chunked\r\n"); Encoder::chunked() } - }, - None | - Some(BodyLength::Known(0)) => { + } + None | Some(BodyLength::Known(0)) => { if msg.head.subject != StatusCode::NOT_MODIFIED { extend(dst, b"content-length: 0\r\n"); } Encoder::length(0) - }, + } Some(BodyLength::Known(len)) => { if msg.head.subject == StatusCode::NOT_MODIFIED { Encoder::length(0) @@ -510,7 +536,7 @@ impl Http1Transaction for Server { extend(dst, b"\r\n"); Encoder::length(len) } - }, + } }; } @@ -539,15 +565,11 @@ impl Http1Transaction for Server { fn on_error(err: &crate::Error) -> Option> { use crate::error::Kind; let status = match *err.kind() { - Kind::Parse(Parse::Method) | - Kind::Parse(Parse::Header) | - Kind::Parse(Parse::Uri) | - Kind::Parse(Parse::Version) => { - StatusCode::BAD_REQUEST - }, - Kind::Parse(Parse::TooLarge) => { - StatusCode::REQUEST_HEADER_FIELDS_TOO_LARGE - }, + Kind::Parse(Parse::Method) + | Kind::Parse(Parse::Header) + | Kind::Parse(Parse::Uri) + | Kind::Parse(Parse::Version) => StatusCode::BAD_REQUEST, + Kind::Parse(Parse::TooLarge) => StatusCode::REQUEST_HEADER_FIELDS_TOO_LARGE, _ => return None, }; @@ -580,9 +602,9 @@ impl Server { match status { // TODO: support for 1xx codes needs improvement everywhere // would be 100...199 => false - StatusCode::SWITCHING_PROTOCOLS | - StatusCode::NO_CONTENT | - StatusCode::NOT_MODIFIED => false, + StatusCode::SWITCHING_PROTOCOLS + | StatusCode::NO_CONTENT + | StatusCode::NOT_MODIFIED => false, _ => true, } } @@ -603,8 +625,13 @@ impl Http1Transaction for Client { // Unsafe: see comment in Server Http1Transaction, above. let mut headers_indices: [HeaderIndices; MAX_HEADERS] = unsafe { mem::uninitialized() }; let (len, status, version, headers_len) = { - let mut headers: [httparse::Header<'_>; MAX_HEADERS] = unsafe { mem::uninitialized() }; - trace!("Response.parse([Header; {}], [u8; {}])", headers.len(), buf.len()); + let mut headers: [httparse::Header<'_>; MAX_HEADERS] = + unsafe { mem::uninitialized() }; + trace!( + "Response.parse([Header; {}], [u8; {}])", + headers.len(), + buf.len() + ); let mut res = httparse::Response::new(&mut headers); let bytes = buf.as_ref(); match res.parse(bytes)? { @@ -619,16 +646,14 @@ impl Http1Transaction for Client { record_header_indices(bytes, &res.headers, &mut headers_indices)?; let headers_len = res.headers.len(); (len, status, version, headers_len) - }, + } httparse::Status::Partial => return Ok(None), } }; let slice = buf.split_to(len).freeze(); - let mut headers = ctx.cached_headers - .take() - .unwrap_or_else(HeaderMap::new); + let mut headers = ctx.cached_headers.take().unwrap_or_else(HeaderMap::new); let mut keep_alive = version == Version::HTTP_11; @@ -639,15 +664,14 @@ impl Http1Transaction for Client { if let header::CONNECTION = name { // keep_alive was previously set to default for Version - if keep_alive { - // HTTP/1.1 - keep_alive = !headers::connection_close(&value); - - } else { - // HTTP/1.0 - keep_alive = headers::connection_keep_alive(&value); - } + if keep_alive { + // HTTP/1.1 + keep_alive = !headers::connection_close(&value); + } else { + // HTTP/1.0 + keep_alive = headers::connection_keep_alive(&value); } + } headers.append(name, value); } @@ -667,12 +691,15 @@ impl Http1Transaction for Client { wants_upgrade: is_upgrade, })); } - } } fn encode(msg: Encode<'_, Self::Outgoing>, dst: &mut Vec) -> crate::Result { - trace!("Client::encode method={:?}, body={:?}", msg.head.subject.0, msg.body); + trace!( + "Client::encode method={:?}, body={:?}", + msg.head.subject.0, + msg.body + ); *msg.req_method = Some(msg.head.subject.0.clone()); @@ -681,7 +708,6 @@ impl Http1Transaction for Client { let init_cap = 30 + msg.head.headers.len() * AVERAGE_HEADER_SIZE; dst.reserve(init_cap); - extend(dst, msg.head.subject.0.as_str().as_bytes()); extend(dst, b" "); //TODO: add API to http::Uri to encode without std::fmt @@ -693,7 +719,7 @@ impl Http1Transaction for Client { Version::HTTP_2 => { warn!("request with HTTP2 version coerced to HTTP/1.1"); extend(dst, b"HTTP/1.1"); - }, + } other => panic!("unexpected request version: {:?}", other), } extend(dst, b"\r\n"); @@ -723,7 +749,10 @@ impl Client { /// Returns Some(length, wants_upgrade) if successful. /// /// Returns None if this message head should be skipped (like a 100 status). - fn decoder(inc: &MessageHead, method: &mut Option) -> Result, Parse> { + fn decoder( + inc: &MessageHead, + method: &mut Option, + ) -> Result, Parse> { // According to https://tools.ietf.org/html/rfc7230#section-3.3.3 // 1. HEAD responses, and Status 1xx, 204, and 304 cannot have a body. // 2. Status 2xx to a CONNECT cannot have a body. @@ -736,23 +765,24 @@ impl Client { match inc.subject.as_u16() { 101 => { return Ok(Some((DecodedLength::ZERO, true))); - }, + } 100..=199 => { trace!("ignoring informational response: {}", inc.subject.as_u16()); return Ok(None); - }, - 204 | - 304 => return Ok(Some((DecodedLength::ZERO, false))), + } + 204 | 304 => return Ok(Some((DecodedLength::ZERO, false))), _ => (), } match *method { Some(Method::HEAD) => { return Ok(Some((DecodedLength::ZERO, false))); } - Some(Method::CONNECT) => if let 200..=299 = inc.subject.as_u16() { - return Ok(Some((DecodedLength::ZERO, true))); + Some(Method::CONNECT) => { + if let 200..=299 = inc.subject.as_u16() { + return Ok(Some((DecodedLength::ZERO, true))); + } } - Some(_) => {}, + Some(_) => {} None => { trace!("Client::decoder is missing the Method"); } @@ -790,7 +820,7 @@ impl Client { body } else { head.headers.remove(header::TRANSFER_ENCODING); - return Encoder::length(0) + return Encoder::length(0); }; // HTTP/1.0 doesn't know about chunked @@ -853,7 +883,7 @@ impl Client { headers::add_chunked(te); Some(Encoder::chunked()) } - }, + } Entry::Vacant(te) => { if let Some(len) = existing_con_len { Some(Encoder::length(len)) @@ -864,20 +894,16 @@ impl Client { // assume no body here. If you *must* send a body, // set the headers explicitly. match head.subject.0 { - Method::GET | - Method::HEAD | - Method::CONNECT => { - Some(Encoder::length(0)) - }, + Method::GET | Method::HEAD | Method::CONNECT => Some(Encoder::length(0)), _ => { te.insert(HeaderValue::from_static("chunked")); Some(Encoder::chunked()) - }, + } } } else { None } - }, + } }; // This is because we need a second mutable borrow to remove @@ -923,7 +949,7 @@ fn set_content_length(headers: &mut HeaderMap, len: u64) -> Encoder { cl.insert(HeaderValue::from(len)); Encoder::length(len) - }, + } Entry::Vacant(cl) => { cl.insert(HeaderValue::from(len)); Encoder::length(len) @@ -944,7 +970,7 @@ struct HeaderIndices { fn record_header_indices( bytes: &[u8], headers: &[httparse::Header<'_>], - indices: &mut [HeaderIndices] + indices: &mut [HeaderIndices], ) -> Result<(), crate::error::Parse> { let bytes_ptr = bytes.as_ptr() as usize; @@ -983,17 +1009,17 @@ fn title_case(dst: &mut Vec, name: &[u8]) { } while let Some(c) = iter.next() { - dst.push(*c); - - if *c == b'-' { - if let Some(c) = iter.next() { - if *c >= b'a' && *c <= b'z' { - dst.push(*c ^ b' '); - } else { - dst.push(*c); - } - } - } + dst.push(*c); + + if *c == b'-' { + if let Some(c) = iter.next() { + if *c >= b'a' && *c <= b'z' { + dst.push(*c ^ b' '); + } else { + dst.push(*c); + } + } + } } } @@ -1046,10 +1072,15 @@ mod tests { let _ = pretty_env_logger::try_init(); let mut raw = BytesMut::from("GET /echo HTTP/1.1\r\nHost: hyper.rs\r\n\r\n"); let mut method = None; - let msg = Server::parse(&mut raw, ParseContext { - cached_headers: &mut None, - req_method: &mut method, - }).unwrap().unwrap(); + let msg = Server::parse( + &mut raw, + ParseContext { + cached_headers: &mut None, + req_method: &mut method, + }, + ) + .unwrap() + .unwrap(); assert_eq!(raw.len(), 0); assert_eq!(msg.head.subject.0, crate::Method::GET); assert_eq!(msg.head.subject.1, "/echo"); @@ -1059,7 +1090,6 @@ mod tests { assert_eq!(method, Some(crate::Method::GET)); } - #[test] fn test_parse_response() { let _ = pretty_env_logger::try_init(); @@ -1086,337 +1116,524 @@ mod tests { Server::parse(&mut raw, ctx).unwrap_err(); } - #[test] fn test_decoder_request() { fn parse(s: &str) -> ParsedMessage { let mut bytes = BytesMut::from(s); - Server::parse(&mut bytes, ParseContext { - cached_headers: &mut None, - req_method: &mut None, - }) - .expect("parse ok") - .expect("parse complete") + Server::parse( + &mut bytes, + ParseContext { + cached_headers: &mut None, + req_method: &mut None, + }, + ) + .expect("parse ok") + .expect("parse complete") } fn parse_err(s: &str, comment: &str) -> crate::error::Parse { let mut bytes = BytesMut::from(s); - Server::parse(&mut bytes, ParseContext { - cached_headers: &mut None, - req_method: &mut None, - }) - .expect_err(comment) + Server::parse( + &mut bytes, + ParseContext { + cached_headers: &mut None, + req_method: &mut None, + }, + ) + .expect_err(comment) } // no length or transfer-encoding means 0-length body - assert_eq!(parse("\ - GET / HTTP/1.1\r\n\ - \r\n\ - ").decode, DecodedLength::ZERO); + assert_eq!( + parse( + "\ + GET / HTTP/1.1\r\n\ + \r\n\ + " + ) + .decode, + DecodedLength::ZERO + ); - assert_eq!(parse("\ - POST / HTTP/1.1\r\n\ - \r\n\ - ").decode, DecodedLength::ZERO); + assert_eq!( + parse( + "\ + POST / HTTP/1.1\r\n\ + \r\n\ + " + ) + .decode, + DecodedLength::ZERO + ); // transfer-encoding: chunked - assert_eq!(parse("\ - POST / HTTP/1.1\r\n\ - transfer-encoding: chunked\r\n\ - \r\n\ - ").decode, DecodedLength::CHUNKED); - - assert_eq!(parse("\ - POST / HTTP/1.1\r\n\ - transfer-encoding: gzip, chunked\r\n\ - \r\n\ - ").decode, DecodedLength::CHUNKED); - - assert_eq!(parse("\ - POST / HTTP/1.1\r\n\ - transfer-encoding: gzip\r\n\ - transfer-encoding: chunked\r\n\ - \r\n\ - ").decode, DecodedLength::CHUNKED); + assert_eq!( + parse( + "\ + POST / HTTP/1.1\r\n\ + transfer-encoding: chunked\r\n\ + \r\n\ + " + ) + .decode, + DecodedLength::CHUNKED + ); + + assert_eq!( + parse( + "\ + POST / HTTP/1.1\r\n\ + transfer-encoding: gzip, chunked\r\n\ + \r\n\ + " + ) + .decode, + DecodedLength::CHUNKED + ); + + assert_eq!( + parse( + "\ + POST / HTTP/1.1\r\n\ + transfer-encoding: gzip\r\n\ + transfer-encoding: chunked\r\n\ + \r\n\ + " + ) + .decode, + DecodedLength::CHUNKED + ); // content-length - assert_eq!(parse("\ - POST / HTTP/1.1\r\n\ - content-length: 10\r\n\ - \r\n\ - ").decode, DecodedLength::new(10)); + assert_eq!( + parse( + "\ + POST / HTTP/1.1\r\n\ + content-length: 10\r\n\ + \r\n\ + " + ) + .decode, + DecodedLength::new(10) + ); // transfer-encoding and content-length = chunked - assert_eq!(parse("\ - POST / HTTP/1.1\r\n\ - content-length: 10\r\n\ - transfer-encoding: chunked\r\n\ - \r\n\ - ").decode, DecodedLength::CHUNKED); - - assert_eq!(parse("\ - POST / HTTP/1.1\r\n\ - transfer-encoding: chunked\r\n\ - content-length: 10\r\n\ - \r\n\ - ").decode, DecodedLength::CHUNKED); - - assert_eq!(parse("\ - POST / HTTP/1.1\r\n\ - transfer-encoding: gzip\r\n\ - content-length: 10\r\n\ - transfer-encoding: chunked\r\n\ - \r\n\ - ").decode, DecodedLength::CHUNKED); + assert_eq!( + parse( + "\ + POST / HTTP/1.1\r\n\ + content-length: 10\r\n\ + transfer-encoding: chunked\r\n\ + \r\n\ + " + ) + .decode, + DecodedLength::CHUNKED + ); + + assert_eq!( + parse( + "\ + POST / HTTP/1.1\r\n\ + transfer-encoding: chunked\r\n\ + content-length: 10\r\n\ + \r\n\ + " + ) + .decode, + DecodedLength::CHUNKED + ); + assert_eq!( + parse( + "\ + POST / HTTP/1.1\r\n\ + transfer-encoding: gzip\r\n\ + content-length: 10\r\n\ + transfer-encoding: chunked\r\n\ + \r\n\ + " + ) + .decode, + DecodedLength::CHUNKED + ); // multiple content-lengths of same value are fine - assert_eq!(parse("\ - POST / HTTP/1.1\r\n\ - content-length: 10\r\n\ - content-length: 10\r\n\ - \r\n\ - ").decode, DecodedLength::new(10)); - + assert_eq!( + parse( + "\ + POST / HTTP/1.1\r\n\ + content-length: 10\r\n\ + content-length: 10\r\n\ + \r\n\ + " + ) + .decode, + DecodedLength::new(10) + ); // multiple content-lengths with different values is an error - parse_err("\ - POST / HTTP/1.1\r\n\ - content-length: 10\r\n\ - content-length: 11\r\n\ - \r\n\ - ", "multiple content-lengths"); + parse_err( + "\ + POST / HTTP/1.1\r\n\ + content-length: 10\r\n\ + content-length: 11\r\n\ + \r\n\ + ", + "multiple content-lengths", + ); // transfer-encoding that isn't chunked is an error - parse_err("\ - POST / HTTP/1.1\r\n\ - transfer-encoding: gzip\r\n\ - \r\n\ - ", "transfer-encoding but not chunked"); - - parse_err("\ - POST / HTTP/1.1\r\n\ - transfer-encoding: chunked, gzip\r\n\ - \r\n\ - ", "transfer-encoding doesn't end in chunked"); + parse_err( + "\ + POST / HTTP/1.1\r\n\ + transfer-encoding: gzip\r\n\ + \r\n\ + ", + "transfer-encoding but not chunked", + ); + parse_err( + "\ + POST / HTTP/1.1\r\n\ + transfer-encoding: chunked, gzip\r\n\ + \r\n\ + ", + "transfer-encoding doesn't end in chunked", + ); // http/1.0 - assert_eq!(parse("\ - POST / HTTP/1.0\r\n\ - content-length: 10\r\n\ - \r\n\ - ").decode, DecodedLength::new(10)); - + assert_eq!( + parse( + "\ + POST / HTTP/1.0\r\n\ + content-length: 10\r\n\ + \r\n\ + " + ) + .decode, + DecodedLength::new(10) + ); // 1.0 doesn't understand chunked, so its an error - parse_err("\ - POST / HTTP/1.0\r\n\ - transfer-encoding: chunked\r\n\ - \r\n\ - ", "1.0 chunked"); + parse_err( + "\ + POST / HTTP/1.0\r\n\ + transfer-encoding: chunked\r\n\ + \r\n\ + ", + "1.0 chunked", + ); } #[test] fn test_decoder_response() { - fn parse(s: &str) -> ParsedMessage { parse_with_method(s, Method::GET) } fn parse_ignores(s: &str) { let mut bytes = BytesMut::from(s); - assert!(Client::parse(&mut bytes, ParseContext { - cached_headers: &mut None, - req_method: &mut Some(Method::GET), - }) - .expect("parse ok") - .is_none()) + assert!(Client::parse( + &mut bytes, + ParseContext { + cached_headers: &mut None, + req_method: &mut Some(Method::GET), + } + ) + .expect("parse ok") + .is_none()) } fn parse_with_method(s: &str, m: Method) -> ParsedMessage { let mut bytes = BytesMut::from(s); - Client::parse(&mut bytes, ParseContext { - cached_headers: &mut None, - req_method: &mut Some(m), - }) - .expect("parse ok") - .expect("parse complete") + Client::parse( + &mut bytes, + ParseContext { + cached_headers: &mut None, + req_method: &mut Some(m), + }, + ) + .expect("parse ok") + .expect("parse complete") } fn parse_err(s: &str) -> crate::error::Parse { let mut bytes = BytesMut::from(s); - Client::parse(&mut bytes, ParseContext { - cached_headers: &mut None, - req_method: &mut Some(Method::GET), - }) - .expect_err("parse should err") + Client::parse( + &mut bytes, + ParseContext { + cached_headers: &mut None, + req_method: &mut Some(Method::GET), + }, + ) + .expect_err("parse should err") } - // no content-length or transfer-encoding means close-delimited - assert_eq!(parse("\ - HTTP/1.1 200 OK\r\n\ - \r\n\ - ").decode, DecodedLength::CLOSE_DELIMITED); + assert_eq!( + parse( + "\ + HTTP/1.1 200 OK\r\n\ + \r\n\ + " + ) + .decode, + DecodedLength::CLOSE_DELIMITED + ); // 204 and 304 never have a body - assert_eq!(parse("\ - HTTP/1.1 204 No Content\r\n\ - \r\n\ - ").decode, DecodedLength::ZERO); + assert_eq!( + parse( + "\ + HTTP/1.1 204 No Content\r\n\ + \r\n\ + " + ) + .decode, + DecodedLength::ZERO + ); - assert_eq!(parse("\ - HTTP/1.1 304 Not Modified\r\n\ - \r\n\ - ").decode, DecodedLength::ZERO); + assert_eq!( + parse( + "\ + HTTP/1.1 304 Not Modified\r\n\ + \r\n\ + " + ) + .decode, + DecodedLength::ZERO + ); // content-length - assert_eq!(parse("\ - HTTP/1.1 200 OK\r\n\ - content-length: 8\r\n\ - \r\n\ - ").decode, DecodedLength::new(8)); - - assert_eq!(parse("\ - HTTP/1.1 200 OK\r\n\ - content-length: 8\r\n\ - content-length: 8\r\n\ - \r\n\ - ").decode, DecodedLength::new(8)); - - parse_err("\ - HTTP/1.1 200 OK\r\n\ - content-length: 8\r\n\ - content-length: 9\r\n\ - \r\n\ - "); + assert_eq!( + parse( + "\ + HTTP/1.1 200 OK\r\n\ + content-length: 8\r\n\ + \r\n\ + " + ) + .decode, + DecodedLength::new(8) + ); + assert_eq!( + parse( + "\ + HTTP/1.1 200 OK\r\n\ + content-length: 8\r\n\ + content-length: 8\r\n\ + \r\n\ + " + ) + .decode, + DecodedLength::new(8) + ); + + parse_err( + "\ + HTTP/1.1 200 OK\r\n\ + content-length: 8\r\n\ + content-length: 9\r\n\ + \r\n\ + ", + ); // transfer-encoding - assert_eq!(parse("\ - HTTP/1.1 200 OK\r\n\ - transfer-encoding: chunked\r\n\ - \r\n\ - ").decode, DecodedLength::CHUNKED); + assert_eq!( + parse( + "\ + HTTP/1.1 200 OK\r\n\ + transfer-encoding: chunked\r\n\ + \r\n\ + " + ) + .decode, + DecodedLength::CHUNKED + ); // transfer-encoding and content-length = chunked - assert_eq!(parse("\ - HTTP/1.1 200 OK\r\n\ - content-length: 10\r\n\ - transfer-encoding: chunked\r\n\ - \r\n\ - ").decode, DecodedLength::CHUNKED); - + assert_eq!( + parse( + "\ + HTTP/1.1 200 OK\r\n\ + content-length: 10\r\n\ + transfer-encoding: chunked\r\n\ + \r\n\ + " + ) + .decode, + DecodedLength::CHUNKED + ); // HEAD can have content-length, but not body - assert_eq!(parse_with_method("\ - HTTP/1.1 200 OK\r\n\ - content-length: 8\r\n\ - \r\n\ - ", Method::HEAD).decode, DecodedLength::ZERO); + assert_eq!( + parse_with_method( + "\ + HTTP/1.1 200 OK\r\n\ + content-length: 8\r\n\ + \r\n\ + ", + Method::HEAD + ) + .decode, + DecodedLength::ZERO + ); // CONNECT with 200 never has body { - let msg = parse_with_method("\ - HTTP/1.1 200 OK\r\n\ - \r\n\ - ", Method::CONNECT); + let msg = parse_with_method( + "\ + HTTP/1.1 200 OK\r\n\ + \r\n\ + ", + Method::CONNECT, + ); assert_eq!(msg.decode, DecodedLength::ZERO); assert!(!msg.keep_alive, "should be upgrade"); assert!(msg.wants_upgrade, "should be upgrade"); } // CONNECT receiving non 200 can have a body - assert_eq!(parse_with_method("\ - HTTP/1.1 400 Bad Request\r\n\ - \r\n\ - ", Method::CONNECT).decode, DecodedLength::CLOSE_DELIMITED); - + assert_eq!( + parse_with_method( + "\ + HTTP/1.1 400 Bad Request\r\n\ + \r\n\ + ", + Method::CONNECT + ) + .decode, + DecodedLength::CLOSE_DELIMITED + ); // 1xx status codes - parse_ignores("\ - HTTP/1.1 100 Continue\r\n\ - \r\n\ - "); + parse_ignores( + "\ + HTTP/1.1 100 Continue\r\n\ + \r\n\ + ", + ); - parse_ignores("\ - HTTP/1.1 103 Early Hints\r\n\ - \r\n\ - "); + parse_ignores( + "\ + HTTP/1.1 103 Early Hints\r\n\ + \r\n\ + ", + ); // 101 upgrade not supported yet { - let msg = parse("\ - HTTP/1.1 101 Switching Protocols\r\n\ - \r\n\ - "); + let msg = parse( + "\ + HTTP/1.1 101 Switching Protocols\r\n\ + \r\n\ + ", + ); assert_eq!(msg.decode, DecodedLength::ZERO); assert!(!msg.keep_alive, "should be last"); assert!(msg.wants_upgrade, "should be upgrade"); } - // http/1.0 - assert_eq!(parse("\ - HTTP/1.0 200 OK\r\n\ - \r\n\ - ").decode, DecodedLength::CLOSE_DELIMITED); + assert_eq!( + parse( + "\ + HTTP/1.0 200 OK\r\n\ + \r\n\ + " + ) + .decode, + DecodedLength::CLOSE_DELIMITED + ); // 1.0 doesn't understand chunked - parse_err("\ - HTTP/1.0 200 OK\r\n\ - transfer-encoding: chunked\r\n\ - \r\n\ - "); + parse_err( + "\ + HTTP/1.0 200 OK\r\n\ + transfer-encoding: chunked\r\n\ + \r\n\ + ", + ); // keep-alive - assert!(parse("\ - HTTP/1.1 200 OK\r\n\ - content-length: 0\r\n\ - \r\n\ - ").keep_alive, "HTTP/1.1 keep-alive is default"); - - assert!(!parse("\ - HTTP/1.1 200 OK\r\n\ - content-length: 0\r\n\ - connection: foo, close, bar\r\n\ - \r\n\ - ").keep_alive, "connection close is always close"); - - assert!(!parse("\ - HTTP/1.0 200 OK\r\n\ - content-length: 0\r\n\ - \r\n\ - ").keep_alive, "HTTP/1.0 close is default"); - - assert!(parse("\ - HTTP/1.0 200 OK\r\n\ - content-length: 0\r\n\ - connection: foo, keep-alive, bar\r\n\ - \r\n\ - ").keep_alive, "connection keep-alive is always keep-alive"); + assert!( + parse( + "\ + HTTP/1.1 200 OK\r\n\ + content-length: 0\r\n\ + \r\n\ + " + ) + .keep_alive, + "HTTP/1.1 keep-alive is default" + ); + + assert!( + !parse( + "\ + HTTP/1.1 200 OK\r\n\ + content-length: 0\r\n\ + connection: foo, close, bar\r\n\ + \r\n\ + " + ) + .keep_alive, + "connection close is always close" + ); + + assert!( + !parse( + "\ + HTTP/1.0 200 OK\r\n\ + content-length: 0\r\n\ + \r\n\ + " + ) + .keep_alive, + "HTTP/1.0 close is default" + ); + + assert!( + parse( + "\ + HTTP/1.0 200 OK\r\n\ + content-length: 0\r\n\ + connection: foo, keep-alive, bar\r\n\ + \r\n\ + " + ) + .keep_alive, + "connection keep-alive is always keep-alive" + ); } #[test] fn test_client_request_encode_title_case() { - use http::header::HeaderValue; use crate::proto::BodyLength; + use http::header::HeaderValue; let mut head = MessageHead::default(); - head.headers.insert("content-length", HeaderValue::from_static("10")); - head.headers.insert("content-type", HeaderValue::from_static("application/json")); + head.headers + .insert("content-length", HeaderValue::from_static("10")); + head.headers + .insert("content-type", HeaderValue::from_static("application/json")); head.headers.insert("*-*", HeaderValue::from_static("o_o")); let mut vec = Vec::new(); - Client::encode(Encode { - head: &mut head, - body: Some(BodyLength::Known(10)), - keep_alive: true, - req_method: &mut None, - title_case_headers: true, - }, &mut vec).unwrap(); + Client::encode( + Encode { + head: &mut head, + body: Some(BodyLength::Known(10)), + keep_alive: true, + req_method: &mut None, + title_case_headers: true, + }, + &mut vec, + ) + .unwrap(); assert_eq!(vec, b"GET / HTTP/1.1\r\nContent-Length: 10\r\nContent-Type: application/json\r\n*-*: o_o\r\n\r\n".to_vec()); } @@ -1426,13 +1643,17 @@ mod tests { let mut head = MessageHead::default(); let mut vec = Vec::new(); - let encoder = Server::encode(Encode { - head: &mut head, - body: None, - keep_alive: true, - req_method: &mut Some(Method::CONNECT), - title_case_headers: false, - }, &mut vec).unwrap(); + let encoder = Server::encode( + Encode { + head: &mut head, + body: None, + keep_alive: true, + req_method: &mut Some(Method::CONNECT), + title_case_headers: false, + }, + &mut vec, + ) + .unwrap(); assert!(encoder.is_last()); } @@ -1440,12 +1661,15 @@ mod tests { #[test] fn parse_header_htabs() { let mut bytes = BytesMut::from("HTTP/1.1 200 OK\r\nserver: hello\tworld\r\n\r\n"); - let parsed = Client::parse(&mut bytes, ParseContext { - cached_headers: &mut None, - req_method: &mut Some(Method::GET), - }) - .expect("parse ok") - .expect("parse complete"); + let parsed = Client::parse( + &mut bytes, + ParseContext { + cached_headers: &mut None, + req_method: &mut Some(Method::GET), + }, + ) + .expect("parse ok") + .expect("parse complete"); assert_eq!(parsed.head.headers["server"], "hello\tworld"); } @@ -1473,24 +1697,28 @@ mod tests { X-Content-Duration: None\r\nX-Content-Security-Policy: None\ \r\nX-DNSPrefetch-Control: None\r\nX-Frame-Options: \ Something important obviously\r\nX-Requested-With: Nothing\ - \r\n\r\n"[..] + \r\n\r\n"[..], ); let len = raw.len(); let mut headers = Some(HeaderMap::new()); b.bytes = len as u64; b.iter(|| { - let mut msg = Server::parse(&mut raw, ParseContext { - cached_headers: &mut headers, - req_method: &mut None, - }).unwrap().unwrap(); + let mut msg = Server::parse( + &mut raw, + ParseContext { + cached_headers: &mut headers, + req_method: &mut None, + }, + ) + .unwrap() + .unwrap(); ::test::black_box(&msg); msg.head.headers.clear(); headers = Some(msg.head.headers); restart(&mut raw, len); }); - fn restart(b: &mut BytesMut, len: usize) { b.reserve(1); unsafe { @@ -1509,17 +1737,21 @@ mod tests { b.bytes = len as u64; b.iter(|| { - let mut msg = Server::parse(&mut raw, ParseContext { - cached_headers: &mut headers, - req_method: &mut None, - }).unwrap().unwrap(); + let mut msg = Server::parse( + &mut raw, + ParseContext { + cached_headers: &mut headers, + req_method: &mut None, + }, + ) + .unwrap() + .unwrap(); ::test::black_box(&msg); msg.head.headers.clear(); headers = Some(msg.head.headers); restart(&mut raw, len); }); - fn restart(b: &mut BytesMut, len: usize) { b.reserve(1); unsafe { @@ -1531,8 +1763,8 @@ mod tests { #[cfg(feature = "nightly")] #[bench] fn bench_server_encode_headers_preset(b: &mut Bencher) { - use http::header::HeaderValue; use crate::proto::BodyLength; + use http::header::HeaderValue; let len = 108; b.bytes = len as u64; @@ -1545,13 +1777,17 @@ mod tests { b.iter(|| { let mut vec = Vec::new(); head.headers = headers.clone(); - Server::encode(Encode { - head: &mut head, - body: Some(BodyLength::Known(10)), - keep_alive: true, - req_method: &mut Some(Method::GET), - title_case_headers: false, - }, &mut vec).unwrap(); + Server::encode( + Encode { + head: &mut head, + body: Some(BodyLength::Known(10)), + keep_alive: true, + req_method: &mut Some(Method::GET), + title_case_headers: false, + }, + &mut vec, + ) + .unwrap(); assert_eq!(vec.len(), len); ::test::black_box(vec); }) @@ -1569,13 +1805,17 @@ mod tests { let mut vec = Vec::with_capacity(128); b.iter(|| { - Server::encode(Encode { - head: &mut head, - body: Some(BodyLength::Known(10)), - keep_alive: true, - req_method: &mut Some(Method::GET), - title_case_headers: false, - }, &mut vec).unwrap(); + Server::encode( + Encode { + head: &mut head, + body: Some(BodyLength::Known(10)), + keep_alive: true, + req_method: &mut Some(Method::GET), + title_case_headers: false, + }, + &mut vec, + ) + .unwrap(); assert_eq!(vec.len(), len); ::test::black_box(&vec); diff --git a/src/proto/h2/client.rs b/src/proto/h2/client.rs index 9d186bc96b..d0d251fc55 100644 --- a/src/proto/h2/client.rs +++ b/src/proto/h2/client.rs @@ -1,15 +1,15 @@ use futures_channel::{mpsc, oneshot}; -use futures_util::future::{self, FutureExt as _, TryFutureExt as _, Either}; +use futures_util::future::{self, Either, FutureExt as _, TryFutureExt as _}; use futures_util::stream::StreamExt as _; use h2::client::{Builder, SendRequest}; use tokio::io::{AsyncRead, AsyncWrite}; -use crate::headers::content_length_parse_all; +use super::{PipeToSendStream, SendBuf}; use crate::body::Payload; -use crate::common::{Exec, Future, Never, Pin, Poll, task}; +use crate::common::{task, Exec, Future, Never, Pin, Poll}; use crate::headers; +use crate::headers::content_length_parse_all; use crate::proto::Dispatched; -use super::{PipeToSendStream, SendBuf}; use crate::{Body, Request, Response}; type ClientRx = crate::client::dispatch::Receiver, Response>; @@ -45,13 +45,10 @@ where let (conn_drop_ref, rx) = mpsc::channel(1); let (cancel_tx, conn_eof) = oneshot::channel(); - let conn_drop_rx = rx.into_future() - .map(|(item, _rx)| { - match item { - Some(never) => match never {}, - None => (), - } - }); + let conn_drop_rx = rx.into_future().map(|(item, _rx)| match item { + Some(never) => match never {}, + None => (), + }); let conn = conn.map_err(|e| debug!("connection error: {}", e)); @@ -138,12 +135,11 @@ where }; if !eos { - let mut pipe = PipeToSendStream::new(body, body_tx) - .map(|res| { - if let Err(e) = res { - debug!("client request body error: {}", e); - } - }); + let mut pipe = PipeToSendStream::new(body, body_tx).map(|res| { + if let Err(e) = res { + debug!("client request body error: {}", e); + } + }); // eagerly see if the body pipe is ready and // can thus skip allocating in the executor @@ -152,45 +148,39 @@ where Poll::Pending => { let conn_drop_ref = self.conn_drop_ref.clone(); let pipe = pipe.map(move |x| { - drop(conn_drop_ref); - x - }); + drop(conn_drop_ref); + x + }); self.executor.execute(pipe); } } } - let fut = fut - .map(move |result| { - match result { - Ok(res) => { - let content_length = content_length_parse_all(res.headers()); - let res = res.map(|stream| - crate::Body::h2(stream, content_length)); - Ok(res) - }, - Err(err) => { - debug!("client response error: {}", err); - Err((crate::Error::new_h2(err), None)) - } - } - }); + let fut = fut.map(move |result| match result { + Ok(res) => { + let content_length = content_length_parse_all(res.headers()); + let res = res.map(|stream| crate::Body::h2(stream, content_length)); + Ok(res) + } + Err(err) => { + debug!("client response error: {}", err); + Err((crate::Error::new_h2(err), None)) + } + }); self.executor.execute(cb.send_when(fut)); continue; - }, + } Poll::Ready(None) => { trace!("client::dispatch::Sender dropped"); return Poll::Ready(Ok(Dispatched::Shutdown)); } - Poll::Pending => { - match ready!(Pin::new(&mut self.conn_eof).poll(cx)) { - Ok(never) => match never {}, - Err(_conn_is_eof) => { - trace!("connection task is closed, closing dispatch task"); - return Poll::Ready(Ok(Dispatched::Shutdown)); - } + Poll::Pending => match ready!(Pin::new(&mut self.conn_eof).poll(cx)) { + Ok(never) => match never {}, + Err(_conn_is_eof) => { + trace!("connection task is closed, closing dispatch task"); + return Poll::Ready(Ok(Dispatched::Shutdown)); } }, } diff --git a/src/proto/h2/mod.rs b/src/proto/h2/mod.rs index a4d1a509d9..4a81f3c749 100644 --- a/src/proto/h2/mod.rs +++ b/src/proto/h2/mod.rs @@ -1,5 +1,5 @@ use bytes::Buf; -use h2::{SendStream}; +use h2::SendStream; use http::header::{ HeaderName, CONNECTION, PROXY_AUTHENTICATE, PROXY_AUTHORIZATION, TE, TRAILER, TRANSFER_ENCODING, UPGRADE, @@ -7,7 +7,7 @@ use http::header::{ use http::HeaderMap; use crate::body::Payload; -use crate::common::{Future, Pin, Poll, task}; +use crate::common::{task, Future, Pin, Poll}; pub(crate) mod client; pub(crate) mod server; @@ -38,7 +38,11 @@ fn strip_connection_headers(headers: &mut HeaderMap, is_request: bool) { } if is_request { - if headers.get(TE).map(|te_header| te_header != "trailers").unwrap_or(false) { + if headers + .get(TE) + .map(|te_header| te_header != "trailers") + .unwrap_or(false) + { warn!("TE headers not set to \"trailers\" are illegal in HTTP/2 requests"); headers.remove(TE); } @@ -123,19 +127,24 @@ where if self.body_tx.capacity() == 0 { loop { match ready!(self.body_tx.poll_capacity(cx)) { - - Some(Ok(0)) => {}, + Some(Ok(0)) => {} Some(Ok(_)) => break, - Some(Err(e)) => return Poll::Ready(Err(crate::Error::new_body_write(e))) , + Some(Err(e)) => { + return Poll::Ready(Err(crate::Error::new_body_write(e))) + } None => return Poll::Ready(Err(crate::Error::new_canceled())), } } } else { - if let Poll::Ready(reason) = - self.body_tx.poll_reset(cx).map_err(crate::Error::new_body_write)? + if let Poll::Ready(reason) = self + .body_tx + .poll_reset(cx) + .map_err(crate::Error::new_body_write)? { debug!("stream received RST_STREAM: {:?}", reason); - return Poll::Ready(Err(crate::Error::new_body_write(::h2::Error::from(reason)))); + return Poll::Ready(Err(crate::Error::new_body_write(::h2::Error::from( + reason, + )))); } } @@ -170,11 +179,15 @@ where } } } else { - if let Poll::Ready(reason) = - self.body_tx.poll_reset(cx).map_err(|e| crate::Error::new_body_write(e))? + if let Poll::Ready(reason) = self + .body_tx + .poll_reset(cx) + .map_err(|e| crate::Error::new_body_write(e))? { debug!("stream received RST_STREAM: {:?}", reason); - return Poll::Ready(Err(crate::Error::new_body_write(::h2::Error::from(reason)))); + return Poll::Ready(Err(crate::Error::new_body_write(::h2::Error::from( + reason, + )))); } match ready!(Pin::new(&mut self.stream).poll_trailers(cx)) { diff --git a/src/proto/h2/server.rs b/src/proto/h2/server.rs index 9d5346f04b..094748aeb3 100644 --- a/src/proto/h2/server.rs +++ b/src/proto/h2/server.rs @@ -1,19 +1,19 @@ use std::error::Error as StdError; use std::marker::Unpin; -use pin_project::{pin_project, project}; -use h2::Reason; use h2::server::{Builder, Connection, Handshake, SendResponse}; +use h2::Reason; +use pin_project::{pin_project, project}; use tokio::io::{AsyncRead, AsyncWrite}; +use super::{PipeToSendStream, SendBuf}; use crate::body::Payload; use crate::common::exec::H2Exec; -use crate::common::{Future, Pin, Poll, task}; +use crate::common::{task, Future, Pin, Poll}; use crate::headers; use crate::headers::content_length_parse_all; -use crate::service::HttpService; use crate::proto::Dispatched; -use super::{PipeToSendStream, SendBuf}; +use crate::service::HttpService; use crate::{Body, Response}; @@ -45,11 +45,10 @@ where closing: Option, } - impl Server where T: AsyncRead + AsyncWrite + Unpin, - S: HttpService, + S: HttpService, S::Error: Into>, B: Payload, B::Data: Unpin, @@ -69,13 +68,13 @@ where match self.state { State::Handshaking(..) => { // fall-through, to replace state with Closed - }, + } State::Serving(ref mut srv) => { if srv.closing.is_none() { srv.conn.graceful_shutdown(); } return; - }, + } State::Closed => { return; } @@ -87,7 +86,7 @@ where impl Future for Server where T: AsyncRead + AsyncWrite + Unpin, - S: HttpService, + S: HttpService, S::Error: Into>, B: Payload, B::Data: Unpin, @@ -105,7 +104,7 @@ where conn, closing: None, }) - }, + } State::Serving(ref mut srv) => { ready!(srv.poll_server(cx, &mut me.service, &mut me.exec))?; return Poll::Ready(Ok(Dispatched::Shutdown)); @@ -127,12 +126,14 @@ where B: Payload, B::Data: Unpin, { - fn poll_server(&mut self, cx: &mut task::Context<'_>, service: &mut S, exec: &mut E) -> Poll> + fn poll_server( + &mut self, + cx: &mut task::Context<'_>, + service: &mut S, + exec: &mut E, + ) -> Poll> where - S: HttpService< - Body, - ResBody=B, - >, + S: HttpService, S::Error: Into>, E: H2Exec, { @@ -171,25 +172,26 @@ where Some(Ok((req, respond))) => { trace!("incoming request"); let content_length = content_length_parse_all(req.headers()); - let req = req.map(|stream| { - crate::Body::h2(stream, content_length) - }); + let req = req.map(|stream| crate::Body::h2(stream, content_length)); let fut = H2Stream::new(service.call(req), respond); exec.execute_h2stream(fut); - }, + } Some(Err(e)) => { return Poll::Ready(Err(crate::Error::new_h2(e))); - }, + } None => { // no more incoming streams... trace!("incoming connection complete"); return Poll::Ready(Ok(())); - }, + } } } } - debug_assert!(self.closing.is_some(), "poll_server broke loop without closing"); + debug_assert!( + self.closing.is_some(), + "poll_server broke loop without closing" + ); ready!(self.conn.poll_closed(cx).map_err(crate::Error::new_h2))?; @@ -230,7 +232,7 @@ where } macro_rules! reply { - ($me:expr, $res:expr, $eos:expr) => ({ + ($me:expr, $res:expr, $eos:expr) => {{ match $me.reply.send_response($res, $eos) { Ok(tx) => tx, Err(e) => { @@ -239,7 +241,7 @@ macro_rules! reply { return Poll::Ready(Err(crate::Error::new_h2(e))); } } - }) + }}; } impl H2Stream @@ -261,8 +263,10 @@ where Poll::Pending => { // Response is not yet ready, so we want to check if the client has sent a // RST_STREAM frame which would cancel the current request. - if let Poll::Ready(reason) = - me.reply.poll_reset(cx).map_err(|e| crate::Error::new_h2(e))? + if let Poll::Ready(reason) = me + .reply + .poll_reset(cx) + .map_err(|e| crate::Error::new_h2(e))? { debug!("stream received RST_STREAM: {:?}", reason); return Poll::Ready(Err(crate::Error::new_h2(reason.into()))); @@ -274,7 +278,7 @@ where warn!("http2 service errored: {}", err); me.reply.send_reset(err.h2_reason()); return Poll::Ready(Err(err)); - }, + } }; let (head, body) = res.into_parts(); @@ -282,13 +286,10 @@ where super::strip_connection_headers(res.headers_mut(), false); // set Date header if it isn't already set... - res - .headers_mut() + res.headers_mut() .entry(::http::header::DATE) .or_insert_with(crate::proto::h1::date::update_and_header_value); - - // automatically set Content-Length from body... if let Some(len) = body.size_hint().exact() { headers::set_content_length_if_missing(res.headers_mut(), len); @@ -301,7 +302,7 @@ where reply!(me, res, true); return Poll::Ready(Ok(())); } - }, + } H2StreamState::Body(ref mut pipe) => { return Pin::new(pipe).poll(cx); } diff --git a/src/proto/mod.rs b/src/proto/mod.rs index 600d39af97..f95b06cbfc 100644 --- a/src/proto/mod.rs +++ b/src/proto/mod.rs @@ -1,8 +1,8 @@ //! Pieces pertaining to the HTTP message protocol. use http::{HeaderMap, Method, StatusCode, Uri, Version}; -pub(crate) use self::h1::{dispatch, Conn, ServerTransaction}; use self::body_length::DecodedLength; +pub(crate) use self::h1::{dispatch, Conn, ServerTransaction}; pub(crate) mod h1; pub(crate) mod h2; @@ -76,9 +76,8 @@ mod body_length { /// Converts to an Option representing a Known or Unknown length. pub(crate) fn into_opt(self) -> Option { match self { - DecodedLength::CHUNKED | - DecodedLength::CLOSE_DELIMITED => None, - DecodedLength(known) => Some(known) + DecodedLength::CHUNKED | DecodedLength::CLOSE_DELIMITED => None, + DecodedLength(known) => Some(known), } } diff --git a/src/server/accept.rs b/src/server/accept.rs index b78220ceae..e56e3acf84 100644 --- a/src/server/accept.rs +++ b/src/server/accept.rs @@ -9,7 +9,10 @@ #[cfg(feature = "stream")] use futures_core::Stream; -use crate::common::{Pin, task::{self, Poll}}; +use crate::common::{ + task::{self, Poll}, + Pin, +}; /// Asynchronously accept incoming connections. pub trait Accept { @@ -19,8 +22,10 @@ pub trait Accept { type Error; /// Poll to accept the next connection. - fn poll_accept(self: Pin<&mut Self>, cx: &mut task::Context<'_>) - -> Poll>>; + fn poll_accept( + self: Pin<&mut Self>, + cx: &mut task::Context<'_>, + ) -> Poll>>; } /// Create an `Accept` with a polling function. @@ -54,12 +59,11 @@ where { type Conn = IO; type Error = E; - fn poll_accept(self: Pin<&mut Self>, cx: &mut task::Context<'_>) - -> Poll>> - { - unsafe { - (self.get_unchecked_mut().0)(cx) - } + fn poll_accept( + self: Pin<&mut Self>, + cx: &mut task::Context<'_>, + ) -> Poll>> { + unsafe { (self.get_unchecked_mut().0)(cx) } } } @@ -85,13 +89,11 @@ where { type Conn = IO; type Error = E; - fn poll_accept(self: Pin<&mut Self>, cx: &mut task::Context<'_>) - -> Poll>> - { - unsafe { - Pin::new_unchecked(&mut self.get_unchecked_mut().0) - .poll_next(cx) - } + fn poll_accept( + self: Pin<&mut Self>, + cx: &mut task::Context<'_>, + ) -> Poll>> { + unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().0).poll_next(cx) } } } diff --git a/src/server/conn.rs b/src/server/conn.rs index 16eeeccb74..881d69017f 100644 --- a/src/server/conn.rs +++ b/src/server/conn.rs @@ -11,29 +11,31 @@ use std::error::Error as StdError; use std::fmt; use std::mem; -#[cfg(feature = "tcp")] use std::net::SocketAddr; +#[cfg(feature = "tcp")] +use std::net::SocketAddr; use bytes::Bytes; use futures_core::Stream; -use tokio::io::{AsyncRead, AsyncWrite}; use pin_project::{pin_project, project}; +use tokio::io::{AsyncRead, AsyncWrite}; +use super::Accept; use crate::body::{Body, Payload}; use crate::common::exec::{Exec, H2Exec, NewSvcExec}; use crate::common::io::Rewind; -use crate::common::{Future, Pin, Poll, Unpin, task}; +use crate::common::{task, Future, Pin, Poll, Unpin}; use crate::error::{Kind, Parse}; use crate::proto; -use crate::service::{MakeServiceRef, HttpService}; +use crate::service::{HttpService, MakeServiceRef}; use crate::upgrade::Upgraded; -use super::Accept; -pub(super) use self::spawn_all::NoopWatcher; use self::spawn_all::NewSvcTask; +pub(super) use self::spawn_all::NoopWatcher; pub(super) use self::spawn_all::Watcher; pub(super) use self::upgrades::UpgradeableConnection; -#[cfg(feature = "tcp")] pub use super::tcp::{AddrIncoming, AddrStream}; +#[cfg(feature = "tcp")] +pub use super::tcp::{AddrIncoming, AddrStream}; // Our defaults are chosen for the "majority" case, which usually are not // resource contrained, and so the spec default of 64kb can be too limiting @@ -161,7 +163,7 @@ impl Unpin for Fallback {} /// This allows taking apart a `Connection` at a later time, in order to /// reclaim the IO object, and additional related pieces. #[derive(Debug)] -pub struct Parts { +pub struct Parts { /// The original IO object used in the handshake. pub io: T, /// A buffer of bytes that have been read but not processed as HTTP. @@ -274,7 +276,10 @@ impl Http { /// Passing `None` will do nothing. /// /// If not set, hyper will use a default. - pub fn http2_initial_connection_window_size(&mut self, sz: impl Into>) -> &mut Self { + pub fn http2_initial_connection_window_size( + &mut self, + sz: impl Into>, + ) -> &mut Self { if let Some(sz) = sz.into() { self.h2_builder.initial_connection_window_size(sz); } @@ -374,7 +379,7 @@ impl Http { /// ``` pub fn serve_connection(&self, io: I, service: S) -> Connection where - S: HttpService, + S: HttpService, S::Error: Into>, Bd: Payload, Bd::Data: Unpin, @@ -402,7 +407,8 @@ impl Http { } ConnectionMode::H2Only => { let rewind_io = Rewind::new(io); - let h2 = proto::h2::Server::new(rewind_io, service, &self.h2_builder, self.exec.clone()); + let h2 = + proto::h2::Server::new(rewind_io, service, &self.h2_builder, self.exec.clone()); ProtoServer::H2(h2) } }; @@ -419,14 +425,10 @@ impl Http { pub(super) fn serve(&self, incoming: I, make_service: S) -> Serve where - I: Accept, + I: Accept, IE: Into>, IO: AsyncRead + AsyncWrite + Unpin, - S: MakeServiceRef< - IO, - Body, - ResBody=Bd, - >, + S: MakeServiceRef, S::Error: Into>, Bd: Payload, E: H2Exec<>::Future, Bd>, @@ -439,12 +441,11 @@ impl Http { } } - // ===== impl Connection ===== impl Connection where - S: HttpService, + S: HttpService, S::Error: Into>, I: AsyncRead + AsyncWrite + Unpin, B: Payload + 'static, @@ -459,7 +460,7 @@ where match self.project().conn.as_mut().unwrap() { ProtoServer::H1(ref mut h1) => { h1.disable_keep_alive(); - }, + } ProtoServer::H2(ref mut h2) => { h2.graceful_shutdown(); } @@ -476,7 +477,8 @@ where /// # Panics /// This method will panic if this connection is using an h2 protocol. pub fn into_parts(self) -> Parts { - self.try_into_parts().unwrap_or_else(|| panic!("h2 cannot into_inner")) + self.try_into_parts() + .unwrap_or_else(|| panic!("h2 cannot into_inner")) } /// Return the inner IO object, and additional information, if available. @@ -492,7 +494,7 @@ where service: dispatch.into_service(), _inner: (), }) - }, + } ProtoServer::H2(_h2) => None, } } @@ -521,22 +523,20 @@ where }; match ready!(polled) { Ok(x) => return Poll::Ready(Ok(x)), - Err(e) => { - match *e.kind() { - Kind::Parse(Parse::VersionH2) if self.fallback.to_h2() => { - self.upgrade_h2(); - continue; - } - _ => return Poll::Ready(Err(e)), + Err(e) => match *e.kind() { + Kind::Parse(Parse::VersionH2) if self.fallback.to_h2() => { + self.upgrade_h2(); + continue; } - } + _ => return Poll::Ready(Err(e)), + }, } } } /// Prevent shutdown of the underlying IO object at the end of service the request, /// instead run `into_parts`. This is a convenience wrapper over `poll_without_shutdown`. - pub fn without_shutdown(self) -> impl Future>> + pub fn without_shutdown(self) -> impl Future>> where S: Unpin, S::Future: Unpin, @@ -554,9 +554,7 @@ where let conn = self.conn.take(); let (io, read_buf, dispatch) = match conn.unwrap() { - ProtoServer::H1(h1) => { - h1.into_inner() - }, + ProtoServer::H1(h1) => h1.into_inner(), ProtoServer::H2(_h2) => { panic!("h2 cannot into_inner"); } @@ -567,12 +565,7 @@ where Fallback::ToHttp2(ref builder, ref exec) => (builder, exec), Fallback::Http1Only => unreachable!("upgrade_h2 with Fallback::Http1Only"), }; - let h2 = proto::h2::Server::new( - rewind_io, - dispatch.into_service(), - builder, - exec.clone(), - ); + let h2 = proto::h2::Server::new(rewind_io, dispatch.into_service(), builder, exec.clone()); debug_assert!(self.conn.is_none()); self.conn = Some(ProtoServer::H2(h2)); @@ -585,15 +578,13 @@ where where I: Send, { - UpgradeableConnection { - inner: self, - } + UpgradeableConnection { inner: self } } } impl Future for Connection where - S: HttpService, + S: HttpService, S::Error: Into>, I: AsyncRead + AsyncWrite + Unpin + 'static, B: Payload + 'static, @@ -614,16 +605,14 @@ where pending.manual(); } return Poll::Ready(Ok(())); - }, - Err(e) => { - match *e.kind() { - Kind::Parse(Parse::VersionH2) if self.fallback.to_h2() => { - self.upgrade_h2(); - continue; - } - _ => return Poll::Ready(Err(e)), - } } + Err(e) => match *e.kind() { + Kind::Parse(Parse::VersionH2) if self.fallback.to_h2() => { + self.upgrade_h2(); + continue; + } + _ => return Poll::Ready(Err(e)), + }, } } } @@ -634,8 +623,7 @@ where S: HttpService, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Connection") - .finish() + f.debug_struct("Connection").finish() } } // ===== impl Serve ===== @@ -655,25 +643,23 @@ impl Serve { /// Spawn all incoming connections onto the executor in `Http`. pub(super) fn spawn_all(self) -> SpawnAll { - SpawnAll { - serve: self, - } + SpawnAll { serve: self } } } - - - impl Serve where - I: Accept, + I: Accept, IO: AsyncRead + AsyncWrite + Unpin, IE: Into>, - S: MakeServiceRef, + S: MakeServiceRef, B: Payload, E: H2Exec<>::Future, B>, { - fn poll_next_(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll>>> { + fn poll_next_( + self: Pin<&mut Self>, + cx: &mut task::Context<'_>, + ) -> Poll>>> { let me = self.project(); match ready!(me.make_service.poll_ready_ref(cx)) { Ok(()) => (), @@ -700,10 +686,10 @@ where // deprecated impl Stream for Serve where - I: Accept, + I: Accept, IO: AsyncRead + AsyncWrite + Unpin, IE: Into>, - S: MakeServiceRef, + S: MakeServiceRef, B: Payload, E: H2Exec<>::Future, B>, { @@ -716,12 +702,11 @@ where // ===== impl Connecting ===== - impl Future for Connecting where I: AsyncRead + AsyncWrite + Unpin, - F: Future>, - S: HttpService, + F: Future>, + S: HttpService, B: Payload, B::Data: Unpin, E: H2Exec, @@ -753,18 +738,18 @@ impl SpawnAll { impl SpawnAll where - I: Accept, + I: Accept, IE: Into>, IO: AsyncRead + AsyncWrite + Unpin + Send + 'static, - S: MakeServiceRef< - IO, - Body, - ResBody=B, - >, + S: MakeServiceRef, B: Payload, E: H2Exec<>::Future, B>, { - pub(super) fn poll_watch(self: Pin<&mut Self>, cx: &mut task::Context<'_>, watcher: &W) -> Poll> + pub(super) fn poll_watch( + self: Pin<&mut Self>, + cx: &mut task::Context<'_>, + watcher: &W, + ) -> Poll> where E: NewSvcExec, W: Watcher, @@ -773,7 +758,12 @@ where loop { if let Some(connecting) = ready!(me.serve.as_mut().poll_next_(cx)?) { let fut = NewSvcTask::new(connecting, watcher.clone()); - me.serve.as_mut().project().protocol.exec.execute_new_svc(fut); + me.serve + .as_mut() + .project() + .protocol + .exec + .execute_new_svc(fut); } else { return Poll::Ready(Ok(())); } @@ -808,11 +798,11 @@ pub(crate) mod spawn_all { use std::error::Error as StdError; use tokio::io::{AsyncRead, AsyncWrite}; + use super::{Connecting, UpgradeableConnection}; use crate::body::{Body, Payload}; use crate::common::exec::H2Exec; - use crate::common::{Future, Pin, Poll, Unpin, task}; + use crate::common::{task, Future, Pin, Poll, Unpin}; use crate::service::HttpService; - use super::{Connecting, UpgradeableConnection}; use pin_project::{pin_project, project}; // Used by `SpawnAll` to optionally watch a `Connection` future. @@ -881,9 +871,9 @@ pub(crate) mod spawn_all { impl Future for NewSvcTask where I: AsyncRead + AsyncWrite + Unpin + Send + 'static, - N: Future>, + N: Future>, NE: Into>, - S: HttpService, + S: HttpService, B: Payload, B::Data: Unpin, E: H2Exec, @@ -914,15 +904,13 @@ pub(crate) mod spawn_all { }; let connected = watcher.watch(conn.with_upgrades()); State::Connected(connected) - }, + } State::Connected(future) => { - return future - .poll(cx) - .map(|res| { - if let Err(err) = res { - debug!("connection error: {}", err); - } - }); + return future.poll(cx).map(|res| { + if let Err(err) = res { + debug!("connection error: {}", err); + } + }); } } }; @@ -951,7 +939,7 @@ mod upgrades { impl UpgradeableConnection where - S: HttpService, + S: HttpService, S::Error: Into>, I: AsyncRead + AsyncWrite + Unpin, B: Payload + 'static, @@ -969,7 +957,7 @@ mod upgrades { impl Future for UpgradeableConnection where - S: HttpService, + S: HttpService, S::Error: Into>, I: AsyncRead + AsyncWrite + Unpin + Send + 'static, B: Payload + 'static, @@ -991,19 +979,16 @@ mod upgrades { let (io, buf, _) = h1.into_inner(); pending.fulfill(Upgraded::new(Box::new(io), buf)); return Poll::Ready(Ok(())); - }, - Err(e) => { - match *e.kind() { - Kind::Parse(Parse::VersionH2) if self.inner.fallback.to_h2() => { - self.inner.upgrade_h2(); - continue; - } - _ => return Poll::Ready(Err(e)), - } } + Err(e) => match *e.kind() { + Kind::Parse(Parse::VersionH2) if self.inner.fallback.to_h2() => { + self.inner.upgrade_h2(); + continue; + } + _ => return Poll::Ready(Err(e)), + }, } } } } } - diff --git a/src/server/mod.rs b/src/server/mod.rs index 3d525b3206..c28dcfd9bd 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -51,27 +51,31 @@ pub mod accept; pub mod conn; mod shutdown; -#[cfg(feature = "tcp")] mod tcp; +#[cfg(feature = "tcp")] +mod tcp; use std::error::Error as StdError; use std::fmt; -#[cfg(feature = "tcp")] use std::net::{SocketAddr, TcpListener as StdTcpListener}; +#[cfg(feature = "tcp")] +use std::net::{SocketAddr, TcpListener as StdTcpListener}; -#[cfg(feature = "tcp")] use std::time::Duration; +#[cfg(feature = "tcp")] +use std::time::Duration; -use tokio::io::{AsyncRead, AsyncWrite}; use pin_project::pin_project; +use tokio::io::{AsyncRead, AsyncWrite}; +use self::accept::Accept; use crate::body::{Body, Payload}; use crate::common::exec::{Exec, H2Exec, NewSvcExec}; -use crate::common::{Future, Pin, Poll, Unpin, task}; -use crate::service::{MakeServiceRef, HttpService}; -use self::accept::Accept; +use crate::common::{task, Future, Pin, Poll, Unpin}; +use crate::service::{HttpService, MakeServiceRef}; // Renamed `Http` as `Http_` for now so that people upgrading don't see an // error that `hyper::server::Http` is private... use self::conn::{Http as Http_, NoopWatcher, SpawnAll}; use self::shutdown::{Graceful, GracefulWatcher}; -#[cfg(feature = "tcp")] use self::tcp::AddrIncoming; +#[cfg(feature = "tcp")] +use self::tcp::AddrIncoming; /// A listening HTTP server that accepts connections in both HTTP1 and HTTP2 by default. /// @@ -113,23 +117,20 @@ impl Server { /// This method will panic if binding to the address fails. For a method /// to bind to an address and return a `Result`, see `Server::try_bind`. pub fn bind(addr: &SocketAddr) -> Builder { - let incoming = AddrIncoming::new(addr) - .unwrap_or_else(|e| { - panic!("error binding to {}: {}", addr, e); - }); + let incoming = AddrIncoming::new(addr).unwrap_or_else(|e| { + panic!("error binding to {}: {}", addr, e); + }); Server::builder(incoming) } /// Tries to bind to the provided address, and returns a [`Builder`](Builder). pub fn try_bind(addr: &SocketAddr) -> crate::Result> { - AddrIncoming::new(addr) - .map(Server::builder) + AddrIncoming::new(addr).map(Server::builder) } /// Create a new instance from a `std::net::TcpListener` instance. pub fn from_tcp(listener: StdTcpListener) -> Result, crate::Error> { - AddrIncoming::from_std(listener) - .map(Server::builder) + AddrIncoming::from_std(listener).map(Server::builder) } } @@ -143,10 +144,10 @@ impl Server { impl Server where - I: Accept, + I: Accept, IE: Into>, IO: AsyncRead + AsyncWrite + Unpin + Send + 'static, - S: MakeServiceRef, + S: MakeServiceRef, S::Error: Into>, B: Payload, B::Data: Unpin, @@ -191,7 +192,7 @@ where /// ``` pub fn with_graceful_shutdown(self, signal: F) -> Graceful where - F: Future + F: Future, { Graceful::new(self.spawn_all, signal) } @@ -199,10 +200,10 @@ where impl Future for Server where - I: Accept, + I: Accept, IE: Into>, IO: AsyncRead + AsyncWrite + Unpin + Send + 'static, - S: MakeServiceRef, + S: MakeServiceRef, S::Error: Into>, B: Payload, B::Data: Unpin, @@ -231,10 +232,7 @@ impl Builder { /// /// For a more convenient constructor, see [`Server::bind`](Server::bind). pub fn new(incoming: I, protocol: Http_) -> Self { - Builder { - incoming, - protocol, - } + Builder { incoming, protocol } } /// Sets whether to use keep-alive for HTTP/1 connections. @@ -245,7 +243,6 @@ impl Builder { self } - /// Set whether HTTP/1 connections should support half-closures. /// /// Clients can chose to shutdown their write-side while waiting @@ -319,7 +316,8 @@ impl Builder { /// /// If not set, hyper will use a default. pub fn http2_initial_connection_window_size(mut self, sz: impl Into>) -> Self { - self.protocol.http2_initial_connection_window_size(sz.into()); + self.protocol + .http2_initial_connection_window_size(sz.into()); self } @@ -387,7 +385,7 @@ impl Builder { I: Accept, I::Error: Into>, I::Conn: AsyncRead + AsyncWrite + Unpin + Send + 'static, - S: MakeServiceRef, + S: MakeServiceRef, S::Error: Into>, B: Payload, B::Data: Unpin, @@ -396,9 +394,7 @@ impl Builder { { let serve = self.protocol.serve(self.incoming, new_service); let spawn_all = serve.spawn_all(); - Server { - spawn_all, - } + Server { spawn_all } } } @@ -440,4 +436,3 @@ impl Builder { self } } - diff --git a/src/server/shutdown.rs b/src/server/shutdown.rs index e470af5c24..67d2901122 100644 --- a/src/server/shutdown.rs +++ b/src/server/shutdown.rs @@ -1,15 +1,15 @@ use std::error::Error as StdError; -use tokio::io::{AsyncRead, AsyncWrite}; use pin_project::{pin_project, project}; +use tokio::io::{AsyncRead, AsyncWrite}; +use super::conn::{SpawnAll, UpgradeableConnection, Watcher}; +use super::Accept; use crate::body::{Body, Payload}; use crate::common::drain::{self, Draining, Signal, Watch, Watching}; use crate::common::exec::{H2Exec, NewSvcExec}; -use crate::common::{Future, Pin, Poll, Unpin, task}; -use crate::service::{MakeServiceRef, HttpService}; -use super::Accept; -use super::conn::{SpawnAll, UpgradeableConnection, Watcher}; +use crate::common::{task, Future, Pin, Poll, Unpin}; +use crate::service::{HttpService, MakeServiceRef}; #[allow(missing_debug_implementations)] #[pin_project] @@ -43,17 +43,16 @@ impl Graceful { } } - impl Future for Graceful where - I: Accept, + I: Accept, IE: Into>, IO: AsyncRead + AsyncWrite + Unpin + Send + 'static, - S: MakeServiceRef, + S: MakeServiceRef, S::Error: Into>, B: Payload, B::Data: Unpin, - F: Future, + F: Future, E: H2Exec<>::Future, B>, E: NewSvcExec, { @@ -73,20 +72,13 @@ where } => match signal.poll(cx) { Poll::Ready(()) => { debug!("signal received, starting graceful shutdown"); - let sig = drain - .take() - .expect("drain channel") - .0; + let sig = drain.take().expect("drain channel").0; State::Draining(sig.drain()) - }, + } Poll::Pending => { - let watch = drain - .as_ref() - .expect("drain channel") - .1 - .clone(); + let watch = drain.as_ref().expect("drain channel").1.clone(); return spawn_all.poll_watch(cx, &GracefulWatcher(watch)); - }, + } }, State::Draining(ref mut draining) => { return Pin::new(draining).poll(cx).map(Ok); @@ -109,13 +101,11 @@ where ::Data: Unpin, E: H2Exec, { - type Future = Watching, fn(Pin<&mut UpgradeableConnection>)>; + type Future = + Watching, fn(Pin<&mut UpgradeableConnection>)>; fn watch(&self, conn: UpgradeableConnection) -> Self::Future { - self - .0 - .clone() - .watch(conn, on_drain) + self.0.clone().watch(conn, on_drain) } } @@ -130,4 +120,3 @@ where { conn.graceful_shutdown() } - diff --git a/src/server/tcp.rs b/src/server/tcp.rs index 3878f8c5fd..2f9bdb94dd 100644 --- a/src/server/tcp.rs +++ b/src/server/tcp.rs @@ -7,10 +7,10 @@ use futures_util::FutureExt as _; use tokio::net::TcpListener; use tokio::time::Delay; -use crate::common::{Future, Pin, Poll, task}; +use crate::common::{task, Future, Pin, Poll}; -use super::Accept; pub use self::addr_stream::AddrStream; +use super::Accept; /// A stream of connections from binding to an address. #[must_use = "streams do nothing unless polled"] @@ -25,15 +25,13 @@ pub struct AddrIncoming { impl AddrIncoming { pub(super) fn new(addr: &SocketAddr) -> crate::Result { - let std_listener = StdTcpListener::bind(addr) - .map_err(crate::Error::new_listen)?; + let std_listener = StdTcpListener::bind(addr).map_err(crate::Error::new_listen)?; AddrIncoming::from_std(std_listener) } pub(super) fn from_std(std_listener: StdTcpListener) -> crate::Result { - let listener = TcpListener::from_std(std_listener) - .map_err(crate::Error::new_listen)?; + let listener = TcpListener::from_std(std_listener).map_err(crate::Error::new_listen)?; let addr = listener.local_addr().map_err(crate::Error::new_listen)?; Ok(AddrIncoming { listener, @@ -115,7 +113,7 @@ impl AddrIncoming { trace!("error trying to set TCP nodelay: {}", e); } return Poll::Ready(Ok(AddrStream::new(socket, addr))); - }, + } Poll::Pending => return Poll::Pending, Poll::Ready(Err(e)) => { // Connection errors can be ignored directly, continue by @@ -134,17 +132,17 @@ impl AddrIncoming { match Pin::new(&mut timeout).poll(cx) { Poll::Ready(()) => { // Wow, it's been a second already? Ok then... - continue - }, + continue; + } Poll::Pending => { self.timeout = Some(timeout); return Poll::Pending; - }, + } } } else { return Poll::Ready(Err(e)); } - }, + } } } } @@ -154,7 +152,10 @@ impl Accept for AddrIncoming { type Conn = AddrStream; type Error = io::Error; - fn poll_accept(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll>> { + fn poll_accept( + mut self: Pin<&mut Self>, + cx: &mut task::Context<'_>, + ) -> Poll>> { let result = ready!(self.poll_next_(cx)); Poll::Ready(Some(result)) } @@ -169,9 +170,9 @@ impl Accept for AddrIncoming { /// and EMFILE. Otherwise, could enter into tight loop. fn is_connection_error(e: &io::Error) -> bool { match e.kind() { - io::ErrorKind::ConnectionRefused | - io::ErrorKind::ConnectionAborted | - io::ErrorKind::ConnectionReset => true, + io::ErrorKind::ConnectionRefused + | io::ErrorKind::ConnectionAborted + | io::ErrorKind::ConnectionReset => true, _ => false, } } @@ -188,14 +189,13 @@ impl fmt::Debug for AddrIncoming { } mod addr_stream { + use bytes::{Buf, BufMut}; use std::io; use std::net::SocketAddr; - use bytes::{Buf, BufMut}; - use tokio::net::TcpStream; use tokio::io::{AsyncRead, AsyncWrite}; + use tokio::net::TcpStream; - use crate::common::{Pin, Poll, task}; - + use crate::common::{task, Pin, Poll}; /// A transport returned yieled by `AddrIncoming`. #[derive(Debug)] @@ -226,29 +226,48 @@ mod addr_stream { } impl AsyncRead for AddrStream { - unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [std::mem::MaybeUninit]) -> bool { + unsafe fn prepare_uninitialized_buffer( + &self, + buf: &mut [std::mem::MaybeUninit], + ) -> bool { self.inner.prepare_uninitialized_buffer(buf) } #[inline] - fn poll_read(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &mut [u8]) -> Poll> { + fn poll_read( + mut self: Pin<&mut Self>, + cx: &mut task::Context<'_>, + buf: &mut [u8], + ) -> Poll> { Pin::new(&mut self.inner).poll_read(cx, buf) } #[inline] - fn poll_read_buf(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &mut B) -> Poll> { + fn poll_read_buf( + mut self: Pin<&mut Self>, + cx: &mut task::Context<'_>, + buf: &mut B, + ) -> Poll> { Pin::new(&mut self.inner).poll_read_buf(cx, buf) } } impl AsyncWrite for AddrStream { #[inline] - fn poll_write(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &[u8]) -> Poll> { + fn poll_write( + mut self: Pin<&mut Self>, + cx: &mut task::Context<'_>, + buf: &[u8], + ) -> Poll> { Pin::new(&mut self.inner).poll_write(cx, buf) } #[inline] - fn poll_write_buf(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &mut B) -> Poll> { + fn poll_write_buf( + mut self: Pin<&mut Self>, + cx: &mut task::Context<'_>, + buf: &mut B, + ) -> Poll> { Pin::new(&mut self.inner).poll_write_buf(cx, buf) } @@ -259,7 +278,10 @@ mod addr_stream { } #[inline] - fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { + fn poll_shutdown( + mut self: Pin<&mut Self>, + cx: &mut task::Context<'_>, + ) -> Poll> { Pin::new(&mut self.inner).poll_shutdown(cx) } } diff --git a/src/service/http.rs b/src/service/http.rs index bb146016c4..9c91f652c8 100644 --- a/src/service/http.rs +++ b/src/service/http.rs @@ -1,7 +1,7 @@ use std::error::Error as StdError; use crate::body::Payload; -use crate::common::{Future, Poll, task}; +use crate::common::{task, Future, Poll}; use crate::{Request, Response}; /// An asynchronous function from `Request` to `Response`. @@ -17,7 +17,7 @@ pub trait HttpService: sealed::Sealed { type Error: Into>; /// The `Future` returned by this `Service`. - type Future: Future, Self::Error>>; + type Future: Future, Self::Error>>; #[doc(hidden)] fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll>; @@ -27,7 +27,7 @@ pub trait HttpService: sealed::Sealed { } impl HttpService for T -where +where T: tower_service::Service, Response = Response>, B2: Payload, T::Error: Into>, @@ -46,13 +46,13 @@ where } } -impl sealed::Sealed for T -where +impl sealed::Sealed for T +where T: tower_service::Service, Response = Response>, B2: Payload, -{} +{ +} mod sealed { pub trait Sealed {} } - diff --git a/src/service/make.rs b/src/service/make.rs index ef8dbebce7..56d30f10b3 100644 --- a/src/service/make.rs +++ b/src/service/make.rs @@ -3,9 +3,9 @@ use std::fmt; use tokio::io::{AsyncRead, AsyncWrite}; -use crate::body::Payload; -use crate::common::{Future, Poll, task}; use super::{HttpService, Service}; +use crate::body::Payload; +use crate::common::{task, Future, Poll}; // The same "trait alias" as tower::MakeConnection, but inlined to reduce // dependencies. @@ -44,13 +44,9 @@ where pub trait MakeServiceRef: self::sealed::Sealed<(Target, ReqBody)> { type ResBody: Payload; type Error: Into>; - type Service: HttpService< - ReqBody, - ResBody=Self::ResBody, - Error=Self::Error, - >; + type Service: HttpService; type MakeError: Into>; - type Future: Future>; + type Future: Future>; // Acting like a #[non_exhaustive] for associated types of this trait. // @@ -70,11 +66,11 @@ pub trait MakeServiceRef: self::sealed::Sealed<(Target, ReqBody impl MakeServiceRef for T where - T: for<'a> Service<&'a Target, Error=ME, Response=S, Future=F>, + T: for<'a> Service<&'a Target, Error = ME, Response = S, Future = F>, E: Into>, ME: Into>, - S: HttpService, - F: Future>, + S: HttpService, + F: Future>, IB: Payload, OB: Payload, { @@ -145,9 +141,7 @@ where F: FnMut(&Target) -> Ret, Ret: Future, { - MakeServiceFn { - f, - } + MakeServiceFn { f } } // Not exported from crate as this will likely be replaced with `impl Service`. @@ -158,7 +152,7 @@ pub struct MakeServiceFn { impl<'t, F, Ret, Target, Svc, MkErr> Service<&'t Target> for MakeServiceFn where F: FnMut(&Target) -> Ret, - Ret: Future>, + Ret: Future>, MkErr: Into>, { type Error = MkErr; @@ -176,8 +170,7 @@ where impl fmt::Debug for MakeServiceFn { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("MakeServiceFn") - .finish() + f.debug_struct("MakeServiceFn").finish() } } diff --git a/src/service/mod.rs b/src/service/mod.rs index 26d21b9188..9c2b0768fd 100644 --- a/src/service/mod.rs +++ b/src/service/mod.rs @@ -41,10 +41,9 @@ mod make; mod oneshot; mod util; -pub(crate) use self::make::{MakeConnection, MakeServiceRef}; pub(crate) use self::http::HttpService; +pub(crate) use self::make::{MakeConnection, MakeServiceRef}; pub(crate) use self::oneshot::{oneshot, Oneshot}; pub use self::make::make_service_fn; pub use self::util::service_fn; - diff --git a/src/service/oneshot.rs b/src/service/oneshot.rs index 1cf4ea5348..94f4b43a80 100644 --- a/src/service/oneshot.rs +++ b/src/service/oneshot.rs @@ -1,11 +1,11 @@ // TODO: Eventually to be replaced with tower_util::Oneshot. -use std::mem; use std::marker::Unpin; +use std::mem; use tower_service::Service; -use crate::common::{Future, Pin, Poll, task}; +use crate::common::{task, Future, Pin, Poll}; pub(crate) fn oneshot(svc: S, req: Req) -> Oneshot where @@ -35,7 +35,8 @@ impl Unpin for Oneshot where S: Service, S::Future: Unpin, -{} +{ +} impl Future for Oneshot where @@ -52,17 +53,17 @@ where State::NotReady(ref mut svc, _) => { ready!(svc.poll_ready(cx))?; // fallthrough out of the match's borrow - }, + } State::Called(ref mut fut) => { return unsafe { Pin::new_unchecked(fut) }.poll(cx); - }, + } State::Tmp => unreachable!(), } match mem::replace(&mut me.state, State::Tmp) { State::NotReady(mut svc, req) => { me.state = State::Called(svc.call(req)); - }, + } _ => unreachable!(), } } diff --git a/src/service/util.rs b/src/service/util.rs index 7c658176da..0860fbade7 100644 --- a/src/service/util.rs +++ b/src/service/util.rs @@ -3,7 +3,7 @@ use std::fmt; use std::marker::PhantomData; use crate::body::Payload; -use crate::common::{Future, Poll, task}; +use crate::common::{task, Future, Poll}; use crate::{Request, Response}; /// Create a `Service` from a function. @@ -41,11 +41,12 @@ pub struct ServiceFn { _req: PhantomData, } -impl tower_service::Service> for ServiceFn +impl tower_service::Service> + for ServiceFn where F: FnMut(Request) -> Ret, ReqBody: Payload, - Ret: Future, E>>, + Ret: Future, E>>, E: Into>, ResBody: Payload, { @@ -64,7 +65,6 @@ where impl fmt::Debug for ServiceFn { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("impl Service") - .finish() + f.debug_struct("impl Service").finish() } } diff --git a/src/upgrade.rs b/src/upgrade.rs index 956586f945..e8377322a0 100644 --- a/src/upgrade.rs +++ b/src/upgrade.rs @@ -11,12 +11,12 @@ use std::fmt; use std::io; use std::marker::Unpin; -use bytes::{/*Buf, BufMut, */Bytes}; +use bytes::Bytes; use tokio::io::{AsyncRead, AsyncWrite}; use tokio::sync::oneshot; use crate::common::io::Rewind; -use crate::common::{Future, Pin, Poll, task}; +use crate::common::{task, Future, Pin, Poll}; /// An upgraded HTTP connection. /// @@ -58,7 +58,7 @@ pub struct Parts { } pub(crate) struct Pending { - tx: oneshot::Sender> + tx: oneshot::Sender>, } /// Error cause returned when an upgrade was expected but canceled @@ -70,14 +70,7 @@ struct UpgradeExpected(()); pub(crate) fn pending() -> (Pending, OnUpgrade) { let (tx, rx) = oneshot::channel(); - ( - Pending { - tx, - }, - OnUpgrade { - rx: Some(rx), - }, - ) + (Pending { tx }, OnUpgrade { rx: Some(rx) }) } pub(crate) trait Io: AsyncRead + AsyncWrite + Unpin + 'static { @@ -130,7 +123,7 @@ impl Upgraded { }), Err(io) => Err(Upgraded { io: Rewind::new_buffered(io, buf), - }) + }), } } } @@ -140,13 +133,21 @@ impl AsyncRead for Upgraded { self.io.prepare_uninitialized_buffer(buf) } - fn poll_read(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &mut [u8]) -> Poll> { + fn poll_read( + mut self: Pin<&mut Self>, + cx: &mut task::Context<'_>, + buf: &mut [u8], + ) -> Poll> { Pin::new(&mut self.io).poll_read(cx, buf) } } impl AsyncWrite for Upgraded { - fn poll_write(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &[u8]) -> Poll> { + fn poll_write( + mut self: Pin<&mut Self>, + cx: &mut task::Context<'_>, + buf: &[u8], + ) -> Poll> { Pin::new(&mut self.io).poll_write(cx, buf) } @@ -161,8 +162,7 @@ impl AsyncWrite for Upgraded { impl fmt::Debug for Upgraded { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Upgraded") - .finish() + f.debug_struct("Upgraded").finish() } } @@ -170,9 +170,7 @@ impl fmt::Debug for Upgraded { impl OnUpgrade { pub(crate) fn none() -> Self { - OnUpgrade { - rx: None, - } + OnUpgrade { rx: None } } pub(crate) fn is_none(&self) -> bool { @@ -188,9 +186,9 @@ impl Future for OnUpgrade { Some(ref mut rx) => Pin::new(rx).poll(cx).map(|res| match res { Ok(Ok(upgraded)) => Ok(upgraded), Ok(Err(err)) => Err(err), - Err(_oneshot_canceled) => Err( - crate::Error::new_canceled().with(UpgradeExpected(())) - ), + Err(_oneshot_canceled) => { + Err(crate::Error::new_canceled().with(UpgradeExpected(()))) + } }), None => Poll::Ready(Err(crate::Error::new_user_no_upgrade())), } @@ -199,8 +197,7 @@ impl Future for OnUpgrade { impl fmt::Debug for OnUpgrade { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("OnUpgrade") - .finish() + f.debug_struct("OnUpgrade").finish() } } @@ -233,4 +230,3 @@ impl StdError for UpgradeExpected { "upgrade expected but not completed" } } - diff --git a/tests/client.rs b/tests/client.rs index 03c0da2e10..16f3dfb501 100644 --- a/tests/client.rs +++ b/tests/client.rs @@ -1,7 +1,8 @@ #![deny(warnings)] #![warn(rust_2018_idioms)] -#[macro_use] extern crate matches; +#[macro_use] +extern crate matches; use std::io::{Read, Write}; use std::net::{SocketAddr, TcpListener}; @@ -12,12 +13,12 @@ use std::time::Duration; use hyper::{Body, Client, Method, Request, StatusCode}; -use futures_core::{Future, Stream, TryFuture}; use futures_channel::oneshot; +use futures_core::{Future, Stream, TryFuture}; use futures_util::future::{self, FutureExt, TryFutureExt}; use futures_util::StreamExt; -use tokio::runtime::Runtime; use tokio::net::TcpStream; +use tokio::runtime::Runtime; fn s(buf: &[u8]) -> &str { ::std::str::from_utf8(buf).expect("from_utf8") @@ -288,25 +289,25 @@ macro_rules! test { } macro_rules! __client_req_prop { - ($req_builder:ident, $body:ident, $addr:ident, headers: $map:tt) => ({ + ($req_builder:ident, $body:ident, $addr:ident, headers: $map:tt) => {{ __client_req_header!($req_builder, $map) - }); + }}; - ($req_builder:ident, $body:ident, $addr:ident, method: $method:ident) => ({ + ($req_builder:ident, $body:ident, $addr:ident, method: $method:ident) => {{ $req_builder = $req_builder.method(Method::$method); - }); + }}; - ($req_builder:ident, $body:ident, $addr:ident, version: $version:ident) => ({ + ($req_builder:ident, $body:ident, $addr:ident, version: $version:ident) => {{ $req_builder = $req_builder.version(hyper::Version::$version); - }); + }}; - ($req_builder:ident, $body:ident, $addr:ident, url: $url:expr) => ({ - $req_builder = $req_builder.uri(format!($url, addr=$addr)); - }); + ($req_builder:ident, $body:ident, $addr:ident, url: $url:expr) => {{ + $req_builder = $req_builder.uri(format!($url, addr = $addr)); + }}; - ($req_builder:ident, $body:ident, $addr:ident, body: $body_e:expr) => ({ + ($req_builder:ident, $body:ident, $addr:ident, body: $body_e:expr) => {{ $body = $body_e.into(); - }); + }}; } macro_rules! __client_req_header { @@ -931,19 +932,19 @@ test! { mod dispatch_impl { use super::*; use std::io::{self, Read, Write}; - use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; + use std::sync::Arc; use std::thread; - use std::time::{Duration}; + use std::time::Duration; - use futures_core::{self, Future}; use futures_channel::{mpsc, oneshot}; + use futures_core::{self, Future}; use futures_util::future::{FutureExt, TryFutureExt}; - use futures_util::stream::{StreamExt}; + use futures_util::stream::StreamExt; use http::Uri; - use tokio::runtime::Runtime; use tokio::io::{AsyncRead, AsyncWrite}; use tokio::net::TcpStream; + use tokio::runtime::Runtime; use hyper::client::connect::{Connected, Connection, HttpConnector}; use hyper::Client; @@ -957,19 +958,27 @@ mod dispatch_impl { let addr = server.local_addr().unwrap(); let mut rt = Runtime::new().unwrap(); let (closes_tx, closes) = mpsc::channel(10); - let client = Client::builder() - .build(DebugConnector::with_http_and_closes(HttpConnector::new(), closes_tx)); + let client = Client::builder().build(DebugConnector::with_http_and_closes( + HttpConnector::new(), + closes_tx, + )); let (tx1, rx1) = oneshot::channel(); thread::spawn(move || { let mut sock = server.accept().unwrap().0; sock.set_read_timeout(Some(Duration::from_secs(5))).unwrap(); - sock.set_write_timeout(Some(Duration::from_secs(5))).unwrap(); + sock.set_write_timeout(Some(Duration::from_secs(5))) + .unwrap(); let mut buf = [0; 4096]; sock.read(&mut buf).expect("read 1"); let body = vec![b'x'; 1024 * 128]; - write!(sock, "HTTP/1.1 200 OK\r\nContent-Length: {}\r\n\r\n", body.len()).expect("write head"); + write!( + sock, + "HTTP/1.1 200 OK\r\nContent-Length: {}\r\n\r\n", + body.len() + ) + .expect("write head"); let _ = sock.write_all(&body); let _ = tx1.send(()); }); @@ -1006,27 +1015,38 @@ mod dispatch_impl { thread::spawn(move || { let mut sock = server.accept().unwrap().0; sock.set_read_timeout(Some(Duration::from_secs(5))).unwrap(); - sock.set_write_timeout(Some(Duration::from_secs(5))).unwrap(); + sock.set_write_timeout(Some(Duration::from_secs(5))) + .unwrap(); let mut buf = [0; 4096]; sock.read(&mut buf).expect("read 1"); - let body =[b'x'; 64]; - write!(sock, "HTTP/1.1 200 OK\r\nContent-Length: {}\r\n\r\n", body.len()).expect("write head"); + let body = [b'x'; 64]; + write!( + sock, + "HTTP/1.1 200 OK\r\nContent-Length: {}\r\n\r\n", + body.len() + ) + .expect("write head"); let _ = sock.write_all(&body); let _ = tx1.send(()); }); let res = { - let client = Client::builder() - .build(DebugConnector::with_http_and_closes(HttpConnector::new(), closes_tx)); + let client = Client::builder().build(DebugConnector::with_http_and_closes( + HttpConnector::new(), + closes_tx, + )); let req = Request::builder() .uri(&*format!("http://{}/a", addr)) .body(Body::empty()) .unwrap(); - client.request(req).and_then(move |res| { - assert_eq!(res.status(), hyper::StatusCode::OK); - concat(res.into_body()) - }).map_ok(|_| ()) + client + .request(req) + .and_then(move |res| { + assert_eq!(res.status(), hyper::StatusCode::OK); + concat(res.into_body()) + }) + .map_ok(|_| ()) }; // client is dropped let rx = rx1.expect("thread panicked"); @@ -1039,7 +1059,6 @@ mod dispatch_impl { rt.block_on(closes.into_future()).0.expect("closes"); } - #[tokio::test] async fn drop_client_closes_idle_connections() { use futures_util::future; @@ -1056,21 +1075,31 @@ mod dispatch_impl { thread::spawn(move || { let mut sock = server.accept().unwrap().0; sock.set_read_timeout(Some(Duration::from_secs(5))).unwrap(); - sock.set_write_timeout(Some(Duration::from_secs(5))).unwrap(); + sock.set_write_timeout(Some(Duration::from_secs(5))) + .unwrap(); let mut buf = [0; 4096]; sock.read(&mut buf).expect("read 1"); let body = [b'x'; 64]; - write!(sock, "HTTP/1.1 200 OK\r\nContent-Length: {}\r\n\r\n", body.len()).expect("write head"); + write!( + sock, + "HTTP/1.1 200 OK\r\nContent-Length: {}\r\n\r\n", + body.len() + ) + .expect("write head"); let _ = sock.write_all(&body); let _ = tx1.send(()); // prevent this thread from closing until end of test, so the connection // stays open and idle until Client is dropped - Runtime::new().unwrap().block_on(client_drop_rx.into_future()) + Runtime::new() + .unwrap() + .block_on(client_drop_rx.into_future()) }); - let client = Client::builder() - .build(DebugConnector::with_http_and_closes(HttpConnector::new(), closes_tx)); + let client = Client::builder().build(DebugConnector::with_http_and_closes( + HttpConnector::new(), + closes_tx, + )); let req = Request::builder() .uri(&*format!("http://{}/a", addr)) @@ -1089,17 +1118,15 @@ mod dispatch_impl { future::poll_fn(|ctx| { assert!(Pin::new(&mut closes).poll_next(ctx).is_pending()); Poll::Ready(()) - }).await; + }) + .await; // drop to start the connections closing drop(client); // and wait a few ticks for the connections to close - let t = tokio::time::delay_for(Duration::from_millis(100)) - .map(|_| panic!("time out")); - let close = closes - .into_future() - .map(|(opt, _)| opt.expect("closes")); + let t = tokio::time::delay_for(Duration::from_millis(100)).map(|_| panic!("time out")); + let close = closes.into_future().map(|(opt, _)| opt.expect("closes")); future::select(t, close).await; } @@ -1117,7 +1144,8 @@ mod dispatch_impl { thread::spawn(move || { let mut sock = server.accept().unwrap().0; sock.set_read_timeout(Some(Duration::from_secs(5))).unwrap(); - sock.set_write_timeout(Some(Duration::from_secs(5))).unwrap(); + sock.set_write_timeout(Some(Duration::from_secs(5))) + .unwrap(); let mut buf = [0; 4096]; sock.read(&mut buf).expect("read 1"); // we never write a response head @@ -1130,26 +1158,23 @@ mod dispatch_impl { }); let res = { - let client = Client::builder() - .build(DebugConnector::with_http_and_closes(HttpConnector::new(), closes_tx)); + let client = Client::builder().build(DebugConnector::with_http_and_closes( + HttpConnector::new(), + closes_tx, + )); let req = Request::builder() .uri(&*format!("http://{}/a", addr)) .body(Body::empty()) .unwrap(); - client - .request(req) - .map(|_| unreachable!()) + client.request(req).map(|_| unreachable!()) }; future::select(res, rx1).await; // res now dropped - let t = tokio::time::delay_for(Duration::from_millis(100)) - .map(|_| panic!("time out")); - let close = closes - .into_future() - .map(|(opt, _)| opt.expect("closes")); + let t = tokio::time::delay_for(Duration::from_millis(100)).map(|_| panic!("time out")); + let close = closes.into_future().map(|(opt, _)| opt.expect("closes")); future::select(t, close).await; } @@ -1167,10 +1192,15 @@ mod dispatch_impl { thread::spawn(move || { let mut sock = server.accept().unwrap().0; sock.set_read_timeout(Some(Duration::from_secs(5))).unwrap(); - sock.set_write_timeout(Some(Duration::from_secs(5))).unwrap(); + sock.set_write_timeout(Some(Duration::from_secs(5))) + .unwrap(); let mut buf = [0; 4096]; sock.read(&mut buf).expect("read 1"); - write!(sock, "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n").expect("write head"); + write!( + sock, + "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n" + ) + .expect("write head"); let _ = tx1.send(()); // prevent this thread from closing until end of test, so the connection @@ -1180,8 +1210,10 @@ mod dispatch_impl { let rx = rx1.expect("thread panicked"); let res = { - let client = Client::builder() - .build(DebugConnector::with_http_and_closes(HttpConnector::new(), closes_tx)); + let client = Client::builder().build(DebugConnector::with_http_and_closes( + HttpConnector::new(), + closes_tx, + )); let req = Request::builder() .uri(&*format!("http://{}/a", addr)) @@ -1191,17 +1223,13 @@ mod dispatch_impl { client.request(req) }; - let (res, ()) = future::join(res, rx).await; // drop the body res.unwrap(); // and wait a few ticks to see the connection drop - let t = tokio::time::delay_for(Duration::from_millis(100)) - .map(|_| panic!("time out")); - let close = closes - .into_future() - .map(|(opt, _)| opt.expect("closes")); + let t = tokio::time::delay_for(Duration::from_millis(100)).map(|_| panic!("time out")); + let close = closes.into_future().map(|(opt, _)| opt.expect("closes")); future::select(t, close).await; } @@ -1220,10 +1248,12 @@ mod dispatch_impl { thread::spawn(move || { let mut sock = server.accept().unwrap().0; sock.set_read_timeout(Some(Duration::from_secs(5))).unwrap(); - sock.set_write_timeout(Some(Duration::from_secs(5))).unwrap(); + sock.set_write_timeout(Some(Duration::from_secs(5))) + .unwrap(); let mut buf = [0; 4096]; sock.read(&mut buf).expect("read 1"); - sock.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n").unwrap(); + sock.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n") + .unwrap(); let _ = tx1.send(()); // prevent this thread from closing until end of test, so the connection @@ -1231,9 +1261,13 @@ mod dispatch_impl { let _ = rx2.recv(); }); - let client = Client::builder() - .keep_alive(false) - .build(DebugConnector::with_http_and_closes(HttpConnector::new(), closes_tx)); + let client = + Client::builder() + .keep_alive(false) + .build(DebugConnector::with_http_and_closes( + HttpConnector::new(), + closes_tx, + )); let req = Request::builder() .uri(&*format!("http://{}/a", addr)) @@ -1248,11 +1282,8 @@ mod dispatch_impl { let (res, ()) = future::join(res, rx).await; res.unwrap(); - let t = tokio::time::delay_for(Duration::from_millis(100)) - .map(|_| panic!("time out")); - let close = closes - .into_future() - .map(|(opt, _)| opt.expect("closes")); + let t = tokio::time::delay_for(Duration::from_millis(100)).map(|_| panic!("time out")); + let close = closes.into_future().map(|(opt, _)| opt.expect("closes")); future::select(t, close).await; } @@ -1270,15 +1301,19 @@ mod dispatch_impl { thread::spawn(move || { let mut sock = server.accept().unwrap().0; sock.set_read_timeout(Some(Duration::from_secs(5))).unwrap(); - sock.set_write_timeout(Some(Duration::from_secs(5))).unwrap(); + sock.set_write_timeout(Some(Duration::from_secs(5))) + .unwrap(); let mut buf = [0; 4096]; sock.read(&mut buf).expect("read 1"); - sock.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n").unwrap(); + sock.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n") + .unwrap(); let _ = tx1.send(()); }); - let client = Client::builder() - .build(DebugConnector::with_http_and_closes(HttpConnector::new(), closes_tx)); + let client = Client::builder().build(DebugConnector::with_http_and_closes( + HttpConnector::new(), + closes_tx, + )); let req = Request::builder() .uri(&*format!("http://{}/a", addr)) @@ -1293,11 +1328,8 @@ mod dispatch_impl { let (res, ()) = future::join(res, rx).await; res.unwrap(); - let t = tokio::time::delay_for(Duration::from_millis(100)) - .map(|_| panic!("time out")); - let close = closes - .into_future() - .map(|(opt, _)| opt.expect("closes")); + let t = tokio::time::delay_for(Duration::from_millis(100)).map(|_| panic!("time out")); + let close = closes.into_future().map(|(opt, _)| opt.expect("closes")); future::select(t, close).await; } @@ -1311,8 +1343,7 @@ mod dispatch_impl { let connector = DebugConnector::new(); let connects = connector.connects.clone(); - let client = Client::builder() - .build(connector); + let client = Client::builder().build(connector); assert_eq!(connects.load(Ordering::Relaxed), 0); let req = Request::builder() @@ -1334,8 +1365,7 @@ mod dispatch_impl { let connector = DebugConnector::new(); let connects = connector.connects.clone(); - let client = Client::builder() - .build(connector); + let client = Client::builder().build(connector); let (tx1, rx1) = oneshot::channel(); let (tx2, rx2) = oneshot::channel(); @@ -1343,21 +1373,23 @@ mod dispatch_impl { let mut sock = server.accept().unwrap().0; //drop(server); sock.set_read_timeout(Some(Duration::from_secs(5))).unwrap(); - sock.set_write_timeout(Some(Duration::from_secs(5))).unwrap(); + sock.set_write_timeout(Some(Duration::from_secs(5))) + .unwrap(); let mut buf = [0; 4096]; sock.read(&mut buf).expect("read 1"); - sock.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n").expect("write 1"); + sock.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n") + .expect("write 1"); let _ = tx1.send(()); let n2 = sock.read(&mut buf).expect("read 2"); assert_ne!(n2, 0); let second_get = "GET /b HTTP/1.1\r\n"; assert_eq!(s(&buf[..second_get.len()]), second_get); - sock.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n").expect("write 2"); + sock.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n") + .expect("write 2"); let _ = tx2.send(()); }); - assert_eq!(connects.load(Ordering::SeqCst), 0); let rx = rx1.expect("thread panicked"); @@ -1382,7 +1414,11 @@ mod dispatch_impl { let res = client.request(req); rt.block_on(future::join(res, rx).map(|r| r.0)).unwrap(); - assert_eq!(connects.load(Ordering::SeqCst), 1, "second request should still only have 1 connect"); + assert_eq!( + connects.load(Ordering::SeqCst), + 1, + "second request should still only have 1 connect" + ); drop(client); } @@ -1396,18 +1432,19 @@ mod dispatch_impl { let connector = DebugConnector::new(); let connects = connector.connects.clone(); - let client = Client::builder() - .build(connector); + let client = Client::builder().build(connector); let (tx1, rx1) = oneshot::channel(); let (tx2, rx2) = oneshot::channel(); thread::spawn(move || { let mut sock = server.accept().unwrap().0; sock.set_read_timeout(Some(Duration::from_secs(5))).unwrap(); - sock.set_write_timeout(Some(Duration::from_secs(5))).unwrap(); + sock.set_write_timeout(Some(Duration::from_secs(5))) + .unwrap(); let mut buf = [0; 4096]; sock.read(&mut buf).expect("read 1"); - sock.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nhello").expect("write 1"); + sock.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nhello") + .expect("write 1"); // the body "hello", while ignored because its a HEAD request, should mean the connection // cannot be put back in the pool let _ = tx1.send(()); @@ -1417,11 +1454,12 @@ mod dispatch_impl { assert_ne!(n2, 0); let second_get = "GET /b HTTP/1.1\r\n"; assert_eq!(s(&buf[..second_get.len()]), second_get); - sock2.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n").expect("write 2"); + sock2 + .write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n") + .expect("write 2"); let _ = tx2.send(()); }); - assert_eq!(connects.load(Ordering::Relaxed), 0); let rx = rx1.expect("thread panicked"); @@ -1448,7 +1486,6 @@ mod dispatch_impl { #[test] fn client_keep_alive_when_response_before_request_body_ends() { - let _ = pretty_env_logger::try_init(); let server = TcpListener::bind("127.0.0.1:0").unwrap(); let addr = server.local_addr().unwrap(); @@ -1457,8 +1494,7 @@ mod dispatch_impl { let connector = DebugConnector::new(); let connects = connector.connects.clone(); - let client = Client::builder() - .build(connector); + let client = Client::builder().build(connector); let (tx1, rx1) = oneshot::channel(); let (tx2, rx2) = oneshot::channel(); @@ -1466,10 +1502,12 @@ mod dispatch_impl { thread::spawn(move || { let mut sock = server.accept().unwrap().0; sock.set_read_timeout(Some(Duration::from_secs(5))).unwrap(); - sock.set_write_timeout(Some(Duration::from_secs(5))).unwrap(); + sock.set_write_timeout(Some(Duration::from_secs(5))) + .unwrap(); let mut buf = [0; 4096]; sock.read(&mut buf).expect("read 1"); - sock.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n").expect("write 1"); + sock.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n") + .expect("write 1"); // after writing the response, THEN stream the body let _ = tx1.send(()); @@ -1480,11 +1518,11 @@ mod dispatch_impl { assert_ne!(n2, 0); let second_get = "GET /b HTTP/1.1\r\n"; assert_eq!(s(&buf[..second_get.len()]), second_get); - sock.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n").expect("write 2"); + sock.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n") + .expect("write 2"); let _ = tx3.send(()); }); - assert_eq!(connects.load(Ordering::Relaxed), 0); let delayed_body = rx1 @@ -1511,8 +1549,7 @@ mod dispatch_impl { .uri(&*format!("http://{}/b", addr)) .body(Body::empty()) .unwrap(); - future::join(client2.request(req), rx) - .map(|r| r.0) + future::join(client2.request(req), rx).map(|r| r.0) }); rt.block_on(fut).unwrap(); @@ -1526,28 +1563,30 @@ mod dispatch_impl { let server = TcpListener::bind("127.0.0.1:0").unwrap(); let addr = server.local_addr().unwrap(); let mut rt = Runtime::new().unwrap(); - let connector = DebugConnector::new() - .proxy(); + let connector = DebugConnector::new().proxy(); - let client = Client::builder() - .build(connector); + let client = Client::builder().build(connector); let (tx1, rx1) = oneshot::channel(); thread::spawn(move || { let mut sock = server.accept().unwrap().0; //drop(server); sock.set_read_timeout(Some(Duration::from_secs(5))).unwrap(); - sock.set_write_timeout(Some(Duration::from_secs(5))).unwrap(); + sock.set_write_timeout(Some(Duration::from_secs(5))) + .unwrap(); let mut buf = [0; 4096]; let n = sock.read(&mut buf).expect("read 1"); - let expected = format!("GET http://{addr}/foo/bar HTTP/1.1\r\nhost: {addr}\r\n\r\n", addr=addr); + let expected = format!( + "GET http://{addr}/foo/bar HTTP/1.1\r\nhost: {addr}\r\n\r\n", + addr = addr + ); assert_eq!(s(&buf[..n]), expected); - sock.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n").expect("write 1"); + sock.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n") + .expect("write 1"); let _ = tx1.send(()); }); - let rx = rx1.expect("thread panicked"); let req = Request::builder() .uri(&*format!("http://{}/foo/bar", addr)) @@ -1563,28 +1602,30 @@ mod dispatch_impl { let server = TcpListener::bind("127.0.0.1:0").unwrap(); let addr = server.local_addr().unwrap(); let mut rt = Runtime::new().unwrap(); - let connector = DebugConnector::new() - .proxy(); + let connector = DebugConnector::new().proxy(); - let client = Client::builder() - .build(connector); + let client = Client::builder().build(connector); let (tx1, rx1) = oneshot::channel(); thread::spawn(move || { let mut sock = server.accept().unwrap().0; //drop(server); sock.set_read_timeout(Some(Duration::from_secs(5))).unwrap(); - sock.set_write_timeout(Some(Duration::from_secs(5))).unwrap(); + sock.set_write_timeout(Some(Duration::from_secs(5))) + .unwrap(); let mut buf = [0; 4096]; let n = sock.read(&mut buf).expect("read 1"); - let expected = format!("CONNECT {addr} HTTP/1.1\r\nhost: {addr}\r\n\r\n", addr=addr); + let expected = format!( + "CONNECT {addr} HTTP/1.1\r\nhost: {addr}\r\n\r\n", + addr = addr + ); assert_eq!(s(&buf[..n]), expected); - sock.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n").expect("write 1"); + sock.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n") + .expect("write 1"); let _ = tx1.send(()); }); - let rx = rx1.expect("thread panicked"); let req = Request::builder() .method("CONNECT") @@ -1606,22 +1647,25 @@ mod dispatch_impl { let connector = DebugConnector::new(); - let client = Client::builder() - .build(connector); + let client = Client::builder().build(connector); let (tx1, rx1) = oneshot::channel(); thread::spawn(move || { let mut sock = server.accept().unwrap().0; sock.set_read_timeout(Some(Duration::from_secs(5))).unwrap(); - sock.set_write_timeout(Some(Duration::from_secs(5))).unwrap(); + sock.set_write_timeout(Some(Duration::from_secs(5))) + .unwrap(); let mut buf = [0; 4096]; sock.read(&mut buf).expect("read 1"); - sock.write_all(b"\ + sock.write_all( + b"\ HTTP/1.1 101 Switching Protocols\r\n\ Upgrade: foobar\r\n\ \r\n\ foobar=ready\ - ").unwrap(); + ", + ) + .unwrap(); let _ = tx1.send(()); let n = sock.read(&mut buf).expect("read 2"); @@ -1641,9 +1685,8 @@ mod dispatch_impl { let res = rt.block_on(future::join(res, rx).map(|r| r.0)).unwrap(); assert_eq!(res.status(), 101); - let upgraded = rt.block_on(res - .into_body() - .on_upgrade()) + let upgraded = rt + .block_on(res.into_body().on_upgrade()) .expect("on_upgrade"); let parts = upgraded.downcast::().unwrap(); @@ -1658,37 +1701,45 @@ mod dispatch_impl { #[test] fn alpn_h2() { - use hyper::Response; use hyper::server::conn::Http; use hyper::service::service_fn; + use hyper::Response; use tokio::net::TcpListener; let _ = pretty_env_logger::try_init(); let mut rt = Runtime::new().unwrap(); - let mut listener = rt.block_on(TcpListener::bind(SocketAddr::from(([127, 0, 0, 1], 0)))).unwrap(); + let mut listener = rt + .block_on(TcpListener::bind(SocketAddr::from(([127, 0, 0, 1], 0)))) + .unwrap(); let addr = listener.local_addr().unwrap(); let mut connector = DebugConnector::new(); connector.alpn_h2 = true; let connects = connector.connects.clone(); - let client = Client::builder() - .build::<_, ::hyper::Body>(connector); + let client = Client::builder().build::<_, ::hyper::Body>(connector); rt.spawn(async move { let (socket, _addr) = listener.accept().await.expect("accept"); Http::new() .http2_only(true) - .serve_connection(socket, service_fn(|req| async move { - assert_eq!(req.headers().get("host"), None); - Ok::<_, hyper::Error>(Response::new(Body::empty())) - })) + .serve_connection( + socket, + service_fn(|req| { + async move { + assert_eq!(req.headers().get("host"), None); + Ok::<_, hyper::Error>(Response::new(Body::empty())) + } + }), + ) .await .expect("server"); }); assert_eq!(connects.load(Ordering::SeqCst), 0); - let url = format!("http://{}/a", addr).parse::<::hyper::Uri>().unwrap(); + let url = format!("http://{}/a", addr) + .parse::<::hyper::Uri>() + .unwrap(); let res1 = client.get(url.clone()); let res2 = client.get(url.clone()); let res3 = client.get(url.clone()); @@ -1702,11 +1753,14 @@ mod dispatch_impl { let res4 = client.get(url.clone()); rt.block_on(res4).unwrap(); - assert_eq!(connects.load(Ordering::SeqCst), 3, "after ALPN, no more connects"); + assert_eq!( + connects.load(Ordering::SeqCst), + 3, + "after ALPN, no more connects" + ); drop(client); } - #[derive(Clone)] struct DebugConnector { http: HttpConnector, @@ -1742,9 +1796,7 @@ mod dispatch_impl { impl hyper::service::Service for DebugConnector { type Response = DebugStream; type Error = >::Error; - type Future = Pin - > + Send>>; + type Future = Pin> + Send>>; fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { // don't forget to check inner service is ready :) @@ -1756,13 +1808,11 @@ mod dispatch_impl { let closes = self.closes.clone(); let is_proxy = self.is_proxy; let is_alpn_h2 = self.alpn_h2; - Box::pin(self.http.call(dst).map_ok(move |tcp| { - DebugStream { - tcp, - on_drop: closes, - is_alpn_h2, - is_proxy, - } + Box::pin(self.http.call(dst).map_ok(move |tcp| DebugStream { + tcp, + on_drop: closes, + is_alpn_h2, + is_proxy, })) } } @@ -1781,11 +1831,17 @@ mod dispatch_impl { } impl AsyncWrite for DebugStream { - fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + fn poll_shutdown( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { Pin::new(&mut self.tcp).poll_shutdown(cx) } - fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + fn poll_flush( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { Pin::new(&mut self.tcp).poll_flush(cx) } @@ -1827,24 +1883,26 @@ mod conn { use std::pin::Pin; use std::task::{Context, Poll}; use std::thread; - use std::time::{Duration}; + use std::time::Duration; use futures_channel::oneshot; use futures_util::future::{self, poll_fn, FutureExt, TryFutureExt}; use futures_util::StreamExt; - use tokio::runtime::Runtime; use tokio::io::{AsyncRead, AsyncReadExt as _, AsyncWrite, AsyncWriteExt as _}; use tokio::net::{TcpListener as TkTcpListener, TcpStream}; + use tokio::runtime::Runtime; - use hyper::{self, Request, Body, Method}; use hyper::client::conn; + use hyper::{self, Body, Method, Request}; use super::{concat, s, tcp_connect, FutureHyperExt}; #[tokio::test] async fn get() { let _ = ::pretty_env_logger::try_init(); - let mut listener = TkTcpListener::bind(SocketAddr::from(([127, 0, 0, 1], 0))).await.unwrap(); + let mut listener = TkTcpListener::bind(SocketAddr::from(([127, 0, 0, 1], 0))) + .await + .unwrap(); let addr = listener.local_addr().unwrap(); let server = async move { @@ -1858,7 +1916,9 @@ mod conn { let expected = "GET /a HTTP/1.1\r\n\r\n"; assert_eq!(s(&buf[..n]), expected); - sock.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n").await.unwrap(); + sock.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n") + .await + .unwrap(); }; let client = async move { @@ -1894,14 +1954,16 @@ mod conn { thread::spawn(move || { let mut sock = server.accept().unwrap().0; sock.set_read_timeout(Some(Duration::from_secs(5))).unwrap(); - sock.set_write_timeout(Some(Duration::from_secs(5))).unwrap(); + sock.set_write_timeout(Some(Duration::from_secs(5))) + .unwrap(); let mut buf = [0; 4096]; let n = sock.read(&mut buf).expect("read 1"); let expected = "GET / HTTP/1.1\r\n\r\n"; assert_eq!(s(&buf[..n]), expected); - sock.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nhello").unwrap(); + sock.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nhello") + .unwrap(); let _ = tx1.send(()); }); @@ -1939,7 +2001,8 @@ mod conn { let server = thread::spawn(move || { let mut sock = server.accept().unwrap().0; sock.set_read_timeout(Some(Duration::from_secs(5))).unwrap(); - sock.set_write_timeout(Some(Duration::from_secs(5))).unwrap(); + sock.set_write_timeout(Some(Duration::from_secs(5))) + .unwrap(); let expected = "POST / HTTP/1.1\r\ntransfer-encoding: chunked\r\n\r\n5\r\nhello\r\n"; let mut buf = vec![0; expected.len()]; sock.read_exact(&mut buf).expect("read 1"); @@ -1986,7 +2049,8 @@ mod conn { thread::spawn(move || { let mut sock = server.accept().unwrap().0; sock.set_read_timeout(Some(Duration::from_secs(5))).unwrap(); - sock.set_write_timeout(Some(Duration::from_secs(5))).unwrap(); + sock.set_write_timeout(Some(Duration::from_secs(5))) + .unwrap(); let mut buf = [0; 4096]; let n = sock.read(&mut buf).expect("read 1"); @@ -1995,7 +2059,8 @@ mod conn { let expected = "GET http://hyper.local/a HTTP/1.1\r\n\r\n"; assert_eq!(s(&buf[..n]), expected); - sock.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n").unwrap(); + sock.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n") + .unwrap(); let _ = tx1.send(()); }); @@ -2030,7 +2095,8 @@ mod conn { thread::spawn(move || { let mut sock = server.accept().unwrap().0; sock.set_read_timeout(Some(Duration::from_secs(5))).unwrap(); - sock.set_write_timeout(Some(Duration::from_secs(5))).unwrap(); + sock.set_write_timeout(Some(Duration::from_secs(5))) + .unwrap(); let mut buf = [0; 4096]; let n = sock.read(&mut buf).expect("read 1"); @@ -2038,7 +2104,8 @@ mod conn { let expected = "GET /a HTTP/1.1\r\n\r\n"; assert_eq!(s(&buf[..n]), expected); - sock.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n").unwrap(); + sock.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n") + .unwrap(); let _ = tx1.send(()); }); @@ -2074,10 +2141,12 @@ mod conn { thread::spawn(move || { let mut sock = server.accept().unwrap().0; sock.set_read_timeout(Some(Duration::from_secs(5))).unwrap(); - sock.set_write_timeout(Some(Duration::from_secs(5))).unwrap(); + sock.set_write_timeout(Some(Duration::from_secs(5))) + .unwrap(); let mut buf = [0; 4096]; sock.read(&mut buf).expect("read 1"); - sock.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n").unwrap(); + sock.write_all(b"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n") + .unwrap(); let _ = tx1.send(Ok::<_, ()>(())); }); @@ -2102,17 +2171,16 @@ mod conn { .uri("/b") .body(Default::default()) .unwrap(); - let res2 = client - .send_request(req) - .map(|result| { - let err = result.expect_err("res2"); - assert!(err.is_canceled(), "err not canceled, {:?}", err); - Ok::<_, ()>(()) - }); + let res2 = client.send_request(req).map(|result| { + let err = result.expect_err("res2"); + assert!(err.is_canceled(), "err not canceled, {:?}", err); + Ok::<_, ()>(()) + }); let rx = rx1.expect("thread panicked"); let rx = rx.then(|_| tokio::time::delay_for(Duration::from_millis(200))); - rt.block_on(future::join3(res1, res2, rx).map(|r| r.0)).unwrap(); + rt.block_on(future::join3(res1, res2, rx).map(|r| r.0)) + .unwrap(); } #[test] @@ -2130,15 +2198,19 @@ mod conn { thread::spawn(move || { let mut sock = server.accept().unwrap().0; sock.set_read_timeout(Some(Duration::from_secs(5))).unwrap(); - sock.set_write_timeout(Some(Duration::from_secs(5))).unwrap(); + sock.set_write_timeout(Some(Duration::from_secs(5))) + .unwrap(); let mut buf = [0; 4096]; sock.read(&mut buf).expect("read 1"); - sock.write_all(b"\ + sock.write_all( + b"\ HTTP/1.1 101 Switching Protocols\r\n\ Upgrade: foobar\r\n\ \r\n\ foobar=ready\ - ").unwrap(); + ", + ) + .unwrap(); let _ = tx1.send(()); let n = sock.read(&mut buf).expect("read 2"); @@ -2156,9 +2228,7 @@ mod conn { let (mut client, mut conn) = rt.block_on(conn::handshake(io)).unwrap(); { - let until_upgrade = poll_fn(|ctx| { - conn.poll_without_shutdown(ctx) - }); + let until_upgrade = poll_fn(|ctx| conn.poll_without_shutdown(ctx)); let req = Request::builder() .uri("/a") @@ -2172,13 +2242,15 @@ mod conn { let rx = rx1.expect("thread panicked"); let rx = rx.then(|_| tokio::time::delay_for(Duration::from_millis(200))); - rt.block_on(future::join3(until_upgrade, res, rx).map(|r| r.0)).unwrap(); + rt.block_on(future::join3(until_upgrade, res, rx).map(|r| r.0)) + .unwrap(); // should not be ready now rt.block_on(poll_fn(|ctx| { assert!(client.poll_ready(ctx).is_pending()); Poll::Ready(Ok::<_, ()>(())) - })).unwrap(); + })) + .unwrap(); } let parts = conn.into_parts(); @@ -2191,7 +2263,8 @@ mod conn { let ready = client.poll_ready(ctx); assert_matches!(ready, Poll::Ready(Err(_))); ready - })).unwrap_err(); + })) + .unwrap_err(); let mut vec = vec![]; rt.block_on(io.write_all(b"foo=bar")).unwrap(); @@ -2214,14 +2287,18 @@ mod conn { thread::spawn(move || { let mut sock = server.accept().unwrap().0; sock.set_read_timeout(Some(Duration::from_secs(5))).unwrap(); - sock.set_write_timeout(Some(Duration::from_secs(5))).unwrap(); + sock.set_write_timeout(Some(Duration::from_secs(5))) + .unwrap(); let mut buf = [0; 4096]; sock.read(&mut buf).expect("read 1"); - sock.write_all(b"\ + sock.write_all( + b"\ HTTP/1.1 200 OK\r\n\ \r\n\ foobar=ready\ - ").unwrap(); + ", + ) + .unwrap(); let _ = tx1.send(Ok::<_, ()>(())); let n = sock.read(&mut buf).expect("read 2"); @@ -2239,9 +2316,7 @@ mod conn { let (mut client, mut conn) = rt.block_on(conn::handshake(io)).unwrap(); { - let until_tunneled = poll_fn(|ctx| { - conn.poll_without_shutdown(ctx) - }); + let until_tunneled = poll_fn(|ctx| conn.poll_without_shutdown(ctx)); let req = Request::builder() .method("CONNECT") @@ -2260,13 +2335,15 @@ mod conn { let rx = rx1.expect("thread panicked"); let rx = rx.then(|_| tokio::time::delay_for(Duration::from_millis(200))); - rt.block_on(future::join3(until_tunneled, res, rx).map(|r| r.0)).unwrap(); + rt.block_on(future::join3(until_tunneled, res, rx).map(|r| r.0)) + .unwrap(); // should not be ready now rt.block_on(poll_fn(|ctx| { assert!(client.poll_ready(ctx).is_pending()); Poll::Ready(Ok::<_, ()>(())) - })).unwrap(); + })) + .unwrap(); } let parts = conn.into_parts(); @@ -2280,7 +2357,8 @@ mod conn { let ready = client.poll_ready(ctx); assert_matches!(ready, Poll::Ready(Err(_))); ready - })).unwrap_err(); + })) + .unwrap_err(); let mut vec = vec![]; rt.block_on(io.write_all(b"foo=bar")).unwrap(); @@ -2291,15 +2369,19 @@ mod conn { #[tokio::test] async fn http2_detect_conn_eof() { use futures_util::future; - use hyper::{Response, Server}; use hyper::service::{make_service_fn, service_fn}; + use hyper::{Response, Server}; let _ = pretty_env_logger::try_init(); let server = Server::bind(&([127, 0, 0, 1], 0).into()) .http2_only(true) - .serve(make_service_fn(|_| async move { - Ok::<_, hyper::Error>(service_fn(|_req| future::ok::<_, hyper::Error>(Response::new(Body::empty())))) + .serve(make_service_fn(|_| { + async move { + Ok::<_, hyper::Error>(service_fn(|_req| { + future::ok::<_, hyper::Error>(Response::new(Body::empty())) + })) + } })); let addr = server.local_addr(); let (shdn_tx, shdn_rx) = oneshot::channel(); @@ -2358,12 +2440,18 @@ mod conn { } impl AsyncWrite for DebugStream { - fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + fn poll_shutdown( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { self.shutdown_called = true; Pin::new(&mut self.tcp).poll_shutdown(cx) } - fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + fn poll_flush( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { Pin::new(&mut self.tcp).poll_flush(cx) } @@ -2388,7 +2476,7 @@ mod conn { } trait FutureHyperExt: TryFuture { - fn expect(self, msg: &'static str) -> Pin>>; + fn expect(self, msg: &'static str) -> Pin>>; } impl FutureHyperExt for F @@ -2396,9 +2484,10 @@ where F: TryFuture + 'static, F::Error: ::std::fmt::Debug, { - fn expect(self, msg: &'static str) -> Pin>> { - Box::pin(self - .inspect_err(move |e| panic!("expect: {}; error={:?}", msg, e)) - .map(Result::unwrap)) + fn expect(self, msg: &'static str) -> Pin>> { + Box::pin( + self.inspect_err(move |e| panic!("expect: {}; error={:?}", msg, e)) + .map(Result::unwrap), + ) } } diff --git a/tests/integration.rs b/tests/integration.rs index bc292749b5..2deee443f8 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -337,4 +337,3 @@ t! { http2_parallel_10, parallel: 0..10 } - diff --git a/tests/server.rs b/tests/server.rs index 5652ce4618..a7321864d0 100644 --- a/tests/server.rs +++ b/tests/server.rs @@ -2,13 +2,13 @@ #![deny(rust_2018_idioms)] use std::future::Future; -use std::net::{TcpStream, Shutdown, SocketAddr}; use std::io::{self, Read, Write}; +use std::net::TcpListener as StdTcpListener; +use std::net::{Shutdown, SocketAddr, TcpStream}; +use std::pin::Pin; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::mpsc; use std::sync::{Arc, Mutex}; -use std::net::{TcpListener as StdTcpListener}; -use std::pin::Pin; use std::task::{Context, Poll}; use std::thread; use std::time::Duration; @@ -18,17 +18,16 @@ use futures_util::future::{self, Either, FutureExt, TryFutureExt}; #[cfg(feature = "stream")] use futures_util::stream::StreamExt as _; use http::header::{HeaderName, HeaderValue}; +use tokio::io::{AsyncRead, AsyncWrite}; use tokio::net::{TcpListener, TcpStream as TkTcpStream}; use tokio::runtime::Runtime; -use tokio::io::{AsyncRead, AsyncWrite}; -use hyper::{Body, Request, Response, StatusCode, Version}; use hyper::body::HttpBody as _; use hyper::client::Client; use hyper::server::conn::Http; use hyper::server::Server; use hyper::service::{make_service_fn, service_fn}; - +use hyper::{Body, Request, Response, StatusCode, Version}; #[test] fn get_should_ignore_body() { @@ -36,13 +35,16 @@ fn get_should_ignore_body() { let mut req = connect(server.addr()); // Connection: close = don't try to parse the body as a new request - req.write_all(b"\ + req.write_all( + b"\ GET / HTTP/1.1\r\n\ Host: example.domain\r\n\ Connection: close\r\n\ \r\n\ I shouldn't be read.\r\n\ - ").unwrap(); + ", + ) + .unwrap(); req.read(&mut [0; 256]).unwrap(); assert_eq!(server.body(), b""); @@ -52,13 +54,16 @@ fn get_should_ignore_body() { fn get_with_body() { let server = serve(); let mut req = connect(server.addr()); - req.write_all(b"\ + req.write_all( + b"\ GET / HTTP/1.1\r\n\ Host: example.domain\r\n\ Content-Length: 19\r\n\ \r\n\ I'm a good request.\r\n\ - ").unwrap(); + ", + ) + .unwrap(); req.read(&mut [0; 256]).unwrap(); // note: doesn't include trailing \r\n, cause Content-Length wasn't 21 @@ -82,7 +87,10 @@ mod response_body_lengths { } fn run_test(case: TestCase) { - assert!(case.version == 0 || case.version == 1, "TestCase.version must 0 or 1"); + assert!( + case.version == 0 || case.version == 1, + "TestCase.version must 0 or 1" + ); let server = serve(); @@ -95,22 +103,27 @@ mod response_body_lengths { Bd::Known(b) => { reply.body(b); b - }, + } Bd::Unknown(b) => { let (mut tx, body) = hyper::Body::channel(); tx.try_send_data(b.into()).expect("try_send_data"); reply.body_stream(body); b - }, + } }; let mut req = connect(server.addr()); - write!(req, "\ - GET / HTTP/1.{}\r\n\ - Host: example.domain\r\n\ - Connection: close\r\n\ - \r\n\ - ", case.version).expect("request write"); + write!( + req, + "\ + GET / HTTP/1.{}\r\n\ + Host: example.domain\r\n\ + Connection: close\r\n\ + \r\n\ + ", + case.version + ) + .expect("request write"); let mut body = String::new(); req.read_to_string(&mut body).unwrap(); @@ -139,9 +152,17 @@ mod response_body_lengths { if case.expects_chunked { let len = body.len(); - assert_eq!(&body[n + 1..n + 3], "\r\n", "expected body chunk size header"); + assert_eq!( + &body[n + 1..n + 3], + "\r\n", + "expected body chunk size header" + ); assert_eq!(&body[n + 3..len - 7], body_str, "expected body"); - assert_eq!(&body[len - 7..], "\r\n0\r\n\r\n", "expected body final chunk size header"); + assert_eq!( + &body[len - 7..], + "\r\n0\r\n\r\n", + "expected body final chunk size header" + ); } else { assert_eq!(&body[n..], body_str, "expected body"); } @@ -281,7 +302,6 @@ mod response_body_lengths { }); } - #[test] fn http10_chunked_response() { run_test(TestCase { @@ -344,45 +364,49 @@ fn get_chunked_response_with_ka() { let foo_bar = b"foo bar baz"; let foo_bar_chunk = b"\r\nfoo bar baz\r\n0\r\n\r\n"; let server = serve(); - server.reply() + server + .reply() .header("transfer-encoding", "chunked") .body(foo_bar); let mut req = connect(server.addr()); - req.write_all(b"\ + req.write_all( + b"\ GET / HTTP/1.1\r\n\ Host: example.domain\r\n\ Connection: keep-alive\r\n\ \r\n\ - ").expect("writing 1"); + ", + ) + .expect("writing 1"); - read_until(&mut req, |buf| { - buf.ends_with(foo_bar_chunk) - }).expect("reading 1"); + read_until(&mut req, |buf| buf.ends_with(foo_bar_chunk)).expect("reading 1"); // try again! let quux = b"zar quux"; - server.reply() + server + .reply() .header("content-length", quux.len().to_string()) .body(quux); - req.write_all(b"\ + req.write_all( + b"\ GET /quux HTTP/1.1\r\n\ Host: example.domain\r\n\ Connection: close\r\n\ \r\n\ - ").expect("writing 2"); - + ", + ) + .expect("writing 2"); - read_until(&mut req, |buf| { - buf.ends_with(quux) - }).expect("reading 2"); + read_until(&mut req, |buf| buf.ends_with(quux)).expect("reading 2"); } #[test] fn post_with_chunked_body() { let server = serve(); let mut req = connect(server.addr()); - req.write_all(b"\ + req.write_all( + b"\ POST / HTTP/1.1\r\n\ Host: example.domain\r\n\ Transfer-Encoding: chunked\r\n\ @@ -395,7 +419,9 @@ fn post_with_chunked_body() { rt\r\n\ 0\r\n\ \r\n\ - ").unwrap(); + ", + ) + .unwrap(); req.read(&mut [0; 256]).unwrap(); assert_eq!(server.body(), b"qwert"); @@ -406,13 +432,16 @@ fn post_with_incomplete_body() { let _ = pretty_env_logger::try_init(); let server = serve(); let mut req = connect(server.addr()); - req.write_all(b"\ + req.write_all( + b"\ POST / HTTP/1.1\r\n\ Host: example.domain\r\n\ Content-Length: 10\r\n\ \r\n\ 12345\ - ").expect("write"); + ", + ) + .expect("write"); req.shutdown(Shutdown::Write).expect("shutdown write"); server.body_err(); @@ -420,20 +449,21 @@ fn post_with_incomplete_body() { req.read(&mut [0; 256]).expect("read"); } - #[test] fn head_response_can_send_content_length() { let _ = pretty_env_logger::try_init(); let server = serve(); - server.reply() - .header("content-length", "1024"); + server.reply().header("content-length", "1024"); let mut req = connect(server.addr()); - req.write_all(b"\ + req.write_all( + b"\ HEAD / HTTP/1.1\r\n\ Host: example.domain\r\n\ Connection: close\r\n\ \r\n\ - ").unwrap(); + ", + ) + .unwrap(); let mut response = String::new(); req.read_to_string(&mut response).unwrap(); @@ -453,15 +483,17 @@ fn head_response_doesnt_send_body() { let _ = pretty_env_logger::try_init(); let foo_bar = b"foo bar baz"; let server = serve(); - server.reply() - .body(foo_bar); + server.reply().body(foo_bar); let mut req = connect(server.addr()); - req.write_all(b"\ + req.write_all( + b"\ HEAD / HTTP/1.1\r\n\ Host: example.domain\r\n\ Connection: close\r\n\ \r\n\ - ").unwrap(); + ", + ) + .unwrap(); let mut response = String::new(); req.read_to_string(&mut response).unwrap(); @@ -480,16 +512,20 @@ fn head_response_doesnt_send_body() { fn response_does_not_set_chunked_if_body_not_allowed() { let _ = pretty_env_logger::try_init(); let server = serve(); - server.reply() + server + .reply() .status(hyper::StatusCode::NOT_MODIFIED) .header("transfer-encoding", "chunked"); let mut req = connect(server.addr()); - req.write_all(b"\ + req.write_all( + b"\ GET / HTTP/1.1\r\n\ Host: example.domain\r\n\ Connection: close\r\n\ \r\n\ - ").unwrap(); + ", + ) + .unwrap(); let mut response = String::new(); req.read_to_string(&mut response).unwrap(); @@ -509,36 +545,40 @@ fn response_does_not_set_chunked_if_body_not_allowed() { fn keep_alive() { let foo_bar = b"foo bar baz"; let server = serve(); - server.reply() + server + .reply() .header("content-length", foo_bar.len().to_string()) .body(foo_bar); let mut req = connect(server.addr()); - req.write_all(b"\ + req.write_all( + b"\ GET / HTTP/1.1\r\n\ Host: example.domain\r\n\ \r\n\ - ").expect("writing 1"); + ", + ) + .expect("writing 1"); - read_until(&mut req, |buf| { - buf.ends_with(foo_bar) - }).expect("reading 1"); + read_until(&mut req, |buf| buf.ends_with(foo_bar)).expect("reading 1"); // try again! let quux = b"zar quux"; - server.reply() + server + .reply() .header("content-length", quux.len().to_string()) .body(quux); - req.write_all(b"\ + req.write_all( + b"\ GET /quux HTTP/1.1\r\n\ Host: example.domain\r\n\ Connection: close\r\n\ \r\n\ - ").expect("writing 2"); + ", + ) + .expect("writing 2"); - read_until(&mut req, |buf| { - buf.ends_with(quux) - }).expect("reading 2"); + read_until(&mut req, |buf| buf.ends_with(quux)).expect("reading 2"); } #[test] @@ -546,22 +586,23 @@ fn http_10_keep_alive() { let foo_bar = b"foo bar baz"; let server = serve(); // Response version 1.1 with no keep-alive header will downgrade to 1.0 when served - server.reply() + server + .reply() .header("content-length", foo_bar.len().to_string()) .body(foo_bar); let mut req = connect(server.addr()); - req.write_all(b"\ + req.write_all( + b"\ GET / HTTP/1.0\r\n\ Host: example.domain\r\n\ Connection: keep-alive\r\n\ \r\n\ - ").expect("writing 1"); - + ", + ) + .expect("writing 1"); // Connection: keep-alive header should be added when downgrading to a 1.0 response - let res = read_until(&mut req, |buf| { - buf.ends_with(foo_bar) - }).expect("reading 1"); + let res = read_until(&mut req, |buf| buf.ends_with(foo_bar)).expect("reading 1"); let sres = s(&res); assert!( @@ -573,19 +614,20 @@ fn http_10_keep_alive() { // try again! let quux = b"zar quux"; - server.reply() + server + .reply() .header("content-length", quux.len().to_string()) .body(quux); - req.write_all(b"\ + req.write_all( + b"\ GET /quux HTTP/1.0\r\n\ Host: example.domain\r\n\ \r\n\ - ").expect("writing 2"); - + ", + ) + .expect("writing 2"); - read_until(&mut req, |buf| { - buf.ends_with(quux) - }).expect("reading 2"); + read_until(&mut req, |buf| buf.ends_with(quux)).expect("reading 2"); } #[test] @@ -609,7 +651,8 @@ fn http_10_close_on_no_ka() { Connection: keep-alive\r\n\ \r\n\ ", - ).expect("writing 1"); + ) + .expect("writing 1"); // server isn't keeping-alive, so the socket should be closed after // writing the response. thus, read_to_end should succeed. @@ -628,20 +671,21 @@ fn http_10_close_on_no_ka() { #[test] fn disable_keep_alive() { let foo_bar = b"foo bar baz"; - let server = serve_opts() - .keep_alive(false) - .serve(); - server.reply() + let server = serve_opts().keep_alive(false).serve(); + server + .reply() .header("content-length", foo_bar.len().to_string()) .body(foo_bar); let mut req = connect(server.addr()); - req.write_all(b"\ + req.write_all( + b"\ GET / HTTP/1.1\r\n\ Host: example.domain\r\n\ Connection: keep-alive\r\n\ \r\n\ - ").expect("writing 1"); - + ", + ) + .expect("writing 1"); // server isn't keeping-alive, so the socket should be closed after // writing the response. thus, read_to_end should succeed. @@ -654,17 +698,21 @@ fn disable_keep_alive() { fn header_connection_close() { let foo_bar = b"foo bar baz"; let server = serve(); - server.reply() + server + .reply() .header("content-length", foo_bar.len().to_string()) .header("connection", "close") .body(foo_bar); let mut req = connect(server.addr()); - req.write_all(b"\ + req.write_all( + b"\ GET / HTTP/1.1\r\n\ Host: example.domain\r\n\ Connection: keep-alive\r\n\ \r\n\ - ").expect("writing 1"); + ", + ) + .expect("writing 1"); // server isn't keeping-alive, so the socket should be closed after // writing the response. thus, read_to_end should succeed. @@ -685,14 +733,17 @@ fn expect_continue_sends_100() { let mut req = connect(server.addr()); server.reply(); - req.write_all(b"\ + req.write_all( + b"\ POST /foo HTTP/1.1\r\n\ Host: example.domain\r\n\ Expect: 100-continue\r\n\ Content-Length: 5\r\n\ Connection: Close\r\n\ \r\n\ - ").expect("write 1"); + ", + ) + .expect("write 1"); let msg = b"HTTP/1.1 100 Continue\r\n\r\n"; let mut buf = vec![0; msg.len()]; @@ -716,13 +767,16 @@ fn expect_continue_but_no_body_is_ignored() { server.reply(); // no content-length or transfer-encoding means no body! - req.write_all(b"\ + req.write_all( + b"\ POST /foo HTTP/1.1\r\n\ Host: example.domain\r\n\ Expect: 100-continue\r\n\ Connection: Close\r\n\ \r\n\ - ").expect("write"); + ", + ) + .expect("write"); let expected = "HTTP/1.1 200 OK\r\n"; let mut resp = String::new(); @@ -735,21 +789,26 @@ fn expect_continue_but_no_body_is_ignored() { fn pipeline_disabled() { let server = serve(); let mut req = connect(server.addr()); - server.reply() + server + .reply() .header("content-length", "12") .body("Hello World!"); - server.reply() + server + .reply() .header("content-length", "12") .body("Hello World!"); - req.write_all(b"\ + req.write_all( + b"\ GET / HTTP/1.1\r\n\ Host: example.domain\r\n\ \r\n\ GET / HTTP/1.1\r\n\ Host: example.domain\r\n\ \r\n\ - ").expect("write 1"); + ", + ) + .expect("write 1"); let mut buf = vec![0; 4096]; let n = req.read(&mut buf).expect("read 1"); @@ -775,18 +834,19 @@ fn pipeline_disabled() { #[test] fn pipeline_enabled() { - let server = serve_opts() - .pipeline(true) - .serve(); + let server = serve_opts().pipeline(true).serve(); let mut req = connect(server.addr()); - server.reply() + server + .reply() .header("content-length", "12") .body("Hello World\n"); - server.reply() + server + .reply() .header("content-length", "12") .body("Hello World\n"); - req.write_all(b"\ + req.write_all( + b"\ GET / HTTP/1.1\r\n\ Host: example.domain\r\n\ \r\n\ @@ -794,7 +854,9 @@ fn pipeline_enabled() { Host: example.domain\r\n\ Connection: close\r\n\ \r\n\ - ").expect("write 1"); + ", + ) + .expect("write 1"); let mut buf = vec![0; 4096]; let n = req.read(&mut buf).expect("read 1"); @@ -815,7 +877,6 @@ fn pipeline_enabled() { assert_eq!(s(lines.next().unwrap()), "Hello World"); } - // with pipeline enabled, both responses should have been in the first read // so a second read should be EOF let n = req.read(&mut buf).expect("read 2"); @@ -827,10 +888,13 @@ fn http_10_request_receives_http_10_response() { let server = serve(); let mut req = connect(server.addr()); - req.write_all(b"\ + req.write_all( + b"\ GET / HTTP/1.0\r\n\ \r\n\ - ").unwrap(); + ", + ) + .unwrap(); let expected = "HTTP/1.0 200 OK\r\ncontent-length: 0\r\n"; let mut buf = [0; 256]; @@ -860,17 +924,15 @@ async fn disable_keep_alive_mid_request() { let (socket, _) = listener.accept().await.unwrap(); let srv = Http::new().serve_connection(socket, HelloWorld); future::try_select(srv, rx1) - .then(|r| { - match r { - Ok(Either::Left(_)) => panic!("expected rx first"), - Ok(Either::Right(((), mut conn))) => { - Pin::new(&mut conn).graceful_shutdown(); - tx2.send(()).unwrap(); - conn - } - Err(Either::Left((e, _))) => panic!("unexpected error {}", e), - Err(Either::Right((e, _))) => panic!("unexpected error {}", e), + .then(|r| match r { + Ok(Either::Left(_)) => panic!("expected rx first"), + Ok(Either::Right(((), mut conn))) => { + Pin::new(&mut conn).graceful_shutdown(); + tx2.send(()).unwrap(); + conn } + Err(Either::Left((e, _))) => panic!("unexpected error {}", e), + Err(Either::Right((e, _))) => panic!("unexpected error {}", e), }) .await .unwrap(); @@ -888,15 +950,16 @@ async fn disable_keep_alive_post_request() { let child = thread::spawn(move || { let mut req = connect(&addr); - req.write_all(b"\ + req.write_all( + b"\ GET / HTTP/1.1\r\n\ Host: localhost\r\n\ \r\n\ - ").unwrap(); + ", + ) + .unwrap(); - read_until(&mut req, |buf| { - buf.ends_with(HELLO.as_bytes()) - }).expect("reading 1"); + read_until(&mut req, |buf| buf.ends_with(HELLO.as_bytes())).expect("reading 1"); // Connection should get closed *after* tx is sent on tx1.send(()).unwrap(); @@ -913,18 +976,15 @@ async fn disable_keep_alive_post_request() { _debug: dropped2, }; let server = Http::new().serve_connection(transport, HelloWorld); - let fut = future::try_select(server, rx1) - .then(|r| { - match r { - Ok(Either::Left(_)) => panic!("expected rx first"), - Ok(Either::Right(((), mut conn))) => { - Pin::new(&mut conn).graceful_shutdown(); - conn - } - Err(Either::Left((e, _))) => panic!("unexpected error {}", e), - Err(Either::Right((e, _))) => panic!("unexpected error {}", e), - } - }); + let fut = future::try_select(server, rx1).then(|r| match r { + Ok(Either::Left(_)) => panic!("expected rx first"), + Ok(Either::Right(((), mut conn))) => { + Pin::new(&mut conn).graceful_shutdown(); + conn + } + Err(Either::Left((e, _))) => panic!("unexpected error {}", e), + Err(Either::Right((e, _))) => panic!("unexpected error {}", e), + }); assert!(!dropped.load()); fut.await.unwrap(); @@ -986,10 +1046,13 @@ async fn http1_allow_half_close() { let (socket, _) = listener.accept().await.unwrap(); Http::new() .http1_half_close(true) - .serve_connection(socket, service_fn(|_| { - tokio::time::delay_for(Duration::from_millis(500)) - .map(|_| Ok::<_, hyper::Error>(Response::new(Body::empty()))) - })) + .serve_connection( + socket, + service_fn(|_| { + tokio::time::delay_for(Duration::from_millis(500)) + .map(|_| Ok::<_, hyper::Error>(Response::new(Body::empty()))) + }), + ) .await .unwrap(); @@ -1010,12 +1073,16 @@ async fn disconnect_after_reading_request_before_responding() { let (socket, _) = listener.accept().await.unwrap(); Http::new() .http1_half_close(false) - .serve_connection(socket, service_fn(|_| { - tokio::time::delay_for(Duration::from_secs(2)) - .map(|_| -> Result, hyper::Error> { - panic!("response future should have been dropped"); - }) - })) + .serve_connection( + socket, + service_fn(|_| { + tokio::time::delay_for(Duration::from_secs(2)).map( + |_| -> Result, hyper::Error> { + panic!("response future should have been dropped"); + }, + ) + }), + ) .await .expect_err("socket disconnected"); } @@ -1037,12 +1104,19 @@ async fn returning_1xx_response_is_error() { let (socket, _) = listener.accept().await.unwrap(); Http::new() - .serve_connection(socket, service_fn(|_| async move { - Ok::<_, hyper::Error>(Response::builder() - .status(StatusCode::CONTINUE) - .body(Body::empty()) - .unwrap()) - })) + .serve_connection( + socket, + service_fn(|_| { + async move { + Ok::<_, hyper::Error>( + Response::builder() + .status(StatusCode::CONTINUE) + .body(Body::empty()) + .unwrap(), + ) + } + }), + ) .await .expect_err("1xx status code should error"); } @@ -1076,13 +1150,16 @@ async fn upgrades() { thread::spawn(move || { let mut tcp = connect(&addr); - tcp.write_all(b"\ + tcp.write_all( + b"\ GET / HTTP/1.1\r\n\ Upgrade: foobar\r\n\ Connection: upgrade\r\n\ \r\n\ eagerly optimistic\ - ").expect("write 1"); + ", + ) + .expect("write 1"); let mut buf = [0; 256]; tcp.read(&mut buf).expect("read 1"); @@ -1096,15 +1173,17 @@ async fn upgrades() { }); let (socket, _) = listener.accept().await.unwrap(); - let conn = Http::new() - .serve_connection(socket, service_fn(|_| { + let conn = Http::new().serve_connection( + socket, + service_fn(|_| { let res = Response::builder() .status(101) .header("upgrade", "foobar") .body(hyper::Body::empty()) .unwrap(); future::ready(Ok::<_, hyper::Error>(res)) - })); + }), + ); let parts = conn.without_shutdown().await.unwrap(); assert_eq!(parts.read_buf, "eagerly optimistic"); @@ -1130,11 +1209,14 @@ async fn http_connect() { thread::spawn(move || { let mut tcp = connect(&addr); - tcp.write_all(b"\ + tcp.write_all( + b"\ CONNECT localhost:80 HTTP/1.1\r\n\ \r\n\ eagerly optimistic\ - ").expect("write 1"); + ", + ) + .expect("write 1"); let mut buf = [0; 256]; tcp.read(&mut buf).expect("read 1"); @@ -1148,14 +1230,16 @@ async fn http_connect() { }); let (socket, _) = listener.accept().await.unwrap(); - let conn = Http::new() - .serve_connection(socket, service_fn(|_| { + let conn = Http::new().serve_connection( + socket, + service_fn(|_| { let res = Response::builder() .status(200) .body(hyper::Body::empty()) .unwrap(); future::ready(Ok::<_, hyper::Error>(res)) - })); + }), + ); let parts = conn.without_shutdown().await.unwrap(); assert_eq!(parts.read_buf, "eagerly optimistic"); @@ -1181,13 +1265,16 @@ async fn upgrades_new() { thread::spawn(move || { let mut tcp = connect(&addr); - tcp.write_all(b"\ + tcp.write_all( + b"\ GET / HTTP/1.1\r\n\ Upgrade: foobar\r\n\ Connection: upgrade\r\n\ \r\n\ eagerly optimistic\ - ").expect("write 1"); + ", + ) + .expect("write 1"); let mut buf = [0; 256]; tcp.read(&mut buf).expect("read 1"); @@ -1202,15 +1289,15 @@ async fn upgrades_new() { let (upgrades_tx, upgrades_rx) = mpsc::channel(); let svc = service_fn(move |req: Request| { - let on_upgrade = req - .into_body() - .on_upgrade(); + let on_upgrade = req.into_body().on_upgrade(); let _ = upgrades_tx.send(on_upgrade); - future::ok::<_, hyper::Error>(Response::builder() - .status(101) - .header("upgrade", "foobar") - .body(hyper::Body::empty()) - .unwrap()) + future::ok::<_, hyper::Error>( + Response::builder() + .status(101) + .header("upgrade", "foobar") + .body(hyper::Body::empty()) + .unwrap(), + ) }); let (socket, _) = listener.accept().await.unwrap(); @@ -1247,11 +1334,14 @@ async fn http_connect_new() { thread::spawn(move || { let mut tcp = connect(&addr); - tcp.write_all(b"\ + tcp.write_all( + b"\ CONNECT localhost HTTP/1.1\r\n\ \r\n\ eagerly optimistic\ - ").expect("write 1"); + ", + ) + .expect("write 1"); let mut buf = [0; 256]; tcp.read(&mut buf).expect("read 1"); @@ -1266,14 +1356,14 @@ async fn http_connect_new() { let (upgrades_tx, upgrades_rx) = mpsc::channel(); let svc = service_fn(move |req: Request| { - let on_upgrade = req - .into_body() - .on_upgrade(); + let on_upgrade = req.into_body().on_upgrade(); let _ = upgrades_tx.send(on_upgrade); - future::ok::<_, hyper::Error>(Response::builder() - .status(200) - .body(hyper::Body::empty()) - .unwrap()) + future::ok::<_, hyper::Error>( + Response::builder() + .status(200) + .body(hyper::Body::empty()) + .unwrap(), + ) }); let (socket, _) = listener.accept().await.unwrap(); @@ -1299,7 +1389,6 @@ async fn http_connect_new() { assert_eq!(s(&vec), "bar=foo"); } - #[tokio::test] async fn parse_errors_send_4xx_response() { let mut listener = tcp_bind(&"127.0.0.1:0".parse().unwrap()).unwrap(); @@ -1329,7 +1418,8 @@ async fn illegal_request_length_returns_400_response() { thread::spawn(move || { let mut tcp = connect(&addr); - tcp.write_all(b"POST / HTTP/1.1\r\nContent-Length: foo\r\n\r\n").unwrap(); + tcp.write_all(b"POST / HTTP/1.1\r\nContent-Length: foo\r\n\r\n") + .unwrap(); let mut buf = [0; 256]; tcp.read(&mut buf).unwrap(); @@ -1389,24 +1479,22 @@ fn streaming_body() { let _ = pretty_env_logger::try_init(); // disable keep-alive so we can use read_to_end - let server = serve_opts() - .keep_alive(false) - .serve(); + let server = serve_opts().keep_alive(false).serve(); static S: &'static [&'static [u8]] = &[&[b'x'; 1_000] as &[u8]; 1_00] as _; - let b = ::futures_util::stream::iter(S.into_iter()) - .map(|&s| Ok::<_, hyper::Error>(s)); + let b = ::futures_util::stream::iter(S.into_iter()).map(|&s| Ok::<_, hyper::Error>(s)); let b = hyper::Body::wrap_stream(b); - server - .reply() - .body_stream(b); + server.reply().body_stream(b); let mut tcp = connect(server.addr()); tcp.write_all(b"GET / HTTP/1.1\r\n\r\n").unwrap(); let mut buf = Vec::new(); tcp.read_to_end(&mut buf).expect("read 1"); - assert!(buf.starts_with(b"HTTP/1.1 200 OK\r\n"), "response is 200 OK"); + assert!( + buf.starts_with(b"HTTP/1.1 200 OK\r\n"), + "response is 200 OK" + ); assert_eq!(buf.len(), 100_789, "full streamed body read"); } @@ -1417,15 +1505,14 @@ fn http1_response_with_http2_version() { let mut rt = Runtime::new().expect("runtime new"); - server - .reply() - .version(hyper::Version::HTTP_2); + server.reply().version(hyper::Version::HTTP_2); rt.block_on({ let client = Client::new(); let uri = addr_str.parse().expect("server addr should parse"); client.get(uri) - }).unwrap(); + }) + .unwrap(); } #[test] @@ -1441,20 +1528,16 @@ fn try_h2() { .build_http::(); let uri = addr_str.parse().expect("server addr should parse"); - client - .get(uri) - .map_ok(|_| { () }) - .map_err(|_e| { () }) - }).unwrap(); + client.get(uri).map_ok(|_| ()).map_err(|_e| ()) + }) + .unwrap(); assert_eq!(server.body(), b""); } #[test] fn http1_only() { - let server = serve_opts() - .http1_only() - .serve(); + let server = serve_opts().http1_only().serve(); let addr_str = format!("http://{}", server.addr()); let mut rt = Runtime::new().expect("runtime new"); @@ -1465,7 +1548,8 @@ fn http1_only() { .build_http::(); let uri = addr_str.parse().expect("server addr should parse"); client.get(uri) - }).unwrap_err(); + }) + .unwrap_err(); } #[tokio::test] @@ -1504,36 +1588,32 @@ fn http2_body_user_error_sends_reset_reason() { let server = serve(); let addr_str = format!("http://{}", server.addr()); - let b = ::futures_util::stream::once( - future::err::(h2::Error::from(h2::Reason::INADEQUATE_SECURITY)) - ); + let b = ::futures_util::stream::once(future::err::(h2::Error::from( + h2::Reason::INADEQUATE_SECURITY, + ))); let b = hyper::Body::wrap_stream(b); - server - .reply() - .body_stream(b); + server.reply().body_stream(b); let mut rt = Runtime::new().expect("runtime new"); - let err: hyper::Error = rt.block_on(async move { - let client = Client::builder() - .http2_only(true) - .build_http::(); - let uri = addr_str.parse().expect("server addr should parse"); + let err: hyper::Error = rt + .block_on(async move { + let client = Client::builder() + .http2_only(true) + .build_http::(); + let uri = addr_str.parse().expect("server addr should parse"); - let mut res = client.get(uri).await?; + let mut res = client.get(uri).await?; - while let Some(chunk) = res.body_mut().next().await { - chunk?; - } - Ok(()) - }).unwrap_err(); + while let Some(chunk) = res.body_mut().next().await { + chunk?; + } + Ok(()) + }) + .unwrap_err(); - let h2_err = err - .source() - .unwrap() - .downcast_ref::() - .unwrap(); + let h2_err = err.source().unwrap().downcast_ref::().unwrap(); assert_eq!(h2_err.reason(), Some(h2::Reason::INADEQUATE_SECURITY)); } @@ -1543,12 +1623,17 @@ struct Http2ReadyErrorSvc; impl tower_service::Service> for Http2ReadyErrorSvc { type Response = Response; type Error = h2::Error; - type Future = Box - > + Send + Sync + Unpin>; + type Future = Box< + dyn futures_core::Future> + + Send + + Sync + + Unpin, + >; fn poll_ready(&mut self, _: &mut std::task::Context<'_>) -> Poll> { - Poll::Ready(Err::<(), _>(h2::Error::from(h2::Reason::INADEQUATE_SECURITY))) + Poll::Ready(Err::<(), _>(h2::Error::from( + h2::Reason::INADEQUATE_SECURITY, + ))) } fn call(&mut self, _: hyper::Request) -> Self::Future { @@ -1565,7 +1650,9 @@ async fn http2_service_poll_ready_error_sends_goaway() { let server = hyper::Server::bind(&([127, 0, 0, 1], 0).into()) .http2_only(true) - .serve(make_service_fn(|_| async move { Ok::<_, BoxError>(Http2ReadyErrorSvc) })); + .serve(make_service_fn(|_| { + async move { Ok::<_, BoxError>(Http2ReadyErrorSvc) } + })); let addr_str = format!("http://{}", server.local_addr()); @@ -1594,17 +1681,20 @@ async fn http2_service_poll_ready_error_sends_goaway() { #[test] fn skips_content_length_for_304_responses() { let server = serve(); - server.reply() - + server + .reply() .status(hyper::StatusCode::NOT_MODIFIED) .body("foo"); let mut req = connect(server.addr()); - req.write_all(b"\ + req.write_all( + b"\ GET / HTTP/1.1\r\n\ Host: example.domain\r\n\ Connection: close\r\n\ \r\n\ - ").unwrap(); + ", + ) + .unwrap(); let mut response = String::new(); req.read_to_string(&mut response).unwrap(); @@ -1614,17 +1704,20 @@ fn skips_content_length_for_304_responses() { #[test] fn skips_content_length_and_body_for_304_responses() { let server = serve(); - server.reply() - + server + .reply() .status(hyper::StatusCode::NOT_MODIFIED) .body("foo"); let mut req = connect(server.addr()); - req.write_all(b"\ + req.write_all( + b"\ GET / HTTP/1.1\r\n\ Host: example.domain\r\n\ Connection: close\r\n\ \r\n\ - ").unwrap(); + ", + ) + .unwrap(); let mut response = String::new(); req.read_to_string(&mut response).unwrap(); @@ -1667,7 +1760,7 @@ impl Serve { match self.msg_rx.recv() { Ok(Msg::Chunk(msg)) => { buf.extend(&msg); - }, + } Ok(Msg::Error(e)) => return Err(e), Ok(Msg::End) => break, Err(e) => panic!("expected body, found: {:?}", e), @@ -1677,9 +1770,7 @@ impl Serve { } fn reply(&self) -> ReplyBuilder<'_> { - ReplyBuilder { - tx: &self.reply_tx - } + ReplyBuilder { tx: &self.reply_tx } } } @@ -1696,19 +1787,31 @@ impl<'a> ReplyBuilder<'a> { } fn version(self, version: hyper::Version) -> Self { - self.tx.lock().unwrap().send(Reply::Version(version)).unwrap(); + self.tx + .lock() + .unwrap() + .send(Reply::Version(version)) + .unwrap(); self } fn header>(self, name: &str, value: V) -> Self { let name = HeaderName::from_bytes(name.as_bytes()).expect("header name"); let value = HeaderValue::from_str(value.as_ref()).expect("header value"); - self.tx.lock().unwrap().send(Reply::Header(name, value)).unwrap(); + self.tx + .lock() + .unwrap() + .send(Reply::Header(name, value)) + .unwrap(); self } fn body>(self, body: T) { - self.tx.lock().unwrap().send(Reply::Body(body.as_ref().to_vec().into())).unwrap(); + self.tx + .lock() + .unwrap() + .send(Reply::Body(body.as_ref().to_vec().into())) + .unwrap(); } fn body_stream(self, body: Body) { @@ -1717,14 +1820,18 @@ impl<'a> ReplyBuilder<'a> { #[allow(dead_code)] fn error>(self, err: E) { - self.tx.lock().unwrap().send(Reply::Error(err.into())).unwrap(); + self.tx + .lock() + .unwrap() + .send(Reply::Error(err.into())) + .unwrap(); } } impl<'a> Drop for ReplyBuilder<'a> { fn drop(&mut self) { if let Ok(mut tx) = self.tx.lock() { - let _ = tx.send(Reply::End); + let _ = tx.send(Reply::End); } } } @@ -1784,11 +1891,11 @@ impl tower_service::Service> for TestService { match chunk { Ok(chunk) => { tx.send(Msg::Chunk(chunk.to_vec())).unwrap(); - }, + } Err(err) => { tx.send(Msg::Error(err)).unwrap(); return Err("req body error".into()); - }, + } } } @@ -1806,16 +1913,16 @@ impl TestService { match reply { Reply::Status(s) => { *res.status_mut() = s; - }, + } Reply::Version(v) => { *res.version_mut() = v; - }, + } Reply::Header(name, value) => { res.headers_mut().insert(name, value); - }, + } Reply::Body(body) => { *res.body_mut() = body; - }, + } Reply::Error(err) => return Err(err), Reply::End => break, } @@ -1843,7 +1950,6 @@ impl tower_service::Service> for HelloWorld { } } - fn connect(addr: &SocketAddr) -> TcpStream { let req = TcpStream::connect(addr).unwrap(); req.set_read_timeout(Some(Duration::from_secs(1))).unwrap(); @@ -1935,16 +2041,15 @@ impl ServeOptions { .http1_pipeline_flush(options.pipeline) .serve(service); - addr_tx.send( - server.local_addr() - ).expect("server addr tx"); + addr_tx.send(server.local_addr()).expect("server addr tx"); server .with_graceful_shutdown(async { let _ = shutdown_rx.await; }) .await - }).expect("serve()"); + }) + .expect("serve()"); }) .expect("thread spawn"); @@ -1992,7 +2097,7 @@ where if pos == buf.len() { return Err(io::Error::new( io::ErrorKind::Other, - "read_until buffer filled" + "read_until buffer filled", )); } } @@ -2023,7 +2128,6 @@ impl Write for DebugStream { } } - impl AsyncWrite for DebugStream { fn poll_write( mut self: Pin<&mut Self>, @@ -2037,12 +2141,14 @@ impl AsyncWrite for DebugStream { Pin::new(&mut self.stream).poll_flush(cx) } - fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + fn poll_shutdown( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { Pin::new(&mut self.stream).poll_shutdown(cx) } } - impl AsyncRead for DebugStream { fn poll_read( mut self: Pin<&mut Self>, diff --git a/tests/support/mod.rs b/tests/support/mod.rs index 7f9233f0c8..bc39a7e4e7 100644 --- a/tests/support/mod.rs +++ b/tests/support/mod.rs @@ -1,15 +1,20 @@ use std::future::Future; use std::pin::Pin; -use std::sync::{Arc, Mutex, atomic::{AtomicUsize, Ordering}}; -use std::time::{Duration/*, Instant*/}; +use std::sync::{ + atomic::{AtomicUsize, Ordering}, + Arc, Mutex, +}; +use std::time::Duration; -use hyper::{Body, Client, Request, Response, Server, Version}; use hyper::client::HttpConnector; use hyper::service::{make_service_fn, service_fn}; +use hyper::{Body, Client, Request, Response, Server, Version}; -pub use std::net::SocketAddr; -pub use futures_util::{future, FutureExt as _, StreamExt as _, TryFutureExt as _, TryStreamExt as _}; +pub use futures_util::{ + future, FutureExt as _, StreamExt as _, TryFutureExt as _, TryStreamExt as _, +}; pub use hyper::{HeaderMap, StatusCode}; +pub use std::net::SocketAddr; macro_rules! t { ( @@ -154,43 +159,43 @@ macro_rules! t { } macro_rules! __internal_map_prop { - (headers: $map:tt) => ({ + (headers: $map:tt) => {{ #[allow(unused_mut)] { - let mut headers = HeaderMap::new(); - __internal_headers_map!(headers, $map); - headers + let mut headers = HeaderMap::new(); + __internal_headers_map!(headers, $map); + headers } - }); - ($name:tt: $val:tt) => ({ + }}; + ($name:tt: $val:tt) => {{ __internal_req_res_prop!($name: $val) - }); + }}; } macro_rules! __internal_eq_prop { - (headers: $map:tt) => ({ + (headers: $map:tt) => {{ #[allow(unused_mut)] { - let mut headers = Vec::new(); - __internal_headers_eq!(headers, $map); - headers + let mut headers = Vec::new(); + __internal_headers_eq!(headers, $map); + headers } - }); - ($name:tt: $val:tt) => ({ + }}; + ($name:tt: $val:tt) => {{ __internal_req_res_prop!($name: $val) - }); + }}; } macro_rules! __internal_req_res_prop { - (method: $prop_val:expr) => ( + (method: $prop_val:expr) => { $prop_val - ); - (status: $prop_val:expr) => ( + }; + (status: $prop_val:expr) => { StatusCode::from_u16($prop_val).expect("status code") - ); - ($prop_name:ident: $prop_val:expr) => ( + }; + ($prop_name:ident: $prop_val:expr) => { From::from($prop_val) - ) + }; } macro_rules! __internal_headers_map { @@ -325,9 +330,7 @@ async fn async_test(cfg: __TestConfig) { .http2_only(cfg.client_version == 2) .build::<_, Body>(connector); - let serve_handles = Arc::new(Mutex::new( - cfg.server_msgs - )); + let serve_handles = Arc::new(Mutex::new(cfg.server_msgs)); let expected_connections = cfg.connections; let mut cnt = 0; @@ -343,9 +346,7 @@ async fn async_test(cfg: __TestConfig) { // Move a clone into the service_fn let serve_handles = serve_handles.clone(); future::ok::<_, hyper::Error>(service_fn(move |req: Request| { - let (sreq, sres) = serve_handles.lock() - .unwrap() - .remove(0); + let (sreq, sres) = serve_handles.lock().unwrap().remove(0); assert_eq!(req.uri().path(), sreq.uri, "client path"); assert_eq!(req.method(), &sreq.method, "client method"); @@ -354,17 +355,16 @@ async fn async_test(cfg: __TestConfig) { func(&req.headers()); } let sbody = sreq.body; - concat(req.into_body()) - .map_ok(move |body| { - assert_eq!(body.as_ref(), sbody.as_slice(), "client body"); - - let mut res = Response::builder() - .status(sres.status) - .body(Body::from(sres.body)) - .expect("Response::build"); - *res.headers_mut() = sres.headers; - res - }) + concat(req.into_body()).map_ok(move |body| { + assert_eq!(body.as_ref(), sbody.as_slice(), "client body"); + + let mut res = Response::builder() + .status(sres.status) + .body(Body::from(sres.body)) + .expect("Response::build"); + *res.headers_mut() = sres.headers; + res + }) })) }); @@ -388,34 +388,36 @@ async fn async_test(cfg: __TestConfig) { addr = proxy_addr; } - let make_request = Arc::new(move |client: &Client, creq: __CReq, cres: __CRes| { - let uri = format!("http://{}{}", addr, creq.uri); - let mut req = Request::builder() - .method(creq.method) - .uri(uri) - //.headers(creq.headers) - .body(creq.body.into()) - .expect("Request::build"); - *req.headers_mut() = creq.headers; - let cstatus = cres.status; - let cheaders = cres.headers; - let cbody = cres.body; - - client.request(req) - .and_then(move |res| { - assert_eq!(res.status(), cstatus, "server status"); - assert_eq!(res.version(), version, "server version"); - for func in &cheaders { - func(&res.headers()); - } - concat(res.into_body()) - }) - .map_ok(move |body| { - assert_eq!(body.as_ref(), cbody.as_slice(), "server body"); - }) - .map(|res| res.expect("client error")) - }); - + let make_request = Arc::new( + move |client: &Client, creq: __CReq, cres: __CRes| { + let uri = format!("http://{}{}", addr, creq.uri); + let mut req = Request::builder() + .method(creq.method) + .uri(uri) + //.headers(creq.headers) + .body(creq.body.into()) + .expect("Request::build"); + *req.headers_mut() = creq.headers; + let cstatus = cres.status; + let cheaders = cres.headers; + let cbody = cres.body; + + client + .request(req) + .and_then(move |res| { + assert_eq!(res.status(), cstatus, "server status"); + assert_eq!(res.version(), version, "server version"); + for func in &cheaders { + func(&res.headers()); + } + concat(res.into_body()) + }) + .map_ok(move |body| { + assert_eq!(body.as_ref(), cbody.as_slice(), "server body"); + }) + .map(|res| res.expect("client error")) + }, + ); let client_futures: Pin + Send>> = if cfg.parallel { let mut client_futures = vec![]; @@ -425,17 +427,14 @@ async fn async_test(cfg: __TestConfig) { drop(client); Box::pin(future::join_all(client_futures).map(|_| ())) } else { - let mut client_futures: Pin> + Send>> = + let mut client_futures: Pin> + Send>> = Box::pin(future::ready(client)); for (creq, cres) in cfg.client_msgs { let mk_request = make_request.clone(); - client_futures = Box::pin( - client_futures - .then(move |client| { - let fut = mk_request(&client, creq, cres); - fut.map(move |()| client) - }) - ); + client_futures = Box::pin(client_futures.then(move |client| { + let fut = mk_request(&client, creq, cres); + fut.map(move |()| client) + })); } Box::pin(client_futures.map(|_| ())) }; @@ -459,19 +458,18 @@ fn naive_proxy(cfg: ProxyConfig) -> (SocketAddr, impl Future) { let max_connections = cfg.connections; let counter = AtomicUsize::new(0); - let srv = Server::bind(&([127, 0, 0, 1], 0).into()) - .serve(make_service_fn(move |_| { - let prev = counter.fetch_add(1, Ordering::Relaxed); - assert!(max_connections >= prev + 1, "proxy max connections"); - let client = client.clone(); - future::ok::<_, hyper::Error>(service_fn(move |mut req| { - let uri = format!("http://{}{}", dst_addr, req.uri().path()) - .parse() - .expect("proxy new uri parse"); - *req.uri_mut() = uri; - client.request(req) - })) - })); + let srv = Server::bind(&([127, 0, 0, 1], 0).into()).serve(make_service_fn(move |_| { + let prev = counter.fetch_add(1, Ordering::Relaxed); + assert!(max_connections >= prev + 1, "proxy max connections"); + let client = client.clone(); + future::ok::<_, hyper::Error>(service_fn(move |mut req| { + let uri = format!("http://{}{}", dst_addr, req.uri().path()) + .parse() + .expect("proxy new uri parse"); + *req.uri_mut() = uri; + client.request(req) + })) + })); let proxy_addr = srv.local_addr(); (proxy_addr, srv.map(|res| res.expect("proxy error"))) }