Skip to content

Commit

Permalink
fix(server): add remote_addr back to Request when using Http::bind
Browse files Browse the repository at this point in the history
The `Request::remote_addr()` method has been deprecated.

Closes #1410
  • Loading branch information
seanmonstar committed Jan 8, 2018
1 parent b3f3246 commit fa7f437
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 9 deletions.
12 changes: 6 additions & 6 deletions src/proto/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,9 @@ impl<B> Request<B> {
#[inline]
pub fn body_ref(&self) -> Option<&B> { self.body.as_ref() }

/// The remote socket address of this request
///
/// This is an `Option`, because some underlying transports may not have
/// a socket address, such as Unix Sockets.
///
/// This field is not used for outgoing requests.
#[doc(hidden)]
#[inline]
#[deprecated(since="0.11.12", note="This method will be gone in future versions.")]
pub fn remote_addr(&self) -> Option<SocketAddr> { self.remote_addr }

/// The target path of this Request.
Expand Down Expand Up @@ -196,6 +192,10 @@ pub fn split<B>(req: Request<B>) -> (RequestHead, Option<B>) {
(head, req.body)
}

pub fn addr<B>(req: &mut Request<B>, addr: SocketAddr) {
req.remote_addr = Some(addr);
}

#[cfg(test)]
mod tests {
/*
Expand Down
38 changes: 37 additions & 1 deletion src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -352,8 +352,9 @@ impl<S, B> Server<S, B>

// Future for our server's execution
let srv = listener.incoming().for_each(|(socket, addr)| {
let addr_service = SocketAddrService::new(addr, new_service.new_service()?);
let s = NotifyService {
inner: try!(new_service.new_service()),
inner: addr_service,
info: Rc::downgrade(&info),
};
info.borrow_mut().active += 1;
Expand Down Expand Up @@ -644,6 +645,41 @@ mod addr_stream {
}
}

// ===== SocketAddrService

// This is used from `Server::run`, which captures the remote address
// in this service, and then injects it into each `Request`.
struct SocketAddrService<S> {
addr: SocketAddr,
inner: S,
}

impl<S> SocketAddrService<S> {
fn new(addr: SocketAddr, service: S) -> SocketAddrService<S> {
SocketAddrService {
addr: addr,
inner: service,
}
}
}

impl<S> Service for SocketAddrService<S>
where
S: Service<Request=Request>,
{
type Request = S::Request;
type Response = S::Response;
type Error = S::Error;
type Future = S::Future;

fn call(&self, mut req: Self::Request) -> Self::Future {
proto::request::addr(&mut req, self.addr);
self.inner.call(req)
}
}

// ===== NotifyService =====

struct NotifyService<S> {
inner: S,
info: Weak<RefCell<Info>>,
Expand Down
40 changes: 38 additions & 2 deletions tests/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,22 @@ fn nonempty_parse_eof_returns_error() {
core.run(fut).unwrap_err();
}

#[test]
fn remote_addr() {
let server = serve();

let mut req = connect(server.addr());
req.write_all(b"\
GET / HTTP/1.1\r\n\
Host: example.domain\r\n\
\r\n\
").unwrap();
req.read(&mut [0; 256]).unwrap();

let client_addr = req.local_addr().unwrap();
assert_eq!(server.remote_addr(), client_addr);
}

// -------------------------------------------------
// the Server that is used to run all the tests with
// -------------------------------------------------
Expand All @@ -729,10 +745,23 @@ impl Serve {
&self.addr
}

pub fn remote_addr(&self) -> SocketAddr {
match self.msg_rx.try_recv() {
Ok(Msg::Addr(addr)) => addr,
other => panic!("expected remote addr, found: {:?}", other),
}
}

fn body(&self) -> Vec<u8> {
let mut buf = vec![];
while let Ok(Msg::Chunk(msg)) = self.msg_rx.try_recv() {
buf.extend(&msg);
loop {
match self.msg_rx.try_recv() {
Ok(Msg::Chunk(msg)) => {
buf.extend(&msg);
},
Ok(Msg::Addr(_)) => {},
Err(_) => break,
}
}
buf
}
Expand Down Expand Up @@ -787,8 +816,10 @@ enum Reply {
Body(Vec<u8>),
}

#[derive(Debug)]
enum Msg {
//Head(Request),
Addr(SocketAddr),
Chunk(Vec<u8>),
}

Expand All @@ -811,6 +842,11 @@ impl Service for TestService {
type Future = Box<Future<Item=Response, Error=hyper::Error>>;
fn call(&self, req: Request) -> Self::Future {
let tx = self.tx.clone();

#[allow(deprecated)]
let remote_addr = req.remote_addr().expect("remote_addr");
tx.lock().unwrap().send(Msg::Addr(remote_addr)).unwrap();

let replies = self.reply.clone();
Box::new(req.body().for_each(move |chunk| {
tx.lock().unwrap().send(Msg::Chunk(chunk.to_vec())).unwrap();
Expand Down

0 comments on commit fa7f437

Please sign in to comment.