1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-30 18:34:36 +01:00

cleanup and optimize some code

This commit is contained in:
Nikolay Kim 2017-12-12 21:32:58 -08:00
parent ab6efd2421
commit 2e83c5924d
9 changed files with 148 additions and 68 deletions

View File

@ -13,11 +13,13 @@ use futures::future::{FutureResult, result};
/// simple handler /// simple handler
fn index(mut req: HttpRequest) -> Result<HttpResponse> { fn index(mut req: HttpRequest) -> Result<HttpResponse> {
println!("{:?}", req); println!("{:?}", req);
if let Ok(ch) = req.payload_mut().readany() { if let Some(payload) = req.payload_mut() {
if let Ok(ch) = payload.readany() {
if let futures::Async::Ready(Some(d)) = ch { if let futures::Async::Ready(Some(d)) = ch {
println!("{}", String::from_utf8_lossy(d.0.as_ref())); println!("{}", String::from_utf8_lossy(d.0.as_ref()));
} }
} }
}
// session // session
if let Some(count) = req.session().get::<i32>("counter")? { if let Some(count) = req.session().get::<i32>("counter")? {

View File

@ -402,14 +402,14 @@ impl PayloadEncoder {
resp.headers_mut().insert( resp.headers_mut().insert(
CONTENT_LENGTH, CONTENT_LENGTH,
HeaderValue::from_str(format!("{}", b.len()).as_str()).unwrap()); HeaderValue::from_str(&b.len().to_string()).unwrap());
*bytes = Binary::from(b); *bytes = Binary::from(b);
encoding = ContentEncoding::Identity; encoding = ContentEncoding::Identity;
TransferEncoding::eof() TransferEncoding::eof()
} else { } else {
resp.headers_mut().insert( resp.headers_mut().insert(
CONTENT_LENGTH, CONTENT_LENGTH,
HeaderValue::from_str(format!("{}", bytes.len()).as_str()).unwrap()); HeaderValue::from_str(&bytes.len().to_string()).unwrap());
resp.headers_mut().remove(TRANSFER_ENCODING); resp.headers_mut().remove(TRANSFER_ENCODING);
TransferEncoding::length(bytes.len() as u64) TransferEncoding::length(bytes.len() as u64)
} }
@ -478,22 +478,27 @@ impl PayloadEncoder {
impl PayloadEncoder { impl PayloadEncoder {
#[inline]
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.0.get_ref().len() self.0.get_ref().len()
} }
#[inline]
pub fn get_mut(&mut self) -> &mut BytesMut { pub fn get_mut(&mut self) -> &mut BytesMut {
self.0.get_mut() self.0.get_mut()
} }
#[inline]
pub fn is_eof(&self) -> bool { pub fn is_eof(&self) -> bool {
self.0.is_eof() self.0.is_eof()
} }
#[inline]
pub fn write(&mut self, payload: &[u8]) -> Result<(), io::Error> { pub fn write(&mut self, payload: &[u8]) -> Result<(), io::Error> {
self.0.write(payload) self.0.write(payload)
} }
#[inline]
pub fn write_eof(&mut self) -> Result<(), io::Error> { pub fn write_eof(&mut self) -> Result<(), io::Error> {
self.0.write_eof() self.0.write_eof()
} }
@ -508,6 +513,7 @@ enum ContentEncoder {
impl ContentEncoder { impl ContentEncoder {
#[inline]
pub fn is_eof(&self) -> bool { pub fn is_eof(&self) -> bool {
match *self { match *self {
ContentEncoder::Br(ref encoder) => ContentEncoder::Br(ref encoder) =>
@ -521,6 +527,7 @@ impl ContentEncoder {
} }
} }
#[inline]
pub fn get_ref(&self) -> &BytesMut { pub fn get_ref(&self) -> &BytesMut {
match *self { match *self {
ContentEncoder::Br(ref encoder) => ContentEncoder::Br(ref encoder) =>
@ -534,6 +541,7 @@ impl ContentEncoder {
} }
} }
#[inline]
pub fn get_mut(&mut self) -> &mut BytesMut { pub fn get_mut(&mut self) -> &mut BytesMut {
match *self { match *self {
ContentEncoder::Br(ref mut encoder) => ContentEncoder::Br(ref mut encoder) =>
@ -547,6 +555,7 @@ impl ContentEncoder {
} }
} }
#[inline]
pub fn write_eof(&mut self) -> Result<(), io::Error> { pub fn write_eof(&mut self) -> Result<(), io::Error> {
let encoder = mem::replace(self, ContentEncoder::Identity(TransferEncoding::eof())); let encoder = mem::replace(self, ContentEncoder::Identity(TransferEncoding::eof()));
@ -555,7 +564,6 @@ impl ContentEncoder {
match encoder.finish() { match encoder.finish() {
Ok(mut writer) => { Ok(mut writer) => {
writer.encode_eof(); writer.encode_eof();
*self = ContentEncoder::Identity(writer);
Ok(()) Ok(())
}, },
Err(err) => Err(err), Err(err) => Err(err),
@ -565,7 +573,6 @@ impl ContentEncoder {
match encoder.finish() { match encoder.finish() {
Ok(mut writer) => { Ok(mut writer) => {
writer.encode_eof(); writer.encode_eof();
*self = ContentEncoder::Identity(writer);
Ok(()) Ok(())
}, },
Err(err) => Err(err), Err(err) => Err(err),
@ -575,7 +582,6 @@ impl ContentEncoder {
match encoder.finish() { match encoder.finish() {
Ok(mut writer) => { Ok(mut writer) => {
writer.encode_eof(); writer.encode_eof();
*self = ContentEncoder::Identity(writer);
Ok(()) Ok(())
}, },
Err(err) => Err(err), Err(err) => Err(err),
@ -583,19 +589,18 @@ impl ContentEncoder {
}, },
ContentEncoder::Identity(mut writer) => { ContentEncoder::Identity(mut writer) => {
writer.encode_eof(); writer.encode_eof();
*self = ContentEncoder::Identity(writer);
Ok(()) Ok(())
} }
} }
} }
#[inline]
pub fn write(&mut self, data: &[u8]) -> Result<(), io::Error> { pub fn write(&mut self, data: &[u8]) -> Result<(), io::Error> {
match *self { match *self {
ContentEncoder::Br(ref mut encoder) => { ContentEncoder::Br(ref mut encoder) => {
match encoder.write(data) { match encoder.write(data) {
Ok(_) => { Ok(_) =>
encoder.flush() encoder.flush(),
},
Err(err) => { Err(err) => {
trace!("Error decoding br encoding: {}", err); trace!("Error decoding br encoding: {}", err);
Err(err) Err(err)
@ -604,20 +609,18 @@ impl ContentEncoder {
}, },
ContentEncoder::Gzip(ref mut encoder) => { ContentEncoder::Gzip(ref mut encoder) => {
match encoder.write(data) { match encoder.write(data) {
Ok(_) => { Ok(_) =>
encoder.flush() encoder.flush(),
},
Err(err) => { Err(err) => {
trace!("Error decoding br encoding: {}", err); trace!("Error decoding gzip encoding: {}", err);
Err(err) Err(err)
}, },
} }
} }
ContentEncoder::Deflate(ref mut encoder) => { ContentEncoder::Deflate(ref mut encoder) => {
match encoder.write(data) { match encoder.write(data) {
Ok(_) => { Ok(_) =>
encoder.flush() encoder.flush(),
},
Err(err) => { Err(err) => {
trace!("Error decoding deflate encoding: {}", err); trace!("Error decoding deflate encoding: {}", err);
Err(err) Err(err)
@ -655,6 +658,7 @@ enum TransferEncodingKind {
impl TransferEncoding { impl TransferEncoding {
#[inline]
pub fn eof() -> TransferEncoding { pub fn eof() -> TransferEncoding {
TransferEncoding { TransferEncoding {
kind: TransferEncodingKind::Eof, kind: TransferEncodingKind::Eof,
@ -662,6 +666,7 @@ impl TransferEncoding {
} }
} }
#[inline]
pub fn chunked() -> TransferEncoding { pub fn chunked() -> TransferEncoding {
TransferEncoding { TransferEncoding {
kind: TransferEncodingKind::Chunked(false), kind: TransferEncodingKind::Chunked(false),
@ -669,6 +674,7 @@ impl TransferEncoding {
} }
} }
#[inline]
pub fn length(len: u64) -> TransferEncoding { pub fn length(len: u64) -> TransferEncoding {
TransferEncoding { TransferEncoding {
kind: TransferEncodingKind::Length(len), kind: TransferEncodingKind::Length(len),
@ -676,6 +682,7 @@ impl TransferEncoding {
} }
} }
#[inline]
pub fn is_eof(&self) -> bool { pub fn is_eof(&self) -> bool {
match self.kind { match self.kind {
TransferEncodingKind::Eof => true, TransferEncodingKind::Eof => true,
@ -687,6 +694,7 @@ impl TransferEncoding {
} }
/// Encode message. Return `EOF` state of encoder /// Encode message. Return `EOF` state of encoder
#[inline]
pub fn encode(&mut self, msg: &[u8]) -> bool { pub fn encode(&mut self, msg: &[u8]) -> bool {
match self.kind { match self.kind {
TransferEncodingKind::Eof => { TransferEncodingKind::Eof => {
@ -724,6 +732,7 @@ impl TransferEncoding {
} }
/// Encode eof. Return `EOF` state of encoder /// Encode eof. Return `EOF` state of encoder
#[inline]
pub fn encode_eof(&mut self) { pub fn encode_eof(&mut self) {
match self.kind { match self.kind {
TransferEncodingKind::Eof | TransferEncodingKind::Length(_) => (), TransferEncodingKind::Eof | TransferEncodingKind::Length(_) => (),
@ -739,11 +748,13 @@ impl TransferEncoding {
impl io::Write for TransferEncoding { impl io::Write for TransferEncoding {
#[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.encode(buf); self.encode(buf);
Ok(buf.len()) Ok(buf.len())
} }
#[inline]
fn flush(&mut self) -> io::Result<()> { fn flush(&mut self) -> io::Result<()> {
Ok(()) Ok(())
} }

View File

@ -262,6 +262,9 @@ pub enum MultipartError {
/// Multipart boundary is not found /// Multipart boundary is not found
#[fail(display="Multipart boundary is not found")] #[fail(display="Multipart boundary is not found")]
Boundary, Boundary,
/// Request does not contain payload
#[fail(display="Request does not contain payload")]
NoPayload,
/// Error during field parsing /// Error during field parsing
#[fail(display="{}", _0)] #[fail(display="{}", _0)]
Parse(#[cause] ParseError), Parse(#[cause] ParseError),
@ -329,6 +332,9 @@ pub enum WsHandshakeError {
/// Websocket key is not set or wrong /// Websocket key is not set or wrong
#[fail(display="Unknown websocket key")] #[fail(display="Unknown websocket key")]
BadWebsocketKey, BadWebsocketKey,
/// Request does not contain payload
#[fail(display="Request does not contain payload")]
NoPayload,
} }
impl ResponseError for WsHandshakeError { impl ResponseError for WsHandshakeError {
@ -351,7 +357,9 @@ impl ResponseError for WsHandshakeError {
WsHandshakeError::UnsupportedVersion => WsHandshakeError::UnsupportedVersion =>
HTTPBadRequest.with_reason("Unsupported version"), HTTPBadRequest.with_reason("Unsupported version"),
WsHandshakeError::BadWebsocketKey => WsHandshakeError::BadWebsocketKey =>
HTTPBadRequest.with_reason("Handshake error") HTTPBadRequest.with_reason("Handshake error"),
WsHandshakeError::NoPayload =>
HttpResponse::new(StatusCode::INTERNAL_SERVER_ERROR, Body::Empty),
} }
} }
} }
@ -371,6 +379,9 @@ pub enum UrlencodedError {
/// Content type error /// Content type error
#[fail(display="Content type error")] #[fail(display="Content type error")]
ContentType, ContentType,
/// Request does not contain payload
#[fail(display="Request does not contain payload")]
NoPayload,
} }
/// Return `BadRequest` for `UrlencodedError` /// Return `BadRequest` for `UrlencodedError`

View File

@ -545,28 +545,25 @@ impl Reader {
} }
} }
let (mut psender, payload) = Payload::new(false); let decoder = if upgrade(&method, &headers) {
let msg = HttpRequest::new(method, uri, version, headers, payload);
let decoder = if msg.upgrade() {
Decoder::eof() Decoder::eof()
} else { } else {
let has_len = msg.headers().contains_key(header::CONTENT_LENGTH); let has_len = headers.contains_key(header::CONTENT_LENGTH);
// Chunked encoding // Chunked encoding
if msg.chunked()? { if chunked(&headers)? {
if has_len { if has_len {
return Err(ParseError::Header) return Err(ParseError::Header)
} }
Decoder::chunked() Decoder::chunked()
} else { } else {
if !has_len { if !has_len {
psender.feed_eof(); let msg = HttpRequest::new(method, uri, version, headers, None);
return Ok(Message::Http1(msg, None)) return Ok(Message::Http1(msg, None))
} }
// Content-Length // Content-Length
let len = msg.headers().get(header::CONTENT_LENGTH).unwrap(); let len = headers.get(header::CONTENT_LENGTH).unwrap();
if let Ok(s) = len.to_str() { if let Ok(s) = len.to_str() {
if let Ok(len) = s.parse::<u64>() { if let Ok(len) = s.parse::<u64>() {
Decoder::length(len) Decoder::length(len)
@ -581,11 +578,13 @@ impl Reader {
} }
}; };
let payload = PayloadInfo { let (psender, payload) = Payload::new(false);
tx: PayloadType::new(msg.headers(), psender), let info = PayloadInfo {
tx: PayloadType::new(&headers, psender),
decoder: decoder, decoder: decoder,
}; };
Ok(Message::Http1(msg, Some(payload))) let msg = HttpRequest::new(method, uri, version, headers, Some(payload));
Ok(Message::Http1(msg, Some(info)))
} }
} }
@ -610,6 +609,32 @@ fn record_header_indices(bytes: &[u8],
} }
} }
/// Check if request is UPGRADE
fn upgrade(method: &Method, headers: &HeaderMap) -> bool {
if let Some(conn) = headers.get(header::CONNECTION) {
if let Ok(s) = conn.to_str() {
s.to_lowercase().contains("upgrade")
} else {
*method == Method::CONNECT
}
} else {
*method == Method::CONNECT
}
}
/// Check if request has chunked transfer encoding
fn chunked(headers: &HeaderMap) -> Result<bool, ParseError> {
if let Some(encodings) = headers.get(header::TRANSFER_ENCODING) {
if let Ok(s) = encodings.to_str() {
Ok(s.to_lowercase().contains("chunked"))
} else {
Err(ParseError::Header)
}
} else {
Ok(false)
}
}
/// Decoders to handle different Transfer-Encodings. /// Decoders to handle different Transfer-Encodings.
/// ///
/// If a message body does not include a Transfer-Encoding, it *should* /// If a message body does not include a Transfer-Encoding, it *should*

View File

@ -237,7 +237,7 @@ impl Entry {
let (psender, payload) = Payload::new(false); let (psender, payload) = Payload::new(false);
let mut req = HttpRequest::new( let mut req = HttpRequest::new(
parts.method, parts.uri, parts.version, parts.headers, payload); parts.method, parts.uri, parts.version, parts.headers, Some(payload));
// set remote addr // set remote addr
req.set_peer_addr(addr); req.set_peer_addr(addr);

View File

@ -58,6 +58,7 @@ pub(crate) enum ReplyItem {
impl Reply { impl Reply {
/// Create actor response /// Create actor response
#[inline]
pub fn actor<A, S>(ctx: HttpContext<A, S>) -> Reply pub fn actor<A, S>(ctx: HttpContext<A, S>) -> Reply
where A: Actor<Context=HttpContext<A, S>>, S: 'static where A: Actor<Context=HttpContext<A, S>>, S: 'static
{ {
@ -65,6 +66,7 @@ impl Reply {
} }
/// Create async response /// Create async response
#[inline]
pub fn async<F>(fut: F) -> Reply pub fn async<F>(fut: F) -> Reply
where F: Future<Item=HttpResponse, Error=Error> + 'static where F: Future<Item=HttpResponse, Error=Error> + 'static
{ {
@ -72,10 +74,12 @@ impl Reply {
} }
/// Send response /// Send response
#[inline]
pub fn response<R: Into<HttpResponse>>(response: R) -> Reply { pub fn response<R: Into<HttpResponse>>(response: R) -> Reply {
Reply(ReplyItem::Message(response.into())) Reply(ReplyItem::Message(response.into()))
} }
#[inline]
pub(crate) fn into(self) -> ReplyItem { pub(crate) fn into(self) -> ReplyItem {
self.0 self.0
} }

View File

@ -28,7 +28,7 @@ pub struct HttpMessage {
pub params: Params<'static>, pub params: Params<'static>,
pub cookies: Option<Vec<Cookie<'static>>>, pub cookies: Option<Vec<Cookie<'static>>>,
pub addr: Option<SocketAddr>, pub addr: Option<SocketAddr>,
pub payload: Payload, pub payload: Option<Payload>,
pub info: Option<ConnectionInfo<'static>>, pub info: Option<ConnectionInfo<'static>>,
} }
@ -43,7 +43,7 @@ impl Default for HttpMessage {
params: Params::default(), params: Params::default(),
cookies: None, cookies: None,
addr: None, addr: None,
payload: Payload::empty(), payload: None,
extensions: Extensions::new(), extensions: Extensions::new(),
info: None, info: None,
} }
@ -72,13 +72,13 @@ impl HttpMessage {
} }
/// An HTTP Request /// An HTTP Request
pub struct HttpRequest<S=()>(Rc<HttpMessage>, Rc<S>, Option<Router<S>>); pub struct HttpRequest<S=()>(Rc<HttpMessage>, Option<Rc<S>>, Option<Router<S>>);
impl HttpRequest<()> { impl HttpRequest<()> {
/// Construct a new Request. /// Construct a new Request.
#[inline] #[inline]
pub fn new(method: Method, uri: Uri, pub fn new(method: Method, uri: Uri,
version: Version, headers: HeaderMap, payload: Payload) -> HttpRequest version: Version, headers: HeaderMap, payload: Option<Payload>) -> HttpRequest
{ {
HttpRequest( HttpRequest(
Rc::new(HttpMessage { Rc::new(HttpMessage {
@ -93,7 +93,7 @@ impl HttpRequest<()> {
extensions: Extensions::new(), extensions: Extensions::new(),
info: None, info: None,
}), }),
Rc::new(()), None,
None, None,
) )
} }
@ -118,14 +118,14 @@ impl HttpRequest<()> {
extensions: Extensions::new(), extensions: Extensions::new(),
info: None, info: None,
}), }),
Rc::new(()), None,
None, None,
) )
} }
/// Construct new http request with state. /// Construct new http request with state.
pub fn with_state<S>(self, state: Rc<S>, router: Router<S>) -> HttpRequest<S> { pub fn with_state<S>(self, state: Rc<S>, router: Router<S>) -> HttpRequest<S> {
HttpRequest(self.0, state, Some(router)) HttpRequest(self.0, Some(state), Some(router))
} }
} }
@ -133,7 +133,7 @@ impl<S> HttpRequest<S> {
/// Construct new http request without state. /// Construct new http request without state.
pub fn clone_without_state(&self) -> HttpRequest { pub fn clone_without_state(&self) -> HttpRequest {
HttpRequest(Rc::clone(&self.0), Rc::new(()), None) HttpRequest(Rc::clone(&self.0), None, None)
} }
// get mutable reference for inner message // get mutable reference for inner message
@ -153,7 +153,7 @@ impl<S> HttpRequest<S> {
/// Shared application state /// Shared application state
#[inline] #[inline]
pub fn state(&self) -> &S { pub fn state(&self) -> &S {
&self.1 self.1.as_ref().unwrap()
} }
/// Protocol extensions. /// Protocol extensions.
@ -377,20 +377,20 @@ impl<S> HttpRequest<S> {
/// Returns reference to the associated http payload. /// Returns reference to the associated http payload.
#[inline] #[inline]
pub fn payload(&self) -> &Payload { pub fn payload(&self) -> Option<&Payload> {
&self.0.payload self.0.payload.as_ref()
} }
/// Returns mutable reference to the associated http payload. /// Returns mutable reference to the associated http payload.
#[inline] #[inline]
pub fn payload_mut(&mut self) -> &mut Payload { pub fn payload_mut(&mut self) -> Option<&mut Payload> {
&mut self.as_mut().payload self.as_mut().payload.as_mut()
} }
/// Return payload /// Return payload
#[inline] #[inline]
pub fn take_payload(&mut self) -> Payload { pub fn take_payload(&mut self) -> Option<Payload> {
mem::replace(&mut self.as_mut().payload, Payload::empty()) self.as_mut().payload.take()
} }
/// Return stream to process BODY as multipart. /// Return stream to process BODY as multipart.
@ -398,7 +398,11 @@ impl<S> HttpRequest<S> {
/// Content-type: multipart/form-data; /// Content-type: multipart/form-data;
pub fn multipart(&mut self) -> Result<Multipart, MultipartError> { pub fn multipart(&mut self) -> Result<Multipart, MultipartError> {
let boundary = Multipart::boundary(&self.0.headers)?; let boundary = Multipart::boundary(&self.0.headers)?;
Ok(Multipart::new(boundary, self.take_payload())) if let Some(payload) = self.take_payload() {
Ok(Multipart::new(boundary, payload))
} else {
Err(MultipartError::NoPayload)
}
} }
/// Parse `application/x-www-form-urlencoded` encoded body. /// Parse `application/x-www-form-urlencoded` encoded body.
@ -441,7 +445,11 @@ impl<S> HttpRequest<S> {
}; };
if t { if t {
Ok(UrlEncoded{pl: self.take_payload(), body: BytesMut::new()}) if let Some(payload) = self.take_payload() {
Ok(UrlEncoded{pl: payload, body: BytesMut::new()})
} else {
Err(UrlencodedError::NoPayload)
}
} else { } else {
Err(UrlencodedError::ContentType) Err(UrlencodedError::ContentType)
} }
@ -452,13 +460,13 @@ impl Default for HttpRequest<()> {
/// Construct default request /// Construct default request
fn default() -> HttpRequest { fn default() -> HttpRequest {
HttpRequest(Rc::new(HttpMessage::default()), Rc::new(()), None) HttpRequest(Rc::new(HttpMessage::default()), None, None)
} }
} }
impl<S> Clone for HttpRequest<S> { impl<S> Clone for HttpRequest<S> {
fn clone(&self) -> HttpRequest<S> { fn clone(&self) -> HttpRequest<S> {
HttpRequest(Rc::clone(&self.0), Rc::clone(&self.1), None) HttpRequest(Rc::clone(&self.0), self.1.clone(), None)
} }
} }

View File

@ -222,20 +222,20 @@ struct Parts {
chunked: bool, chunked: bool,
encoding: ContentEncoding, encoding: ContentEncoding,
connection_type: Option<ConnectionType>, connection_type: Option<ConnectionType>,
cookies: CookieJar, cookies: Option<CookieJar>,
} }
impl Parts { impl Parts {
fn new(status: StatusCode) -> Self { fn new(status: StatusCode) -> Self {
Parts { Parts {
version: None, version: None,
headers: HeaderMap::new(), headers: HeaderMap::with_capacity(8),
status: status, status: status,
reason: None, reason: None,
chunked: false, chunked: false,
encoding: ContentEncoding::Auto, encoding: ContentEncoding::Auto,
connection_type: None, connection_type: None,
cookies: CookieJar::new(), cookies: None,
} }
} }
} }
@ -359,7 +359,13 @@ impl HttpResponseBuilder {
/// Set a cookie /// Set a cookie
pub fn cookie<'c>(&mut self, cookie: Cookie<'c>) -> &mut Self { pub fn cookie<'c>(&mut self, cookie: Cookie<'c>) -> &mut Self {
if let Some(parts) = parts(&mut self.parts, &self.err) { if let Some(parts) = parts(&mut self.parts, &self.err) {
parts.cookies.add(cookie.into_owned()); if parts.cookies.is_none() {
let mut jar = CookieJar::new();
jar.add(cookie.into_owned());
parts.cookies = Some(jar)
} else {
parts.cookies.as_mut().unwrap().add(cookie.into_owned());
}
} }
self self
} }
@ -367,9 +373,13 @@ impl HttpResponseBuilder {
/// Remote cookie, cookie has to be cookie from `HttpRequest::cookies()` method. /// Remote cookie, cookie has to be cookie from `HttpRequest::cookies()` method.
pub fn del_cookie<'a>(&mut self, cookie: &Cookie<'a>) -> &mut Self { pub fn del_cookie<'a>(&mut self, cookie: &Cookie<'a>) -> &mut Self {
if let Some(parts) = parts(&mut self.parts, &self.err) { if let Some(parts) = parts(&mut self.parts, &self.err) {
if parts.cookies.is_none() {
parts.cookies = Some(CookieJar::new())
}
let mut jar = parts.cookies.as_mut().unwrap();
let cookie = cookie.clone().into_owned(); let cookie = cookie.clone().into_owned();
parts.cookies.add_original(cookie.clone()); jar.add_original(cookie.clone());
parts.cookies.remove(cookie); jar.remove(cookie);
} }
self self
} }
@ -391,11 +401,13 @@ impl HttpResponseBuilder {
if let Some(e) = self.err.take() { if let Some(e) = self.err.take() {
return Err(e) return Err(e)
} }
for cookie in parts.cookies.delta() { if let Some(jar) = parts.cookies {
for cookie in jar.delta() {
parts.headers.append( parts.headers.append(
header::SET_COOKIE, header::SET_COOKIE,
HeaderValue::from_str(&cookie.to_string())?); HeaderValue::from_str(&cookie.to_string())?);
} }
}
Ok(HttpResponse { Ok(HttpResponse {
version: parts.version, version: parts.version,
headers: parts.headers, headers: parts.headers,

View File

@ -96,11 +96,15 @@ pub fn start<A, S>(mut req: HttpRequest<S>, actor: A) -> Result<Reply, Error>
{ {
let resp = handshake(&req)?; let resp = handshake(&req)?;
let stream = WsStream::new(&mut req); if let Some(payload) = req.take_payload() {
let stream = WsStream::new(payload);
let mut ctx = HttpContext::new(req, actor); let mut ctx = HttpContext::new(req, actor);
ctx.start(resp); ctx.start(resp);
ctx.add_stream(stream); ctx.add_stream(stream);
Ok(ctx.into()) Ok(ctx.into())
} else {
Err(WsHandshakeError::NoPayload.into())
}
} }
/// Prepare `WebSocket` handshake response. /// Prepare `WebSocket` handshake response.
@ -178,8 +182,11 @@ pub struct WsStream {
} }
impl WsStream { impl WsStream {
pub fn new<S>(req: &mut HttpRequest<S>) -> WsStream { pub fn new(payload: Payload) -> WsStream {
WsStream { rx: req.take_payload(), buf: BytesMut::new(), closed: false, error_sent: false } WsStream { rx: payload,
buf: BytesMut::new(),
closed: false,
error_sent: false }
} }
} }