Skip to content

Commit 0892cb2

Browse files
committed
feat(client): replace default dispatcher
1 parent 6fde13f commit 0892cb2

File tree

3 files changed

+58
-201
lines changed

3 files changed

+58
-201
lines changed

examples/client.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,7 @@ fn main() {
3232

3333
let mut core = tokio_core::reactor::Core::new().unwrap();
3434
let handle = core.handle();
35-
let client = Client::configure()
36-
.no_proto()
37-
.build(&handle);
35+
let client = Client::new(&handle);
3836

3937
let work = client.get(url).and_then(|res| {
4038
println!("Response: {}", res.status());

src/client/mod.rs

+55-177
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,17 @@ use std::marker::PhantomData;
77
use std::rc::Rc;
88
use std::time::Duration;
99

10-
use futures::{future, Poll, Async, Future, Stream};
11-
use futures::unsync::oneshot;
10+
use futures::{future, Poll, Future, Stream};
1211
#[cfg(feature = "compat")]
1312
use http;
14-
use tokio_io::{AsyncRead, AsyncWrite};
1513
use tokio::reactor::Handle;
16-
use tokio_proto::BindClient;
17-
use tokio_proto::streaming::Message;
18-
use tokio_proto::streaming::pipeline::ClientProto;
19-
use tokio_proto::util::client_proxy::ClientProxy;
2014
pub use tokio_service::Service;
2115

2216
use header::{Headers, Host};
23-
use proto::{self, RequestHead, TokioBody};
24-
use proto::response;
17+
use proto;
2518
use proto::request;
2619
use method::Method;
27-
use self::pool::{Pool, Pooled};
20+
use self::pool::Pool;
2821
use uri::{self, Uri};
2922
use version::HttpVersion;
3023

@@ -45,7 +38,7 @@ pub mod compat;
4538
pub struct Client<C, B = proto::Body> {
4639
connector: C,
4740
handle: Handle,
48-
pool: Dispatch<B>,
41+
pool: Pool<HyperClient<B>>,
4942
}
5043

5144
impl Client<HttpConnector, proto::Body> {
@@ -93,11 +86,7 @@ impl<C, B> Client<C, B> {
9386
Client {
9487
connector: config.connector,
9588
handle: handle.clone(),
96-
pool: if config.no_proto {
97-
Dispatch::Hyper(Pool::new(config.keep_alive, config.keep_alive_timeout))
98-
} else {
99-
Dispatch::Proto(Pool::new(config.keep_alive, config.keep_alive_timeout))
100-
}
89+
pool: Pool::new(config.keep_alive, config.keep_alive_timeout)
10190
}
10291
}
10392
}
@@ -191,105 +180,54 @@ where C: Connect,
191180
headers.extend(head.headers.iter());
192181
head.headers = headers;
193182

194-
match self.pool {
195-
Dispatch::Proto(ref pool) => {
196-
trace!("proto_dispatch");
197-
let checkout = pool.checkout(domain.as_ref());
198-
let connect = {
199-
let handle = self.handle.clone();
200-
let pool = pool.clone();
201-
let pool_key = Rc::new(domain.to_string());
202-
self.connector.connect(url)
203-
.map(move |io| {
204-
let (tx, rx) = oneshot::channel();
205-
let client = HttpClient {
206-
client_rx: RefCell::new(Some(rx)),
207-
}.bind_client(&handle, io);
208-
let pooled = pool.pooled(pool_key, client);
209-
drop(tx.send(pooled.clone()));
210-
pooled
211-
})
212-
};
213-
214-
let race = checkout.select(connect)
215-
.map(|(client, _work)| client)
216-
.map_err(|(e, _work)| {
217-
// the Pool Checkout cannot error, so the only error
218-
// is from the Connector
219-
// XXX: should wait on the Checkout? Problem is
220-
// that if the connector is failing, it may be that we
221-
// never had a pooled stream at all
222-
e.into()
223-
});
224-
let resp = race.and_then(move |client| {
225-
let msg = match body {
226-
Some(body) => {
227-
Message::WithBody(head, body.into())
228-
},
229-
None => Message::WithoutBody(head),
183+
use futures::Sink;
184+
use futures::sync::{mpsc, oneshot};
185+
186+
let checkout = self.pool.checkout(domain.as_ref());
187+
let connect = {
188+
let handle = self.handle.clone();
189+
let pool = self.pool.clone();
190+
let pool_key = Rc::new(domain.to_string());
191+
self.connector.connect(url)
192+
.map(move |io| {
193+
let (tx, rx) = mpsc::channel(0);
194+
let tx = HyperClient {
195+
tx: RefCell::new(tx),
196+
should_close: true,
230197
};
231-
client.call(msg)
232-
});
233-
FutureResponse(Box::new(resp.map(|msg| {
234-
match msg {
235-
Message::WithoutBody(head) => response::from_wire(head, None),
236-
Message::WithBody(head, body) => response::from_wire(head, Some(body.into())),
237-
}
238-
})))
239-
},
240-
Dispatch::Hyper(ref pool) => {
241-
trace!("no_proto dispatch");
242-
use futures::Sink;
243-
use futures::sync::{mpsc, oneshot};
244-
245-
let checkout = pool.checkout(domain.as_ref());
246-
let connect = {
247-
let handle = self.handle.clone();
248-
let pool = pool.clone();
249-
let pool_key = Rc::new(domain.to_string());
250-
self.connector.connect(url)
251-
.map(move |io| {
252-
let (tx, rx) = mpsc::channel(0);
253-
let tx = HyperClient {
254-
tx: RefCell::new(tx),
255-
should_close: true,
256-
};
257-
let pooled = pool.pooled(pool_key, tx);
258-
let conn = proto::Conn::<_, _, proto::ClientTransaction, _>::new(io, pooled.clone());
259-
let dispatch = proto::dispatch::Dispatcher::new(proto::dispatch::Client::new(rx), conn);
260-
handle.spawn(dispatch.map_err(|err| error!("no_proto error: {}", err)));
261-
pooled
262-
})
263-
};
264-
265-
let race = checkout.select(connect)
266-
.map(|(client, _work)| client)
267-
.map_err(|(e, _work)| {
268-
// the Pool Checkout cannot error, so the only error
269-
// is from the Connector
270-
// XXX: should wait on the Checkout? Problem is
271-
// that if the connector is failing, it may be that we
272-
// never had a pooled stream at all
273-
e.into()
274-
});
275-
276-
let resp = race.and_then(move |mut client| {
277-
let (callback, rx) = oneshot::channel();
278-
client.tx.borrow_mut().start_send(proto::dispatch::ClientMsg::Request(head, body, callback)).unwrap();
279-
client.should_close = false;
280-
rx.then(|res| {
281-
match res {
282-
Ok(Ok(res)) => Ok(res),
283-
Ok(Err(err)) => Err(err),
284-
Err(_) => panic!("dispatch dropped without returning error"),
285-
}
286-
})
287-
});
288-
289-
FutureResponse(Box::new(resp))
198+
let pooled = pool.pooled(pool_key, tx);
199+
let conn = proto::Conn::<_, _, proto::ClientTransaction, _>::new(io, pooled.clone());
200+
let dispatch = proto::dispatch::Dispatcher::new(proto::dispatch::Client::new(rx), conn);
201+
handle.spawn(dispatch.map_err(|err| error!("no_proto error: {}", err)));
202+
pooled
203+
})
204+
};
290205

291-
}
292-
}
206+
let race = checkout.select(connect)
207+
.map(|(client, _work)| client)
208+
.map_err(|(e, _work)| {
209+
// the Pool Checkout cannot error, so the only error
210+
// is from the Connector
211+
// XXX: should wait on the Checkout? Problem is
212+
// that if the connector is failing, it may be that we
213+
// never had a pooled stream at all
214+
e.into()
215+
});
216+
217+
let resp = race.and_then(move |mut client| {
218+
let (callback, rx) = oneshot::channel();
219+
client.tx.borrow_mut().start_send(proto::dispatch::ClientMsg::Request(head, body, callback)).unwrap();
220+
client.should_close = false;
221+
rx.then(|res| {
222+
match res {
223+
Ok(Ok(res)) => Ok(res),
224+
Ok(Err(err)) => Err(err),
225+
Err(_) => panic!("dispatch dropped without returning error"),
226+
}
227+
})
228+
});
229+
230+
FutureResponse(Box::new(resp))
293231
}
294232

295233
}
@@ -299,10 +237,7 @@ impl<C: Clone, B> Clone for Client<C, B> {
299237
Client {
300238
connector: self.connector.clone(),
301239
handle: self.handle.clone(),
302-
pool: match self.pool {
303-
Dispatch::Proto(ref pool) => Dispatch::Proto(pool.clone()),
304-
Dispatch::Hyper(ref pool) => Dispatch::Hyper(pool.clone()),
305-
}
240+
pool: self.pool.clone(),
306241
}
307242
}
308243
}
@@ -313,8 +248,6 @@ impl<C, B> fmt::Debug for Client<C, B> {
313248
}
314249
}
315250

