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