Skip to content

Commit c5e9490

Browse files
committed
feat(server): re-design Server as higher-level API
The `hyper::Server` is now a proper higher-level API for running HTTP servers. There is a related `hyper::server::Builder` type, to construct a `Server`. All other types (`Http`, `Serve`, etc) were moved into the "lower-level" `hyper::server::conn` module. The `Server` is a `Future` representing a listening HTTP server. Options needed to build one are set on the `Builder`. As `Server` is just a `Future`, it no longer owns a thread-blocking executor, and can thus be run next to other servers, clients, or what-have-you. Closes #1322 Closes #1263 BREAKING CHANGE: The `Server` is no longer created from `Http::bind`, nor is it `run`. It is a `Future` that must be polled by an `Executor`. The `hyper::server::Http` type has move to `hyper::server::conn::Http`.
1 parent b0f4485 commit c5e9490

File tree

14 files changed

+760
-812
lines changed

14 files changed

+760
-812
lines changed

examples/hello.rs

+9-10
Original file line numberDiff line numberDiff line change
@@ -5,29 +5,28 @@ 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+
.expect("bind to address")
26+
.serve(new_service)
27+
.map_err(|e| eprintln!("server error: {}", e));
2928

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

examples/multi_server.rs

+16-16
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,25 @@ 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+
.expect("binding to address")
50+
.serve(|| Ok(Srv(INDEX1)))
51+
.map_err(|e| eprintln!("server 1 error: {}", e));
4952

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

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

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

6363
Ok(())
6464
}));

examples/params.rs

+9-8
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,13 @@ 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+
.expect("binding to address")
103+
.serve(|| Ok(ParamExample))
104+
.map_err(|e| eprintln!("server error: {}", e));
105+
106+
tokio::run(server);
106107
}

examples/send_file.rs

+10-7
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,15 @@ 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+
.expect("bind to address")
145+
.serve(|| Ok(ResponseExamples))
146+
.map_err(|e| eprintln!("server error: {}", e));
147+
148+
println!("Listening on http://{}", addr);
149+
150+
tokio::run(server);
148151
}

examples/server.rs

+12-8
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,15 @@ 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+
.expect("bind to address")
49+
.serve(|| Ok(Echo))
50+
.map_err(|e| eprintln!("server error: {}", e));
51+
52+
println!("Listening on http://{}", addr);
53+
54+
tokio::run(server);
5155
}

examples/web_api.rs

+9-6
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,18 @@ 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+
.expect("bind to address")
85+
.serve(move || Ok(ResponseExamples(client.clone())))
86+
.map_err(|e| eprintln!("server error: {}", e));
87+
88+
println!("Listening on http://{}", addr);
8489

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

src/error.rs

+4-4
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

+13-2
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)