refactor(http): merge Request and Response from server and client

Request and Response are now visible from:
- hyper::{Request, Response}
- hyper::server::{Request, Response}
- hyper::client::{Request, Response}
They truly exist in the http module, but are re-exported to reduce the number of breaking changes.

request::new and response::new were renamed to ::from_wire to reduce confusion with Request::new
and Response::new. See issue #1126

Request now has an optional Body, because not all requests have bodies.
Use body_ref() to determine if a body exists.
Use body() to take the body, or construct one if no body exists.

Closes #1155

BREAKING CHANGE: Response::body() now consumes the response
This commit is contained in:
Nick Gonzales
2017-05-01 12:19:55 -06:00
parent 0de295670f
commit 864d3e27a4
11 changed files with 242 additions and 314 deletions

View File

@@ -24,13 +24,12 @@ use tokio_proto::streaming::Message;
use tokio_proto::streaming::pipeline::{Transport, Frame, ServerProto};
pub use tokio_service::{NewService, Service};
pub use self::request::Request;
pub use self::response::Response;
use http;
use http::response;
use http::request;
mod request;
mod response;
pub use http::response::Response;
pub use http::request::Request;
/// An instance of the HTTP protocol, and implementation of tokio-proto's
/// `ServerProto` trait.
@@ -284,7 +283,7 @@ impl From<Message<__ProtoRequest, http::TokioBody>> for Request {
Message::WithoutBody(head) => (head.0, http::Body::empty()),
Message::WithBody(head, body) => (head.0, body.into()),
};
request::new(None, head, body)
request::from_wire(None, head, body)
}
}
@@ -321,7 +320,7 @@ impl<T, B> Service for HttpService<T>
Message::WithoutBody(head) => (head.0, http::Body::empty()),
Message::WithBody(head, body) => (head.0, body.into()),
};
let req = request::new(Some(self.remote_addr), head, body);
let req = request::from_wire(Some(self.remote_addr), head, body);
self.inner.call(req).map(Into::into)
}
}

View File

@@ -1,113 +0,0 @@
//! Server Requests
//!
//! These are requests that a `hyper::Server` receives, and include its method,
//! target URI, headers, and message body.
use std::fmt;
use std::net::SocketAddr;
use version::HttpVersion;
use method::Method;
use header::Headers;
use http::{RequestHead, MessageHead, RequestLine, Body};
use uri::Uri;
/// A request bundles several parts of an incoming `NetworkStream`, given to a `Handler`.
pub struct Request {
method: Method,
uri: Uri,
version: HttpVersion,
headers: Headers,
remote_addr: Option<SocketAddr>,
body: Body,
}
impl Request {
/// The `Method`, such as `Get`, `Post`, etc.
#[inline]
pub fn method(&self) -> &Method { &self.method }
/// The headers of the incoming request.
#[inline]
pub fn headers(&self) -> &Headers { &self.headers }
/// The target request-uri for this request.
#[inline]
pub fn uri(&self) -> &Uri { &self.uri }
/// The version of HTTP for this request.
#[inline]
pub fn version(&self) -> HttpVersion { self.version }
/// 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]
pub fn remote_addr(&self) -> Option<SocketAddr> { self.remote_addr }
/// The target path of this Request.
#[inline]
pub fn path(&self) -> &str {
self.uri.path()
}
/// The query string of this Request.
#[inline]
pub fn query(&self) -> Option<&str> {
self.uri.query()
}
/// Take the `Body` of this `Request`.
#[inline]
pub fn body(self) -> Body {
self.body
}
/// Deconstruct this Request into its pieces.
///
/// Modifying these pieces will have no effect on how hyper behaves.
#[inline]
pub fn deconstruct(self) -> (Method, Uri, HttpVersion, Headers, Body) {
(self.method, self.uri, self.version, self.headers, self.body)
}
}
impl fmt::Debug for Request {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Request")
.field("method", &self.method)
.field("uri", &self.uri)
.field("version", &self.version)
.field("remote_addr", &self.remote_addr)
.field("headers", &self.headers)
.finish()
}
}
pub fn new(addr: Option<SocketAddr>, incoming: RequestHead, body: Body) -> Request {
let MessageHead { version, subject: RequestLine(method, uri), headers } = incoming;
debug!("Request::new: addr={}, req=\"{} {} {}\"", MaybeAddr(&addr), method, uri, version);
debug!("Request::new: headers={:?}", headers);
Request {
method: method,
uri: uri,
headers: headers,
version: version,
remote_addr: addr,
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"),
}
}
}

View File

@@ -1,111 +0,0 @@
use std::fmt;
use header;
use http::{self, Body};
use status::StatusCode;
use version;
/// The Response sent to a client after receiving a Request in a Service.
///
/// The default `StatusCode` for a `Response` is `200 OK`.
pub struct Response<B = Body> {
head: http::MessageHead<StatusCode>,
body: Option<B>,
}
impl<B> Response<B> {
/// Create a new Response.
#[inline]
pub fn new() -> Response<B> {
Response::default()
}
/// The headers of this response.
#[inline]
pub fn headers(&self) -> &header::Headers { &self.head.headers }
/// The status of this response.
#[inline]
pub fn status(&self) -> StatusCode {
self.head.subject
}
/// The HTTP version of this response.
#[inline]
pub fn version(&self) -> version::HttpVersion { self.head.version }
/// Get a mutable reference to the Headers.
#[inline]
pub fn headers_mut(&mut self) -> &mut header::Headers { &mut self.head.headers }
/// Set the `StatusCode` for this response.
#[inline]
pub fn set_status(&mut self, status: StatusCode) {
self.head.subject = status;
}
/// Set the body.
#[inline]
pub fn set_body<T: Into<B>>(&mut self, body: T) {
self.body = Some(body.into());
}
/// Set the status and move the Response.
///
/// Useful for the "builder-style" pattern.
#[inline]
pub fn with_status(mut self, status: StatusCode) -> Self {
self.set_status(status);
self
}
/// Set a header and move the Response.
///
/// Useful for the "builder-style" pattern.
#[inline]
pub fn with_header<H: header::Header>(mut self, header: H) -> Self {
self.head.headers.set(header);
self
}
/// Set the headers and move the Response.
///
/// Useful for the "builder-style" pattern.
#[inline]
pub fn with_headers(mut self, headers: header::Headers) -> Self {
self.head.headers = headers;
self
}
/// Set the body and move the Response.
///
/// Useful for the "builder-style" pattern.
#[inline]
pub fn with_body<T: Into<B>>(mut self, body: T) -> Self {
self.set_body(body);
self
}
}
impl<B> Default for Response<B> {
fn default() -> Response<B> {
Response {
head: Default::default(),
body: None,
}
}
}
impl<B> fmt::Debug for Response<B> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Response")
.field("status", &self.head.subject)
.field("version", &self.head.version)
.field("headers", &self.head.headers)
.finish()
}
}
pub fn split<B>(res: Response<B>) -> (http::MessageHead<StatusCode>, Option<B>) {
(res.head, res.body)
}