use std::io::{Read, Write};
pub use url::Url;
use hyper::version::HttpVersion;
use hyper::buffer::BufReader;
use hyper::header::Headers;
use hyper::header::{Connection, ConnectionOption};
use hyper::header::{Upgrade, Protocol, ProtocolName};
use unicase::UniCase;
use header::{WebSocketKey, WebSocketVersion, WebSocketProtocol, WebSocketExtensions, Origin};
use result::WebSocketResult;
use client::response::Response;
use ws::util::url::ToWebSocketUrlComponents;
pub struct Request<R: Read, W: Write> {
pub version: HttpVersion,
pub headers: Headers,
resource_name: String,
reader: BufReader<R>,
writer: W,
}
unsafe impl<R, W> Send for Request<R, W> where R: Read + Send, W: Write + Send { }
impl<R: Read, W: Write> Request<R, W> {
pub fn new<T: ToWebSocketUrlComponents>(components: T, reader: R, writer: W) -> WebSocketResult<Request<R, W>> {
let mut headers = Headers::new();
let (host, resource_name, _) = try!(components.to_components());
headers.set(host);
headers.set(Connection(vec![
ConnectionOption::ConnectionHeader(UniCase("Upgrade".to_string()))
]));
headers.set(Upgrade(vec![Protocol{
name: ProtocolName::WebSocket,
version: None
}]));
headers.set(WebSocketVersion::WebSocket13);
headers.set(WebSocketKey::new());
Ok(Request {
version: HttpVersion::Http11,
headers: headers,
resource_name: resource_name,
reader: BufReader::new(reader),
writer: writer
})
}
pub fn key(&self) -> Option<&WebSocketKey> {
self.headers.get()
}
pub fn version(&self) -> Option<&WebSocketVersion> {
self.headers.get()
}
pub fn protocol(&self) -> Option<&WebSocketProtocol> {
self.headers.get()
}
pub fn extensions(&self) -> Option<&WebSocketExtensions> {
self.headers.get()
}
pub fn origin(&self) -> Option<&Origin> {
self.headers.get()
}
pub fn key_mut(&mut self) -> Option<&mut WebSocketKey> {
self.headers.get_mut()
}
pub fn version_mut(&mut self) -> Option<&mut WebSocketVersion> {
self.headers.get_mut()
}
pub fn protocol_mut(&mut self) -> Option<&mut WebSocketProtocol> {
self.headers.get_mut()
}
pub fn extensions_mut(&mut self) -> Option<&mut WebSocketExtensions> {
self.headers.get_mut()
}
pub fn origin_mut(&mut self) -> Option<&mut Origin> {
self.headers.get_mut()
}
pub fn get_reader(&self) -> &BufReader<R> {
&self.reader
}
pub fn get_writer(&self) -> &W {
&self.writer
}
pub fn get_mut_reader(&mut self) -> &mut BufReader<R> {
&mut self.reader
}
pub fn get_mut_writer(&mut self) -> &mut W {
&mut self.writer
}
pub fn into_inner(self) -> (BufReader<R>, W) {
(self.reader, self.writer)
}
pub fn send(mut self) -> WebSocketResult<Response<R, W>> {
try!(write!(&mut self.writer, "GET {} {}\r\n", self.resource_name, self.version));
try!(write!(&mut self.writer, "{}\r\n", self.headers));
Response::read(self)
}
}