316-
type ProtoClient<B> = ClientProxy<Message<RequestHead, B>, Message<proto::ResponseHead, TokioBody>, ::Error>;
317-
318251
struct HyperClient<B> {
319252
tx: RefCell<::futures::sync::mpsc::Sender<proto::dispatch::ClientMsg<B>>>,
320253
should_close: bool,
@@ -338,60 +271,6 @@ impl<B> Drop for HyperClient<B> {
338271
}
339272
}
340273

341-
enum Dispatch<B> {
342-
Proto(Pool<ProtoClient<B>>),
343-
Hyper(Pool<HyperClient<B>>),
344-
}
345-
346-
struct HttpClient<B> {
347-
client_rx: RefCell<Option<oneshot::Receiver<Pooled<ProtoClient<B>>>>>,
348-
}
349-
350-
impl<T, B> ClientProto<T> for HttpClient<B>
351-
where T: AsyncRead + AsyncWrite + 'static,
352-
B: Stream<Error=::Error> + 'static,
353-
B::Item: AsRef<[u8]>,
354-
{
355-
type Request = proto::RequestHead;
356-
type RequestBody = B::Item;
357-
type Response = proto::ResponseHead;
358-
type ResponseBody = proto::Chunk;
359-
type Error = ::Error;
360-
type Transport = proto::Conn<T, B::Item, proto::ClientTransaction, Pooled<ProtoClient<B>>>;
361-
type BindTransport = BindingClient<T, B>;
362-
363-
fn bind_transport(&self, io: T) -> Self::BindTransport {
364-
BindingClient {
365-
rx: self.client_rx.borrow_mut().take().expect("client_rx was lost"),
366-
io: Some(io),
367-
}
368-
}
369-
}
370-
371-
struct BindingClient<T, B> {
372-
rx: oneshot::Receiver<Pooled<ProtoClient<B>>>,
373-
io: Option<T>,
374-
}
375-
376-
impl<T, B> Future for BindingClient<T, B>
377-
where T: AsyncRead + AsyncWrite + 'static,
378-
B: Stream<Error=::Error>,
379-
B::Item: AsRef<[u8]>,
380-
{
381-
type Item = proto::Conn<T, B::Item, proto::ClientTransaction, Pooled<ProtoClient<B>>>;
382-
type Error = io::Error;
383-
384-
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
385-
match self.rx.poll() {
386-
Ok(Async::Ready(client)) => Ok(Async::Ready(
387-
proto::Conn::new(self.io.take().expect("binding client io lost"), client)
388-
)),
389-
Ok(Async::NotReady) => Ok(Async::NotReady),
390-
Err(_canceled) => unreachable!(),
391-
}
392-
}
393-
}
394-
395274
/// Configuration for a Client
396275
pub struct Config<C, B> {
397276
_body_type: PhantomData<B>,
@@ -490,10 +369,9 @@ impl<C, B> Config<C, B> {
490369
}
491370
*/
492371

493-
/// Disable tokio-proto internal usage.
494-
#[inline]
495-
pub fn no_proto(mut self) -> Config<C, B> {
496-
self.no_proto = true;
372+
#[doc(hidden)]
373+
#[deprecated(since="0.11.11", note="no_proto is always enabled")]
374+
pub fn no_proto(self) -> Config<C, B> {
497375
self
498376
}
499377
}

0 commit comments

Comments
 (0)