Skip to content

Commit

Permalink
feat(lib): replace types with those from http crate
Browse files Browse the repository at this point in the history
BREAKING CHANGE: `Method`, `Request`, `Response`, `StatusCode`,
  `Version`, and `Uri` have been replaced with types from the `http`
  crate. The `hyper::header` module is gone for now.

  Removed `Client::get`, since it needed to construct a `Request<B>`
  with an empty body. Just use `Client::request` instead.

  Removed `compat` cargo feature, and `compat` related API.
  • Loading branch information
seanmonstar committed Mar 19, 2018
1 parent a37e6b5 commit 3cd48b4
Show file tree
Hide file tree
Showing 109 changed files with 1,005 additions and 14,412 deletions.
4 changes: 0 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@ matrix:
- rust: beta
- rust: stable
env: HYPER_DOCS=1
- rust: stable
env: FEATURES="--no-default-features"
- rust: stable
env: FEATURES="--features compat"
- rust: 1.21.0

cache:
Expand Down
5 changes: 1 addition & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ base64 = "0.9"
bytes = "0.4.4"
futures = "0.1.17"
futures-cpupool = "0.1.6"
http = { version = "0.1", optional = true }
http = "0.1.5"
httparse = "1.0"
iovec = "0.1"
language-tags = "0.2"
Expand All @@ -46,7 +46,4 @@ spmc = "0.2"
url = "1.0"

[features]
default = []
nightly = []
raw_status = []
compat = [ "http" ]
27 changes: 11 additions & 16 deletions benches/end_to_end.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ use futures::{Future, Stream};
use tokio_core::reactor::{Core, Handle};
use tokio_core::net::TcpListener;

use hyper::client;
use hyper::header::{ContentLength, ContentType};
use hyper::Method;
use hyper::{Body, Method, Request, Response};


