//! Client Responses use std::io::{BufferedReader, IoResult}; use std::io::net::tcp::TcpStream; use header::{mod, ContentLength, TransferEncoding, Chunked}; use rfc7230::{read_status_line, HttpReader, SizedReader, ChunkedReader, EofReader}; use status; use version; use {HttpResult}; /// A response for a client request to a remote server. pub struct Response { /// The status from the server. pub status: status::StatusCode, /// The headers from the server. pub headers: header::Headers, /// The HTTP version of this response from the server. pub version: version::HttpVersion, body: HttpReader>, } impl Response { /// Creates a new response from a server. pub fn new(tcp: TcpStream) -> HttpResult { let mut tcp = BufferedReader::new(tcp); let (version, status) = try!(read_status_line(&mut tcp)); let mut headers = try!(header::Headers::from_raw(&mut tcp)); debug!("{} {}", version, status); debug!("{}", headers); let body = if headers.has::() { match headers.get_ref::() { Some(&TransferEncoding(ref codings)) => { if codings.len() > 1 { debug!("TODO: #2 handle other codings: {}", codings); }; if codings.contains(&Chunked) { ChunkedReader(tcp, None) } else { debug!("not chucked. read till eof"); EofReader(tcp) } } None => unreachable!() } } else if headers.has::() { match headers.get_ref::() { Some(&ContentLength(len)) => SizedReader(tcp, len), None => unreachable!() } } else { debug!("neither Transfer-Encoding nor Content-Length"); EofReader(tcp) }; Ok(Response { status: status, version: version, headers: headers, body: body, }) } } impl Reader for Response { fn read(&mut self, buf: &mut [u8]) -> IoResult { self.body.read(buf) } }