feat(server): make Http compatible with TcpServer
This implements `From<Message> for Request` and `Into<Message> for Response`, allowing an `Http` instance to be used with a `TcpServer` from tokio-proto. Closes #1036 BREAKING CHANGE: This makes `Request.remote_addr` an `Option<SocketAddr>`, instead of `SocketAddr`.
This commit is contained in:
@@ -265,20 +265,32 @@ impl<T: Io + 'static, B> Future for __ProtoBindTransport<T, B> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Message<__ProtoRequest, http::TokioBody>> for Request {
|
||||||
|
fn from(message: Message<__ProtoRequest, http::TokioBody>) -> Request {
|
||||||
|
let (head, body) = match message {
|
||||||
|
Message::WithoutBody(head) => (head.0, http::Body::empty()),
|
||||||
|
Message::WithBody(head, body) => (head.0, body.into()),
|
||||||
|
};
|
||||||
|
request::new(None, head, body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B> Into<Message<__ProtoResponse, B>> for Response<B> {
|
||||||
|
fn into(self) -> Message<__ProtoResponse, B> {
|
||||||
|
let (head, body) = response::split(self);
|
||||||
|
if let Some(body) = body {
|
||||||
|
Message::WithBody(__ProtoResponse(head), body.into())
|
||||||
|
} else {
|
||||||
|
Message::WithoutBody(__ProtoResponse(head))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct HttpService<T> {
|
struct HttpService<T> {
|
||||||
inner: T,
|
inner: T,
|
||||||
remote_addr: SocketAddr,
|
remote_addr: SocketAddr,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_response_to_message<B>(res: Response<B>) -> Message<__ProtoResponse, B> {
|
|
||||||
let (head, body) = response::split(res);
|
|
||||||
if let Some(body) = body {
|
|
||||||
Message::WithBody(__ProtoResponse(head), body.into())
|
|
||||||
} else {
|
|
||||||
Message::WithoutBody(__ProtoResponse(head))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type ResponseHead = http::MessageHead<::StatusCode>;
|
type ResponseHead = http::MessageHead<::StatusCode>;
|
||||||
|
|
||||||
impl<T, B> Service for HttpService<T>
|
impl<T, B> Service for HttpService<T>
|
||||||
@@ -296,8 +308,8 @@ impl<T, B> Service for HttpService<T>
|
|||||||
Message::WithoutBody(head) => (head.0, http::Body::empty()),
|
Message::WithoutBody(head) => (head.0, http::Body::empty()),
|
||||||
Message::WithBody(head, body) => (head.0, body.into()),
|
Message::WithBody(head, body) => (head.0, body.into()),
|
||||||
};
|
};
|
||||||
let req = request::new(self.remote_addr, head, body);
|
let req = request::new(Some(self.remote_addr), head, body);
|
||||||
self.inner.call(req).map(map_response_to_message)
|
self.inner.call(req).map(Into::into)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ pub struct Request {
|
|||||||
uri: Uri,
|
uri: Uri,
|
||||||
version: HttpVersion,
|
version: HttpVersion,
|
||||||
headers: Headers,
|
headers: Headers,
|
||||||
remote_addr: SocketAddr,
|
remote_addr: Option<SocketAddr>,
|
||||||
body: Body,
|
body: Body,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,8 +40,11 @@ impl Request {
|
|||||||
pub fn version(&self) -> &HttpVersion { &self.version }
|
pub fn version(&self) -> &HttpVersion { &self.version }
|
||||||
|
|
||||||
/// The remote socket address of this request
|
/// 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.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn remote_addr(&self) -> &SocketAddr { &self.remote_addr }
|
pub fn remote_addr(&self) -> Option<&SocketAddr> { self.remote_addr.as_ref() }
|
||||||
|
|
||||||
/// The target path of this Request.
|
/// The target path of this Request.
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -82,9 +85,9 @@ impl fmt::Debug for Request {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(addr: SocketAddr, incoming: RequestHead, body: Body) -> Request {
|
pub fn new(addr: Option<SocketAddr>, incoming: RequestHead, body: Body) -> Request {
|
||||||
let MessageHead { version, subject: RequestLine(method, uri), headers } = incoming;
|
let MessageHead { version, subject: RequestLine(method, uri), headers } = incoming;
|
||||||
debug!("Request::new: addr={}, req=\"{} {} {}\"", addr, method, uri, version);
|
debug!("Request::new: addr={}, req=\"{} {} {}\"", MaybeAddr(&addr), method, uri, version);
|
||||||
debug!("Request::new: headers={:?}", headers);
|
debug!("Request::new: headers={:?}", headers);
|
||||||
|
|
||||||
Request {
|
Request {
|
||||||
@@ -96,3 +99,15 @@ pub fn new(addr: SocketAddr, incoming: RequestHead, body: Body) -> Request {
|
|||||||
body: body,
|
body: body,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct MaybeAddr<'a>(&'a Option<SocketAddr>);
|
||||||
|
|
||||||
|
impl<'a> fmt::Display for MaybeAddr<'a> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match *self.0 {
|
||||||
|
Some(ref addr) => fmt::Display::fmt(addr, f),
|
||||||
|
None => f.write_str("None"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user