#[bench]
Expand All @@ -30,7 +28,7 @@ fn get_one_at_a_time(b: &mut test::Bencher) {
b.bytes = 160 * 2 + PHRASE.len() as u64;
b.iter(move || {
let work = client.get(url.clone()).and_then(|res| {
res.body().for_each(|_chunk| {
res.into_body().into_stream().for_each(|_chunk| {
Ok(())
})
});
Expand All @@ -54,12 +52,11 @@ fn post_one_at_a_time(b: &mut test::Bencher) {
let post = "foo bar baz quux";
b.bytes = 180 * 2 + post.len() as u64 + PHRASE.len() as u64;
b.iter(move || {
let mut req = client::Request::new(Method::Post, url.clone());
req.headers_mut().set(ContentLength(post.len() as u64));
req.set_body(post);

let mut req = Request::new(post.into());
*req.method_mut() = Method::POST;
*req.uri_mut() = url.clone();
let work = client.request(req).and_then(|res| {
res.body().for_each(|_chunk| {
res.into_body().into_stream().for_each(|_chunk| {
Ok(())
})
});
Expand All @@ -71,22 +68,20 @@ fn post_one_at_a_time(b: &mut test::Bencher) {
static PHRASE: &'static [u8] = include_bytes!("../CHANGELOG.md"); //b"Hello, World!";

fn spawn_hello(handle: &Handle) -> SocketAddr {
use hyper::server::{const_service, service_fn, NewService, Request, Response};
use hyper::server::{const_service, service_fn, NewService};
let addr = "127.0.0.1:0".parse().unwrap();
let listener = TcpListener::bind(&addr, handle).unwrap();
let addr = listener.local_addr().unwrap();

let handle2 = handle.clone();
let http = hyper::server::Http::<hyper::Chunk>::new();

let service = const_service(service_fn(|req: Request| {
req.body()
let service = const_service(service_fn(|req: Request<Body>| {
req.into_body()
.into_stream()
.concat2()
.map(|_| {
Response::<hyper::Body>::new()
.with_header(ContentLength(PHRASE.len() as u64))
.with_header(ContentType::plaintext())
.with_body(PHRASE)
Response::new(Body::from(PHRASE))
})
}));

Expand Down
42 changes: 21 additions & 21 deletions benches/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ use std::io::{Read, Write};
use std::net::{TcpListener, TcpStream};
use std::sync::mpsc;

use futures::{future, stream, Future};
use futures::{future, stream, Future, Stream};
use futures::sync::oneshot;

use hyper::header::{ContentLength, ContentType, TransferEncoding};
use hyper::server::{self, Service};
use hyper::{Body, Request, Response};
use hyper::server::Service;

macro_rules! bench_server {
($b:ident, $header:expr, $body:expr) => ({
Expand Down Expand Up @@ -65,37 +65,37 @@ fn body(b: &'static [u8]) -> hyper::Body {

#[bench]
fn throughput_fixedsize_small_payload(b: &mut test::Bencher) {
bench_server!(b, ContentLength(13), || body(b"Hello, World!"))
bench_server!(b, ("content-length", "13"), || body(b"Hello, World!"))
}

#[bench]
fn throughput_fixedsize_large_payload(b: &mut test::Bencher) {
bench_server!(b, ContentLength(1_000_000), || body(&[b'x'; 1_000_000]))
bench_server!(b, ("content-length", "1000000"), || body(&[b'x'; 1_000_000]))
}

#[bench]
fn throughput_fixedsize_many_chunks(b: &mut test::Bencher) {
bench_server!(b, ContentLength(1_000_000), || {
bench_server!(b, ("content-length", "1000000"), || {
static S: &'static [&'static [u8]] = &[&[b'x'; 1_000] as &[u8]; 1_000] as _;
stream::iter_ok(S.iter())
Body::wrap_stream(stream::iter_ok(S.iter()).map(|&s| s))
})
}

#[bench]
fn throughput_chunked_small_payload(b: &mut test::Bencher) {
bench_server!(b, TransferEncoding::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, TransferEncoding::chunked(), || body(&[b'x'; 1_000_000]))
bench_server!(b, ("transfer-encoding", "chunked"), || body(&[b'x'; 1_000_000]))
}

#[bench]
fn throughput_chunked_many_chunks(b: &mut test::Bencher) {
bench_server!(b, TransferEncoding::chunked(), || {
bench_server!(b, ("transfer-encoding", "chunked"), || {
static S: &'static [&'static [u8]] = &[&[b'x'; 1_000] as &[u8]; 1_000] as _;
stream::iter_ok(S.iter())
Body::wrap_stream(stream::iter_ok(S.iter()).map(|&s| s))
})
}

Expand Down Expand Up @@ -177,26 +177,26 @@ fn raw_tcp_throughput_large_payload(b: &mut test::Bencher) {
tx.send(()).unwrap();
}

struct BenchPayload<H, F> {
header: H,
struct BenchPayload<F> {
header: (&'static str, &'static str),
body: F,
}

impl<H, F, B> Service for BenchPayload<H, F>
impl<F, B> Service for BenchPayload<F>
where
H: hyper::header::Header + Clone,
F: Fn() -> B,
{
type Request = server::Request;
type Response = server::Response<B>;
type Request = Request<Body>;
type Response = Response<B>;
type Error = hyper::Error;
type Future = future::FutureResult<Self::Response, hyper::Error>;
fn call(&self, _req: Self::Request) -> Self::Future {
future::ok(
server::Response::new()
.with_header(self.header.clone())
.with_header(ContentType::plaintext())
.with_body((self.body)())
Response::builder()
.header(self.header.0, self.header.1)
.header("content-type", "text/plain")
.body((self.body)())
.unwrap()
)
}
}
12 changes: 7 additions & 5 deletions examples/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use std::io::{self, Write};
use futures::Future;
use futures::stream::Stream;

use hyper::Client;
use hyper::{Body, Client, Request};

fn main() {
pretty_env_logger::init();
Expand All @@ -25,7 +25,7 @@ fn main() {
};

let url = url.parse::<hyper::Uri>().unwrap();
if url.scheme() != Some("http") {
if url.scheme_part().map(|s| s.as_ref()) != Some("http") {
println!("This example only works with 'http' URLs.");
return;
}
Expand All @@ -34,11 +34,13 @@ fn main() {
let handle = core.handle();
let client = Client::new(&handle);

let work = client.get(url).and_then(|res| {
let mut req = Request::new(Body::empty());
*req.uri_mut() = url;
let work = client.request(req).and_then(|res| {
println!("Response: {}", res.status());
println!("Headers: \n{}", res.headers());
println!("Headers: {:#?}", res.headers());

res.body().for_each(|chunk| {
res.into_parts().1.for_each(|chunk| {
io::stdout().write_all(&chunk).map_err(From::from)
})
}).map(|_| {
Expand Down
9 changes: 3 additions & 6 deletions examples/hello.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ extern crate hyper;
extern crate futures;
extern crate pretty_env_logger;

use hyper::header::{ContentLength, ContentType};
use hyper::server::{Http, Response, const_service, service_fn};
use hyper::{Body, Response};
use hyper::server::{Http, const_service, service_fn};

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

Expand All @@ -13,10 +13,7 @@ fn main() {
let addr = ([127, 0, 0, 1], 3000).into();

let new_service = const_service(service_fn(|_| {
Ok(Response::<hyper::Body>::new()
.with_header(ContentLength(PHRASE.len() as u64))
.with_header(ContentType::plaintext())
.with_body(PHRASE))
Ok(Response::new(Body::from(PHRASE)))
}));

let server = Http::new()
Expand Down
27 changes: 13 additions & 14 deletions examples/multi_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,31 @@ extern crate pretty_env_logger;
use futures::{Future, Stream};
use futures::future::FutureResult;

use hyper::{Get, StatusCode};
use hyper::{Body, Method, Request, Response, StatusCode};
use tokio_core::reactor::Core;
use hyper::header::ContentLength;
use hyper::server::{Http, Service, Request, Response};
use hyper::server::{Http, Service};

static INDEX1: &'static [u8] = b"The 1st service!";
static INDEX2: &'static [u8] = b"The 2nd service!";

struct Srv(&'static [u8]);

impl Service for Srv {
type Request = Request;
type Response = Response;
type Request = Request<Body>;
type Response = Response<Body>;
type Error = hyper::Error;
type Future = FutureResult<Response, hyper::Error>;
type Future = FutureResult<Response<Body>, hyper::Error>;

fn call(&self, req: Request) -> Self::Future {
futures::future::ok(match (req.method(), req.path()) {
(&Get, "/") => {
Response::new()
.with_header(ContentLength(self.0.len() as u64))
.with_body(self.0)
fn call(&self, req: Request<Body>) -> Self::Future {
futures::future::ok(match (req.method(), req.uri().path()) {
(&Method::GET, "/") => {
Response::new(self.0.into())
},
_ => {
Response::new()
.with_status(StatusCode::NotFound)
Response::builder()
.status(StatusCode::NOT_FOUND)
.body(Body::empty())
.unwrap()
}
})
}
Expand Down
57 changes: 27 additions & 30 deletions examples/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ extern crate url;

use futures::{Future, Stream};

use hyper::{Get, Post, StatusCode};
use hyper::header::ContentLength;
use hyper::server::{Http, Service, Request, Response};
use hyper::{Body, Method, Request, Response, StatusCode};
use hyper::server::{Http, Service};

use std::collections::HashMap;
use url::form_urlencoded;
Expand All @@ -20,20 +19,18 @@ static NOTNUMERIC: &[u8] = b"Number field is not numeric";
struct ParamExample;

impl Service for ParamExample {
type Request = Request;
type Response = Response;
type Request = Request<Body>;
type Response = Response<Body>;
type Error = hyper::Error;
type Future = Box<Future<Item = Self::Response, Error = Self::Error>>;

fn call(&self, req: Request) -> Self::Future {
match (req.method(), req.path()) {
(&Get, "/") | (&Get, "/post") => {
Box::new(futures::future::ok(Response::new()
.with_header(ContentLength(INDEX.len() as u64))
.with_body(INDEX)))
fn call(&self, req: Request<Body>) -> Self::Future {
match (req.method(), req.uri().path()) {
(&Method::GET, "/") | (&Method::GET, "/post") => {
Box::new(futures::future::ok(Response::new(INDEX.into())))
},
(&Post, "/post") => {
Box::new(req.body().concat2().map(|b| {
(&Method::POST, "/post") => {
Box::new(req.into_parts().1.concat2().map(|b| {
// Parse the request body. form_urlencoded::parse
// always succeeds, but in general parsing may
// fail (for example, an invalid post of json), so
Expand All @@ -52,25 +49,25 @@ impl Service for ParamExample {
let name = if let Some(n) = params.get("name") {
n
} else {
return Response::new()
.with_status(StatusCode::UnprocessableEntity)
.with_header(ContentLength(MISSING.len() as u64))
.with_body(MISSING);
return Response::builder()
.status(StatusCode::UNPROCESSABLE_ENTITY)
.body(MISSING.into())
.unwrap();
};
let number = if let Some(n) = params.get("number") {
if let Ok(v) = n.parse::<f64>() {
v
} else {
return Response::new()
.with_status(StatusCode::UnprocessableEntity)
.with_header(ContentLength(NOTNUMERIC.len() as u64))
.with_body(NOTNUMERIC);
return Response::builder()
.status(StatusCode::UNPROCESSABLE_ENTITY)
.body(NOTNUMERIC.into())
.unwrap();
}
} else {
return Response::new()
.with_status(StatusCode::UnprocessableEntity)
.with_header(ContentLength(MISSING.len() as u64))
.with_body(MISSING);
return Response::builder()
.status(StatusCode::UNPROCESSABLE_ENTITY)
.body(MISSING.into())
.unwrap();
};

// Render the response. This will often involve
Expand All @@ -80,14 +77,14 @@ impl Service for ParamExample {
// responses such as InternalServiceError may be
// needed here, too.
let body = format!("Hello {}, your number is {}", name, number);
Response::new()
.with_header(ContentLength(body.len() as u64))
.with_body(body)
Response::new(body.into())
}))
},
_ => {
Box::new(futures::future::ok(Response::new()
.with_status(StatusCode::NotFound)))
Box::new(futures::future::ok(Response::builder()
.status(StatusCode::NOT_FOUND)
.body(Body::empty())
.unwrap()))
}
}
}
Expand Down
Loading

0 comments on commit 3cd48b4

Please sign in to comment.