Skip to content

Commit 71a15c2

Browse files
authored
Merge pull request #1488 from hyperium/server2
feat(server): re-design `Server` as higher-level API
2 parents 35c38cb + c497450 commit 71a15c2

File tree

16 files changed

+790
-825
lines changed

16 files changed

+790
-825
lines changed

benches/end_to_end.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,19 @@ use tokio::runtime::Runtime;
1313
use tokio::net::TcpListener;
1414

1515
use hyper::{Body, Method, Request, Response};
16-
use hyper::server::Http;
16+
use hyper::client::HttpConnector;
17+
use hyper::server::conn::Http;
1718

1819

1920
#[bench]
2021
fn get_one_at_a_time(b: &mut test::Bencher) {
2122
let mut rt = Runtime::new().unwrap();
2223
let addr = spawn_hello(&mut rt);
2324

24-
let client = hyper::Client::configure()
25-
.build_with_executor(&rt.reactor(), rt.executor());
25+
let connector = HttpConnector::new_with_handle(1, rt.reactor().clone());
26+
let client = hyper::Client::builder()
27+
.executor(rt.executor())
28+
.build::<_, Body>(connector);
2629

2730
let url: hyper::Uri = format!("http://{}/get", addr).parse().unwrap();
2831

@@ -43,8 +46,10 @@ fn post_one_at_a_time(b: &mut test::Bencher) {
4346
let mut rt = Runtime::new().unwrap();
4447
let addr = spawn_hello(&mut rt);
4548

46-
let client = hyper::Client::configure()
47-
.build_with_executor(&rt.reactor(), rt.executor());
49+
let connector = HttpConnector::new_with_handle(1, rt.reactor().clone());
50+
let client = hyper::Client::builder()
51+
.executor(rt.executor())
52+
.build::<_, Body>(connector);
4853

4954
let url: hyper::Uri = format!("http://{}/post", addr).parse().unwrap();
5055

@@ -71,7 +76,7 @@ fn spawn_hello(rt: &mut Runtime) -> SocketAddr {
7176
let listener = TcpListener::bind(&addr).unwrap();
7277
let addr = listener.local_addr().unwrap();
7378

74-
let http = Http::<hyper::Chunk>::new();
79+
let http = Http::new();
7580

7681
let service = const_service(service_fn(|req: Request<Body>| {
7782
req.into_body()
@@ -81,6 +86,7 @@ fn spawn_hello(rt: &mut Runtime) -> SocketAddr {
8186
})
8287
}));
8388

89+
// Specifically only accept 1 connection.
8490
let srv = listener.incoming()
8591
.into_future()
8692
.map_err(|(e, _inc)| panic!("accept error: {}", e))

benches/server.rs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,28 @@ use std::sync::mpsc;
1414
use futures::{future, stream, Future, Stream};
1515
use futures::sync::oneshot;
1616

17-
use hyper::{Body, Request, Response};
17+
use hyper::{Body, Request, Response, Server};
1818
use hyper::server::Service;
1919

2020
macro_rules! bench_server {
2121
($b:ident, $header:expr, $body:expr) => ({
2222
let _ = pretty_env_logger::try_init();
23-
let (_until_tx, until_rx) = oneshot::channel();
23+
let (_until_tx, until_rx) = oneshot::channel::<()>();
2424
let addr = {
2525
let (addr_tx, addr_rx) = mpsc::channel();
2626
::std::thread::spawn(move || {
2727
let addr = "127.0.0.1:0".parse().unwrap();
28-
let srv = hyper::server::Http::new().bind(&addr, || Ok(BenchPayload {
29-
header: $header,
30-
body: $body,
31-
})).unwrap();
32-
let addr = srv.local_addr().unwrap();
33-
addr_tx.send(addr).unwrap();
34-
tokio::run(srv.run_until(until_rx.map_err(|_| ())).map_err(|e| panic!("server error: {}", e)));
28+
let srv = Server::bind(&addr)
29+
.serve(|| Ok(BenchPayload {
30+
header: $header,
31+
body: $body,
32+
}));
33+
addr_tx.send(srv.local_addr()).unwrap();
34+
let fut = srv
35+
.map_err(|e| panic!("server error: {}", e))
36+
.select(until_rx.then(|_| Ok(())))
37+
.then(|_| Ok(()));
38+
tokio::run(fut);
3539
});
3640

3741
addr_rx.recv().unwrap()

examples/hello.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,29 +5,27 @@ extern crate pretty_env_logger;
55
extern crate tokio;
66

77
use futures::Future;
8-
use futures::future::lazy;
98

109
use hyper::{Body, Response};
11-
use hyper::server::{Http, const_service, service_fn};
10+
use hyper::server::{Server, const_service, service_fn};
1211

1312
static PHRASE: &'static [u8] = b"Hello World!";
1413

1514
fn main() {
1615
pretty_env_logger::init();
16+
1717
let addr = ([127, 0, 0, 1], 3000).into();
1818

1919
let new_service = const_service(service_fn(|_| {
2020
//TODO: when `!` is stable, replace error type
2121
Ok::<_, hyper::Error>(Response::new(Body::from(PHRASE)))
2222
}));
2323

24-
tokio::run(lazy(move || {
25-
let server = Http::new()
26-
.sleep_on_errors(true)
27-
.bind(&addr, new_service)
28-
.unwrap();
24+
let server = Server::bind(&addr)
25+
.serve(new_service)
26+
.map_err(|e| eprintln!("server error: {}", e));
2927

30-
println!("Listening on http://{} with 1 thread.", server.local_addr().unwrap());
31-
server.run().map_err(|err| eprintln!("Server error {}", err))
32-
}));
28+
println!("Listening on http://{}", addr);
29+
30+
tokio::run(server);
3331
}

examples/multi_server.rs

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ extern crate futures;
44
extern crate pretty_env_logger;
55
extern crate tokio;
66

7-
use futures::{Future, Stream};
7+
use futures::{Future};
88
use futures::future::{FutureResult, lazy};
99

1010
use hyper::{Body, Method, Request, Response, StatusCode};
11-
use hyper::server::{Http, Service};
11+
use hyper::server::{Server, Service};
1212

1313
static INDEX1: &'static [u8] = b"The 1st service!";
1414
static INDEX2: &'static [u8] = b"The 2nd service!";
@@ -40,25 +40,23 @@ impl Service for Srv {
4040

4141
fn main() {
4242
pretty_env_logger::init();
43-
let addr1 = "127.0.0.1:1337".parse().unwrap();
44-
let addr2 = "127.0.0.1:1338".parse().unwrap();
43+
44+
let addr1 = ([127, 0, 0, 1], 1337).into();
45+
let addr2 = ([127, 0, 0, 1], 1338).into();
4546

4647
tokio::run(lazy(move || {
47-
let srv1 = Http::new().serve_addr(&addr1, || Ok(Srv(INDEX1))).unwrap();
48-
let srv2 = Http::new().serve_addr(&addr2, || Ok(Srv(INDEX2))).unwrap();
48+
let srv1 = Server::bind(&addr1)
49+
.serve(|| Ok(Srv(INDEX1)))
50+
.map_err(|e| eprintln!("server 1 error: {}", e));
4951

50-
println!("Listening on http://{}", srv1.incoming_ref().local_addr());
51-
println!("Listening on http://{}", srv2.incoming_ref().local_addr());
52+
let srv2 = Server::bind(&addr2)
53+
.serve(|| Ok(Srv(INDEX2)))
54+
.map_err(|e| eprintln!("server 2 error: {}", e));
5255

53-
tokio::spawn(srv1.for_each(move |conn| {
54-
tokio::spawn(conn.map_err(|err| println!("srv1 error: {:?}", err)));
55-
Ok(())
56-
}).map_err(|_| ()));
56+
println!("Listening on http://{} and http://{}", addr1, addr2);
5757

58-
tokio::spawn(srv2.for_each(move |conn| {
59-
tokio::spawn(conn.map_err(|err| println!("srv2 error: {:?}", err)));
60-
Ok(())
61-
}).map_err(|_| ()));
58+
tokio::spawn(srv1);
59+
tokio::spawn(srv2);
6260

6361
Ok(())
6462
}));

examples/params.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,9 @@ extern crate tokio;
66
extern crate url;
77

88
use futures::{Future, Stream};
9-
use futures::future::lazy;
109

1110
use hyper::{Body, Method, Request, Response, StatusCode};
12-
use hyper::server::{Http, Service};
11+
use hyper::server::{Server, Service};
1312

1413
use std::collections::HashMap;
1514
use url::form_urlencoded;
@@ -96,11 +95,12 @@ impl Service for ParamExample {
9695

9796
fn main() {
9897
pretty_env_logger::init();
99-
let addr = "127.0.0.1:1337".parse().unwrap();
10098

101-
tokio::run(lazy(move || {
102-
let server = Http::new().bind(&addr, || Ok(ParamExample)).unwrap();
103-
println!("Listening on http://{} with 1 thread.", server.local_addr().unwrap());
104-
server.run().map_err(|err| eprintln!("Server error {}", err))
105-
}));
99+
let addr = ([127, 0, 0, 1], 1337).into();
100+
101+
let server = Server::bind(&addr)
102+
.serve(|| Ok(ParamExample))
103+
.map_err(|e| eprintln!("server error: {}", e));
104+
105+
tokio::run(server);
106106
}

examples/send_file.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@ extern crate pretty_env_logger;
55
extern crate tokio;
66

77
use futures::{Future/*, Sink*/};
8-
use futures::future::lazy;
98
use futures::sync::oneshot;
109

1110
use hyper::{Body, /*Chunk,*/ Method, Request, Response, StatusCode};
12-
use hyper::server::{Http, Service};
11+
use hyper::server::{Server, Service};
1312

1413
use std::fs::File;
1514
use std::io::{self, copy/*, Read*/};
@@ -138,11 +137,14 @@ impl Service for ResponseExamples {
138137

139138
fn main() {
140139
pretty_env_logger::init();
140+
141141
let addr = "127.0.0.1:1337".parse().unwrap();
142142

143-
tokio::run(lazy(move || {
144-
let server = Http::new().bind(&addr, || Ok(ResponseExamples)).unwrap();
145-
println!("Listening on http://{} with 1 thread.", server.local_addr().unwrap());
146-
server.run().map_err(|err| eprintln!("Server error {}", err))
147-
}));
143+
let server = Server::bind(&addr)
144+
.serve(|| Ok(ResponseExamples))
145+
.map_err(|e| eprintln!("server error: {}", e));
146+
147+
println!("Listening on http://{}", addr);
148+
149+
tokio::run(server);
148150
}

examples/server.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ extern crate pretty_env_logger;
55
extern crate tokio;
66

77
use futures::Future;
8-
use futures::future::{FutureResult, lazy};
8+
use futures::future::{FutureResult};
99

1010
use hyper::{Body, Method, Request, Response, StatusCode};
11-
use hyper::server::{Http, Service};
11+
use hyper::server::{Server, Service};
1212

1313
static INDEX: &'static [u8] = b"Try POST /echo";
1414

@@ -41,11 +41,14 @@ impl Service for Echo {
4141

4242
fn main() {
4343
pretty_env_logger::init();
44-
let addr = "127.0.0.1:1337".parse().unwrap();
4544

46-
tokio::run(lazy(move || {
47-
let server = Http::new().bind(&addr, || Ok(Echo)).unwrap();
48-
println!("Listening on http://{} with 1 thread.", server.local_addr().unwrap());
49-
server.run().map_err(|err| eprintln!("Server error {}", err))
50-
}));
45+
let addr = ([127, 0, 0, 1], 1337).into();
46+
47+
let server = Server::bind(&addr)
48+
.serve(|| Ok(Echo))
49+
.map_err(|e| eprintln!("server error: {}", e));
50+
51+
println!("Listening on http://{}", addr);
52+
53+
tokio::run(server);
5154
}

examples/web_api.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use futures::future::lazy;
99

1010
use hyper::{Body, Chunk, Client, Method, Request, Response, StatusCode};
1111
use hyper::client::HttpConnector;
12-
use hyper::server::{Http, Service};
12+
use hyper::server::{Server, Service};
1313

1414
#[allow(unused, deprecated)]
1515
use std::ascii::AsciiExt;
@@ -75,15 +75,17 @@ impl Service for ResponseExamples {
7575

7676
fn main() {
7777
pretty_env_logger::init();
78+
7879
let addr = "127.0.0.1:1337".parse().unwrap();
7980

8081
tokio::run(lazy(move || {
8182
let client = Client::new();
82-
let serve = Http::new().serve_addr(&addr, move || Ok(ResponseExamples(client.clone()))).unwrap();
83-
println!("Listening on http://{} with 1 thread.", serve.incoming_ref().local_addr());
83+
let server = Server::bind(&addr)
84+
.serve(move || Ok(ResponseExamples(client.clone())))
85+
.map_err(|e| eprintln!("server error: {}", e));
86+
87+
println!("Listening on http://{}", addr);
8488

85-
serve.map_err(|_| ()).for_each(move |conn| {
86-
tokio::spawn(conn.map_err(|err| println!("serve error: {:?}", err)))
87-
})
89+
server
8890
}));
8991
}

src/error.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,12 +171,12 @@ impl Error {
171171
Error::new(Kind::Io, Some(cause.into()))
172172
}
173173

174-
pub(crate) fn new_listen(err: io::Error) -> Error {
175-
Error::new(Kind::Listen, Some(err.into()))
174+
pub(crate) fn new_listen<E: Into<Cause>>(cause: E) -> Error {
175+
Error::new(Kind::Listen, Some(cause.into()))
176176
}
177177

178-
pub(crate) fn new_accept(err: io::Error) -> Error {
179-
Error::new(Kind::Accept, Some(Box::new(err)))
178+
pub(crate) fn new_accept<E: Into<Cause>>(cause: E) -> Error {
179+
Error::new(Kind::Accept, Some(cause.into()))
180180
}
181181

182182
pub(crate) fn new_connect<E: Into<Cause>>(cause: E) -> Error {

src/proto/h1/io.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,19 @@ use tokio_io::{AsyncRead, AsyncWrite};
1010

1111
use proto::{Http1Transaction, MessageHead};
1212

13-
const INIT_BUFFER_SIZE: usize = 8192;
14-
pub const DEFAULT_MAX_BUFFER_SIZE: usize = 8192 + 4096 * 100;
13+
/// The initial buffer size allocated before trying to read from IO.
14+
pub(crate) const INIT_BUFFER_SIZE: usize = 8192;
15+
16+
/// The default maximum read buffer size. If the buffer gets this big and
17+
/// a message is still not complete, a `TooLarge` error is triggered.
18+
// Note: if this changes, update server::conn::Http::max_buf_size docs.
19+
pub(crate) const DEFAULT_MAX_BUFFER_SIZE: usize = 8192 + 4096 * 100;
20+
21+
/// The maximum number of distinct `Buf`s to hold in a list before requiring
22+
/// a flush. Only affects when the buffer strategy is to queue buffers.
23+
///
24+
/// Note that a flush can happen before reaching the maximum. This simply
25+
/// forces a flush if the queue gets this big.
1526
const MAX_BUF_LIST_BUFFERS: usize = 16;
1627

1728
pub struct Buffered<T, B> {

0 commit comments

Comments
 (0)