Skip to content

Commit 8bf7964

Browse files
committed
fix(server): GET requests with no body have None instead of Empty
Closes #1373
1 parent b1785c6 commit 8bf7964

File tree

4 files changed

+55
-13
lines changed

4 files changed

+55
-13
lines changed

src/proto/dispatch.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub trait Dispatch {
1818
type PollBody;
1919
type RecvItem;
2020
fn poll_msg(&mut self) -> Poll<Option<(Self::PollItem, Option<Self::PollBody>)>, ::Error>;
21-
fn recv_msg(&mut self, msg: ::Result<(Self::RecvItem, Body)>) -> ::Result<()>;
21+
fn recv_msg(&mut self, msg: ::Result<(Self::RecvItem, Option<Body>)>) -> ::Result<()>;
2222
fn should_poll(&self) -> bool;
2323
}
2424

@@ -60,9 +60,9 @@ where
6060
let body = if has_body {
6161
let (tx, rx) = super::Body::pair();
6262
self.body_tx = Some(tx);
63-
rx
63+
Some(rx)
6464
} else {
65-
Body::empty()
65+
None
6666
};
6767
self.dispatch.recv_msg(Ok((head, body))).expect("recv_msg with Ok shouldn't error");
6868
},
@@ -253,7 +253,7 @@ where
253253
}
254254
}
255255

256-
fn recv_msg(&mut self, msg: ::Result<(Self::RecvItem, Body)>) -> ::Result<()> {
256+
fn recv_msg(&mut self, msg: ::Result<(Self::RecvItem, Option<Body>)>) -> ::Result<()> {
257257
let (msg, body) = msg?;
258258
let req = super::request::from_wire(None, msg, body);
259259
self.in_flight = Some(self.service.call(req));
@@ -300,10 +300,10 @@ where
300300
}
301301
}
302302

303-
fn recv_msg(&mut self, msg: ::Result<(Self::RecvItem, Body)>) -> ::Result<()> {
303+
fn recv_msg(&mut self, msg: ::Result<(Self::RecvItem, Option<Body>)>) -> ::Result<()> {
304304
match msg {
305305
Ok((msg, body)) => {
306-
let res = super::response::from_wire(msg, Some(body));
306+
let res = super::response::from_wire(msg, body);
307307
let cb = self.callback.take().expect("recv_msg without callback");
308308
let _ = cb.send(Ok(res));
309309
Ok(())

src/proto/request.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,16 +168,16 @@ impl<B> From<http::Request<B>> for Request<B> {
168168
}
169169

170170
/// Constructs a request using a received ResponseHead and optional body
171-
pub fn from_wire<B>(addr: Option<SocketAddr>, incoming: RequestHead, body: B) -> Request<B> {
171+
pub fn from_wire(addr: Option<SocketAddr>, incoming: RequestHead, body: Option<Body>) -> Request<Body> {
172172
let MessageHead { version, subject: RequestLine(method, uri), headers } = incoming;
173173

174-
Request::<B> {
174+
Request {
175175
method: method,
176176
uri: uri,
177177
headers: headers,
178178
version: version,
179179
remote_addr: addr,
180-
body: Some(body),
180+
body: body,
181181
is_proxy: false,
182182
}
183183
}

src/server/server_proto.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,8 @@ impl From<Message<__ProtoRequest, proto::TokioBody>> for Request {
219219
#[inline]
220220
fn from(message: Message<__ProtoRequest, proto::TokioBody>) -> Request {
221221
let (head, body) = match message {
222-
Message::WithoutBody(head) => (head.0, proto::Body::empty()),
223-
Message::WithBody(head, body) => (head.0, body.into()),
222+
Message::WithoutBody(head) => (head.0, None),
223+
Message::WithBody(head, body) => (head.0, Some(body.into())),
224224
};
225225
request::from_wire(None, head, body)
226226
}
@@ -256,8 +256,8 @@ impl<T, B> Service for HttpService<T>
256256
#[inline]
257257
fn call(&self, message: Self::Request) -> Self::Future {
258258
let (head, body) = match message {
259-
Message::WithoutBody(head) => (head.0, proto::Body::empty()),
260-
Message::WithBody(head, body) => (head.0, body.into()),
259+
Message::WithoutBody(head) => (head.0, None),
260+
Message::WithBody(head, body) => (head.0, Some(body.into())),
261261
};
262262
let req = request::from_wire(Some(self.remote_addr), head, body);
263263
self.inner.call(req).map(Into::into)

tests/server.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use std::time::Duration;
2121

2222
use hyper::server::{Http, Request, Response, Service, NewService};
2323

24+
2425
#[test]
2526
fn get_should_ignore_body() {
2627
let server = serve();
@@ -56,6 +57,47 @@ fn get_with_body() {
5657
assert_eq!(server.body(), b"I'm a good request.");
5758
}
5859

60+
#[test]
61+
fn get_implicitly_empty() {
62+
// See https://github.com/hyperium/hyper/issues/1373
63+
let mut core = Core::new().unwrap();
64+
let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &core.handle()).unwrap();
65+
let addr = listener.local_addr().unwrap();
66+
67+
thread::spawn(move || {
68+
let mut tcp = connect(&addr);
69+
tcp.write_all(b"\
70+
GET / HTTP/1.1\r\n\
71+
Host: example.domain\r\n\
72+
\r\n\
73+
").unwrap();
74+
});
75+
76+
let fut = listener.incoming()
77+
.into_future()
78+
.map_err(|_| unreachable!())
79+
.and_then(|(item, _incoming)| {
80+
let (socket, _) = item.unwrap();
81+
Http::<hyper::Chunk>::new().serve_connection(socket, GetImplicitlyEmpty)
82+
});
83+
84+
core.run(fut).unwrap();
85+
86+
struct GetImplicitlyEmpty;
87+
88+
impl Service for GetImplicitlyEmpty {
89+
type Request = Request;
90+
type Response = Response;
91+
type Error = hyper::Error;
92+
type Future = FutureResult<Self::Response, Self::Error>;
93+
94+
fn call(&self, req: Request) -> Self::Future {
95+
assert!(req.body_ref().is_none());
96+
future::ok(Response::new())
97+
}
98+
}
99+
}
100+
59101
#[test]
60102
fn get_fixed_response() {
61103
let foo_bar = b"foo bar baz";

0 commit comments

Comments
 (0)