From a38c3985f6101b60253a3b74e8f27661b6b7be5e Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sat, 28 Apr 2018 22:20:32 -0700 Subject: [PATCH 1/2] refactor http1 parser --- src/client/parser.rs | 33 +- src/server/h1.rs | 1348 +++++++++++---------------------------- src/server/h1decoder.rs | 487 ++++++++++++++ src/server/mod.rs | 1 + 4 files changed, 896 insertions(+), 973 deletions(-) create mode 100644 src/server/h1decoder.rs diff --git a/src/client/parser.rs b/src/client/parser.rs index 0d4da4c4..f81aed11 100644 --- a/src/client/parser.rs +++ b/src/client/parser.rs @@ -7,18 +7,18 @@ use std::mem; use error::{ParseError, PayloadError}; -use server::h1::{chunked, Decoder}; +use server::h1decoder::EncodingDecoder; use server::{utils, IoStream}; -use super::ClientResponse; use super::response::ClientMessage; +use super::ClientResponse; const MAX_BUFFER_SIZE: usize = 131_072; const MAX_HEADERS: usize = 96; #[derive(Default)] pub struct HttpResponseParser { - decoder: Option, + decoder: Option, } #[derive(Debug, Fail)] @@ -32,7 +32,7 @@ pub enum HttpResponseParserError { impl HttpResponseParser { pub fn parse( - &mut self, io: &mut T, buf: &mut BytesMut + &mut self, io: &mut T, buf: &mut BytesMut, ) -> Poll where T: IoStream, @@ -75,7 +75,7 @@ impl HttpResponseParser { } pub fn parse_payload( - &mut self, io: &mut T, buf: &mut BytesMut + &mut self, io: &mut T, buf: &mut BytesMut, ) -> Poll, PayloadError> where T: IoStream, @@ -113,8 +113,8 @@ impl HttpResponseParser { } fn parse_message( - buf: &mut BytesMut - ) -> Poll<(ClientResponse, Option), ParseError> { + buf: &mut BytesMut, + ) -> Poll<(ClientResponse, Option), ParseError> { // Parse http message let bytes_ptr = buf.as_ref().as_ptr() as usize; let mut headers: [httparse::Header; MAX_HEADERS] = @@ -160,12 +160,12 @@ impl HttpResponseParser { } let decoder = if status == StatusCode::SWITCHING_PROTOCOLS { - Some(Decoder::eof()) + Some(EncodingDecoder::eof()) } else if let Some(len) = hdrs.get(header::CONTENT_LENGTH) { // Content-Length if let Ok(s) = len.to_str() { if let Ok(len) = s.parse::() { - Some(Decoder::length(len)) + Some(EncodingDecoder::length(len)) } else { debug!("illegal Content-Length: {:?}", len); return Err(ParseError::Header); @@ -176,7 +176,7 @@ impl HttpResponseParser { } } else if chunked(&hdrs)? { // Chunked encoding - Some(Decoder::chunked()) + Some(EncodingDecoder::chunked()) } else { None }; @@ -204,3 +204,16 @@ impl HttpResponseParser { } } } + +/// Check if request has chunked transfer encoding +pub fn chunked(headers: &HeaderMap) -> Result { + 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) + } +} diff --git a/src/server/h1.rs b/src/server/h1.rs index ec0b1938..e411a788 100644 --- a/src/server/h1.rs +++ b/src/server/h1.rs @@ -4,32 +4,29 @@ use std::collections::VecDeque; use std::net::SocketAddr; use std::rc::Rc; use std::time::Duration; -use std::{self, io}; +use std::{io, mem}; use actix::Arbiter; -use bytes::{Bytes, BytesMut}; +use bytes::{BufMut, BytesMut}; use futures::{Async, Future, Poll}; -use http::header::{self, HeaderName, HeaderValue}; -use http::{HeaderMap, HttpTryFrom, Method, Uri, Version}; -use httparse; use tokio_core::reactor::Timeout; -use error::{ParseError, PayloadError, ResponseError}; +use error::PayloadError; use httprequest::HttpRequest; use httpresponse::HttpResponse; use payload::{Payload, PayloadStatus, PayloadWriter}; use pipeline::Pipeline; -use uri::Url; use super::encoding::PayloadType; +use super::h1decoder::{DecoderError, H1Decoder, Message}; use super::h1writer::H1Writer; use super::settings::WorkerSettings; +use super::Writer; use super::{HttpHandler, HttpHandlerTask, IoStream}; -use super::{utils, Writer}; -const MAX_BUFFER_SIZE: usize = 131_072; -const MAX_HEADERS: usize = 96; const MAX_PIPELINED_MESSAGES: usize = 16; +const LW_BUFFER_SIZE: usize = 4096; +const HW_BUFFER_SIZE: usize = 32_768; bitflags! { struct Flags: u8 { @@ -37,6 +34,7 @@ bitflags! { const ERROR = 0b0000_0010; const KEEPALIVE = 0b0000_0100; const SHUTDOWN = 0b0000_1000; + const DISCONNECTED = 0b0001_0000; } } @@ -53,8 +51,9 @@ pub(crate) struct Http1 { settings: Rc>, addr: Option, stream: H1Writer, - reader: Reader, - read_buf: BytesMut, + decoder: H1Decoder, + payload: Option, + buf: BytesMut, tasks: VecDeque, keepalive_timer: Option, } @@ -71,29 +70,42 @@ where { pub fn new( settings: Rc>, stream: T, addr: Option, - read_buf: BytesMut, + buf: BytesMut, ) -> Self { let bytes = settings.get_shared_bytes(); Http1 { flags: Flags::KEEPALIVE, stream: H1Writer::new(stream, bytes, Rc::clone(&settings)), - reader: Reader::new(), + decoder: H1Decoder::new(), + payload: None, tasks: VecDeque::new(), keepalive_timer: None, addr, - read_buf, + buf, settings, } } + #[inline] pub fn settings(&self) -> &WorkerSettings { self.settings.as_ref() } + #[inline] pub(crate) fn io(&mut self) -> &mut T { self.stream.get_mut() } + #[inline] + fn can_read(&self) -> bool { + if let Some(ref info) = self.payload { + info.need_read() == PayloadStatus::Read + } else { + true + } + } + + #[inline] pub fn poll(&mut self) -> Poll<(), ()> { // keep-alive timer if let Some(ref mut timer) = self.keepalive_timer { @@ -119,9 +131,13 @@ where } } + self.poll_io(); + loop { - match self.poll_io()? { - Async::Ready(true) => (), + match self.poll_handler()? { + Async::Ready(true) => { + self.poll_io(); + } Async::Ready(false) => { self.flags.insert(Flags::SHUTDOWN); return self.poll(); @@ -131,93 +147,48 @@ where } } - // TODO: refactor - pub fn poll_io(&mut self) -> Poll { - // read incoming data - let need_read = if !self.flags.intersects(Flags::ERROR) - && self.tasks.len() < MAX_PIPELINED_MESSAGES + #[inline] + pub fn poll_io(&mut self) { + // read io from socket + if !self.flags.intersects(Flags::ERROR) + && self.tasks.len() < MAX_PIPELINED_MESSAGES && self.can_read() { - 'outer: loop { - match self.reader.parse( - self.stream.get_mut(), - &mut self.read_buf, - &self.settings, - ) { - Ok(Async::Ready(mut req)) => { - self.flags.insert(Flags::STARTED); - - // set remote addr - req.set_peer_addr(self.addr); - - // stop keepalive timer - self.keepalive_timer.take(); - - // start request processing - for h in self.settings.handlers().iter_mut() { - req = match h.handle(req) { - Ok(pipe) => { - self.tasks.push_back(Entry { - pipe, - flags: EntryFlags::empty(), - }); - continue 'outer; - } - Err(req) => req, - } - } - - self.tasks.push_back(Entry { - pipe: Pipeline::error(HttpResponse::NotFound()), - flags: EntryFlags::empty(), - }); - continue; + match self.read() { + Ok(true) | Err(_) => { + // notify all tasks + self.stream.disconnected(); + for entry in &mut self.tasks { + entry.pipe.disconnected() } - Ok(Async::NotReady) => (), - Err(err) => { - trace!("Parse error: {:?}", err); + // kill keepalive + self.flags.remove(Flags::KEEPALIVE); + self.keepalive_timer.take(); - // notify all tasks - self.stream.disconnected(); - for entry in &mut self.tasks { - entry.pipe.disconnected() - } + // on parse error, stop reading stream but tasks need to be + // completed + self.flags.insert(Flags::ERROR); - // kill keepalive - self.flags.remove(Flags::KEEPALIVE); - self.keepalive_timer.take(); - - // on parse error, stop reading stream but tasks need to be - // completed - self.flags.insert(Flags::ERROR); - - match err { - ReaderError::Disconnect => (), - _ => if self.tasks.is_empty() { - if let ReaderError::Error(err) = err { - self.tasks.push_back(Entry { - pipe: Pipeline::error(err.error_response()), - flags: EntryFlags::empty(), - }); - } - }, - } + if let Some(ref mut payload) = self.payload { + payload.set_error(PayloadError::Incomplete); } } - break; + Ok(false) => { + self.parse(); + } } - false - } else { - true - }; + } + } - let retry = self.reader.need_read() == PayloadStatus::Read; + pub fn poll_handler(&mut self) -> Poll { + let retry = self.can_read(); // check in-flight messages let mut io = false; let mut idx = 0; while idx < self.tasks.len() { - let item = &mut self.tasks[idx]; + let item: &mut Entry = unsafe { mem::transmute(&mut self.tasks[idx]) }; + // only one task can do io operation in http/1 if !io && !item.flags.contains(EntryFlags::EOF) { // io is corrupted, send buffer if item.flags.contains(EntryFlags::ERROR) { @@ -247,7 +218,8 @@ where } // no more IO for this iteration Ok(Async::NotReady) => { - if self.reader.need_read() == PayloadStatus::Read && !retry { + // check if previously read backpressure was enabled + if self.can_read() && !retry { return Ok(Async::Ready(true)); } io = true; @@ -279,20 +251,20 @@ where } // cleanup finished tasks - let mut popped = false; + let max = self.tasks.len() >= MAX_PIPELINED_MESSAGES; while !self.tasks.is_empty() { if self.tasks[0] .flags .contains(EntryFlags::EOF | EntryFlags::FINISHED) { - popped = true; self.tasks.pop_front(); } else { break; } } - if need_read && popped { - return self.poll_io(); + // read more message + if max && self.tasks.len() >= MAX_PIPELINED_MESSAGES { + return Ok(Async::Ready(true)); } // check stream state @@ -332,736 +304,167 @@ where } Ok(Async::NotReady) } -} -struct Reader { - payload: Option, -} + pub fn parse(&mut self) { + 'outer: loop { + match self.decoder.decode(&mut self.buf, &self.settings) { + Ok(Some(Message::Message { msg, payload })) => { + self.flags.insert(Flags::STARTED); -enum Decoding { - Ready, - NotReady, -} + if payload { + let (ps, pl) = Payload::new(false); + msg.get_mut().payload = Some(pl); + self.payload = + Some(PayloadType::new(&msg.get_ref().headers, ps)); + } -struct PayloadInfo { - tx: PayloadType, - decoder: Decoder, -} + let mut req = HttpRequest::from_message(msg); -#[derive(Debug)] -enum ReaderError { - Disconnect, - Payload, - PayloadDropped, - Error(ParseError), -} + // set remote addr + req.set_peer_addr(self.addr); -impl Reader { - pub fn new() -> Reader { - Reader { payload: None } - } + // stop keepalive timer + self.keepalive_timer.take(); - #[inline] - fn need_read(&self) -> PayloadStatus { - if let Some(ref info) = self.payload { - info.tx.need_read() - } else { - PayloadStatus::Read + // search handler for request + for h in self.settings.handlers().iter_mut() { + req = match h.handle(req) { + Ok(pipe) => { + self.tasks.push_back(Entry { + pipe, + flags: EntryFlags::empty(), + }); + continue 'outer; + } + Err(req) => req, + } + } + + // handler is not found + self.tasks.push_back(Entry { + pipe: Pipeline::error(HttpResponse::NotFound()), + flags: EntryFlags::empty(), + }); + } + Ok(Some(Message::Chunk(chunk))) => { + if let Some(ref mut payload) = self.payload { + payload.feed_data(chunk); + } else { + error!("Internal server error: unexpected payload chunk"); + self.flags.insert(Flags::ERROR); + } + } + Ok(Some(Message::Eof)) => { + if let Some(ref mut payload) = self.payload { + payload.feed_eof(); + } else { + error!("Internal server error: unexpected eof"); + self.flags.insert(Flags::ERROR); + } + } + Ok(None) => break, + Err(e) => { + self.flags.insert(Flags::ERROR); + if let Some(ref mut payload) = self.payload { + let e = match e { + DecoderError::Io(e) => PayloadError::Io(e), + DecoderError::Error(_) => PayloadError::EncodingCorrupted, + }; + payload.set_error(e); + } + } + } } } #[inline] - fn decode( - &mut self, buf: &mut BytesMut, payload: &mut PayloadInfo - ) -> Result { - while !buf.is_empty() { - match payload.decoder.decode(buf) { - Ok(Async::Ready(Some(bytes))) => { - payload.tx.feed_data(bytes); - if payload.decoder.is_eof() { - payload.tx.feed_eof(); - return Ok(Decoding::Ready); - } - } - Ok(Async::Ready(None)) => { - payload.tx.feed_eof(); - return Ok(Decoding::Ready); - } - Ok(Async::NotReady) => return Ok(Decoding::NotReady), - Err(err) => { - payload.tx.set_error(err.into()); - return Err(ReaderError::Payload); - } - } - } - Ok(Decoding::NotReady) - } - - pub fn parse( - &mut self, io: &mut T, buf: &mut BytesMut, settings: &WorkerSettings - ) -> Poll - where - T: IoStream, - { - match self.need_read() { - PayloadStatus::Read => (), - PayloadStatus::Pause => return Ok(Async::NotReady), - PayloadStatus::Dropped => return Err(ReaderError::PayloadDropped), - } - - // read payload - let done = { - if let Some(ref mut payload) = self.payload { - 'buf: loop { - let not_ready = match utils::read_from_io(io, buf) { - Ok(Async::Ready(0)) => { - payload.tx.set_error(PayloadError::Incomplete); - - // http channel should not deal with payload errors - return Err(ReaderError::Payload); - } - Ok(Async::NotReady) => true, - Err(err) => { - payload.tx.set_error(err.into()); - - // http channel should not deal with payload errors - return Err(ReaderError::Payload); - } - _ => false, - }; - loop { - match payload.decoder.decode(buf) { - Ok(Async::Ready(Some(bytes))) => { - payload.tx.feed_data(bytes); - if payload.decoder.is_eof() { - payload.tx.feed_eof(); - break 'buf true; - } - } - Ok(Async::Ready(None)) => { - payload.tx.feed_eof(); - break 'buf true; - } - Ok(Async::NotReady) => { - // if buffer is full then - // socket still can contain more data - if not_ready { - return Ok(Async::NotReady); - } - continue 'buf; - } - Err(err) => { - payload.tx.set_error(err.into()); - return Err(ReaderError::Payload); - } - } - } - } - } else { - false - } - }; - if done { - self.payload = None - } - - // if buf is empty parse_message will always return NotReady, let's avoid that - if buf.is_empty() { - match utils::read_from_io(io, buf) { - Ok(Async::Ready(0)) => return Err(ReaderError::Disconnect), - Ok(Async::Ready(_)) => (), - Ok(Async::NotReady) => return Ok(Async::NotReady), - Err(err) => return Err(ReaderError::Error(err.into())), - } - }; - + fn read(&mut self) -> io::Result { loop { - match Reader::parse_message(buf, settings).map_err(ReaderError::Error)? { - Async::Ready((msg, decoder)) => { - // process payload - if let Some(mut payload) = decoder { - match self.decode(buf, &mut payload)? { - Decoding::Ready => (), - Decoding::NotReady => self.payload = Some(payload), - } - } - return Ok(Async::Ready(msg)); + unsafe { + if self.buf.remaining_mut() < LW_BUFFER_SIZE { + self.buf.reserve(HW_BUFFER_SIZE); } - Async::NotReady => { - if buf.len() >= MAX_BUFFER_SIZE { - error!("MAX_BUFFER_SIZE unprocessed data reached, closing"); - return Err(ReaderError::Error(ParseError::TooLarge)); - } - match utils::read_from_io(io, buf) { - Ok(Async::Ready(0)) => { - debug!("Ignored premature client disconnection"); - return Err(ReaderError::Disconnect); - } - Ok(Async::Ready(_)) => (), - Ok(Async::NotReady) => return Ok(Async::NotReady), - Err(err) => return Err(ReaderError::Error(err.into())), - } - } - } - } - } - - fn parse_message( - buf: &mut BytesMut, settings: &WorkerSettings - ) -> Poll<(HttpRequest, Option), ParseError> { - // Parse http message - let mut has_upgrade = false; - let mut chunked = false; - let mut content_length = None; - - let msg = { - let bytes_ptr = buf.as_ref().as_ptr() as usize; - let mut headers: [httparse::Header; MAX_HEADERS] = - unsafe { std::mem::uninitialized() }; - - let (len, method, path, version, headers_len) = { - let b = unsafe { - let b: &[u8] = buf; - std::mem::transmute(b) - }; - let mut req = httparse::Request::new(&mut headers); - match req.parse(b)? { - httparse::Status::Complete(len) => { - let method = Method::from_bytes(req.method.unwrap().as_bytes()) - .map_err(|_| ParseError::Method)?; - let path = Url::new(Uri::try_from(req.path.unwrap())?); - let version = if req.version.unwrap() == 1 { - Version::HTTP_11 + match self.stream.get_mut().read(self.buf.bytes_mut()) { + Ok(n) => { + if n == 0 { + return Ok(true); } else { - Version::HTTP_10 - }; - (len, method, path, version, req.headers.len()) - } - httparse::Status::Partial => return Ok(Async::NotReady), - } - }; - - let slice = buf.split_to(len).freeze(); - - // convert headers - let msg = settings.get_http_message(); - { - let msg_mut = msg.get_mut(); - msg_mut.keep_alive = version != Version::HTTP_10; - - for header in headers[..headers_len].iter() { - if let Ok(name) = HeaderName::from_bytes(header.name.as_bytes()) { - has_upgrade = has_upgrade || name == header::UPGRADE; - let v_start = header.value.as_ptr() as usize - bytes_ptr; - let v_end = v_start + header.value.len(); - let value = unsafe { - HeaderValue::from_shared_unchecked( - slice.slice(v_start, v_end), - ) - }; - match name { - header::CONTENT_LENGTH => { - if let Ok(s) = value.to_str() { - if let Ok(len) = s.parse::() { - content_length = Some(len) - } else { - debug!("illegal Content-Length: {:?}", len); - return Err(ParseError::Header); - } - } else { - debug!("illegal Content-Length: {:?}", len); - return Err(ParseError::Header); - } - }, - // transfer-encoding - header::TRANSFER_ENCODING => { - if let Ok(s) = value.to_str() { - chunked = s.to_lowercase().contains("chunked"); - } else { - return Err(ParseError::Header) - } - }, - // connection keep-alive state - header::CONNECTION => { - msg_mut.keep_alive = if let Ok(conn) = value.to_str() { - if version == Version::HTTP_10 - && conn.contains("keep-alive") - { - true - } else { - version == Version::HTTP_11 - && !(conn.contains("close") - || conn.contains("upgrade")) - } - } else { - false - }; - }, - _ => (), + self.buf.advance_mut(n); } - - msg_mut.headers.append(name, value); - } else { - return Err(ParseError::Header); } - } - - msg_mut.url = path; - msg_mut.method = method; - msg_mut.version = version; - } - msg - }; - - // https://tools.ietf.org/html/rfc7230#section-3.3.3 - let decoder = if chunked { - // Chunked encoding - Some(Decoder::chunked()) - } else if let Some(len) = content_length { - // Content-Length - Some(Decoder::length(len)) - } else if has_upgrade || msg.get_ref().method == Method::CONNECT { - // upgrade(websocket) or connect - Some(Decoder::eof()) - } else { - None - }; - - if let Some(decoder) = decoder { - let (psender, payload) = Payload::new(false); - let info = PayloadInfo { - tx: PayloadType::new(&msg.get_ref().headers, psender), - decoder, - }; - msg.get_mut().payload = Some(payload); - Ok(Async::Ready(( - HttpRequest::from_message(msg), - Some(info), - ))) - } else { - Ok(Async::Ready((HttpRequest::from_message(msg), None))) - } - } -} - -/// Check if request has chunked transfer encoding -pub fn chunked(headers: &HeaderMap) -> Result { - 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. -/// -/// If a message body does not include a Transfer-Encoding, it *should* -/// include a Content-Length header. -#[derive(Debug, Clone, PartialEq)] -pub struct Decoder { - kind: Kind, -} - -impl Decoder { - pub fn length(x: u64) -> Decoder { - Decoder { - kind: Kind::Length(x), - } - } - - pub fn chunked() -> Decoder { - Decoder { - kind: Kind::Chunked(ChunkedState::Size, 0), - } - } - - pub fn eof() -> Decoder { - Decoder { - kind: Kind::Eof(false), - } - } -} - -#[derive(Debug, Clone, PartialEq)] -enum Kind { - /// A Reader used when a Content-Length header is passed with a positive - /// integer. - Length(u64), - /// A Reader used when Transfer-Encoding is `chunked`. - Chunked(ChunkedState, u64), - /// A Reader used for responses that don't indicate a length or chunked. - /// - /// Note: This should only used for `Response`s. It is illegal for a - /// `Request` to be made with both `Content-Length` and - /// `Transfer-Encoding: chunked` missing, as explained from the spec: - /// - /// > If a Transfer-Encoding header field is present in a response and - /// > the chunked transfer coding is not the final encoding, the - /// > message body length is determined by reading the connection until - /// > it is closed by the server. If a Transfer-Encoding header field - /// > is present in a request and the chunked transfer coding is not - /// > the final encoding, the message body length cannot be determined - /// > reliably; the server MUST respond with the 400 (Bad Request) - /// > status code and then close the connection. - Eof(bool), -} - -#[derive(Debug, PartialEq, Clone)] -enum ChunkedState { - Size, - SizeLws, - Extension, - SizeLf, - Body, - BodyCr, - BodyLf, - EndCr, - EndLf, - End, -} - -impl Decoder { - pub fn is_eof(&self) -> bool { - match self.kind { - Kind::Length(0) | Kind::Chunked(ChunkedState::End, _) | Kind::Eof(true) => { - true - } - _ => false, - } - } - - pub fn decode(&mut self, body: &mut BytesMut) -> Poll, io::Error> { - match self.kind { - Kind::Length(ref mut remaining) => { - if *remaining == 0 { - Ok(Async::Ready(None)) - } else { - if body.is_empty() { - return Ok(Async::NotReady); - } - let len = body.len() as u64; - let buf; - if *remaining > len { - buf = body.take().freeze(); - *remaining -= len; - } else { - buf = body.split_to(*remaining as usize).freeze(); - *remaining = 0; - } - trace!("Length read: {}", buf.len()); - Ok(Async::Ready(Some(buf))) - } - } - Kind::Chunked(ref mut state, ref mut size) => { - loop { - let mut buf = None; - // advances the chunked state - *state = try_ready!(state.step(body, size, &mut buf)); - if *state == ChunkedState::End { - trace!("End of chunked stream"); - return Ok(Async::Ready(None)); - } - if let Some(buf) = buf { - return Ok(Async::Ready(Some(buf))); - } - if body.is_empty() { - return Ok(Async::NotReady); + Err(e) => { + return if e.kind() == io::ErrorKind::WouldBlock { + Ok(false) + } else { + Err(e) + }; } } } - Kind::Eof(ref mut is_eof) => { - if *is_eof { - Ok(Async::Ready(None)) - } else if !body.is_empty() { - Ok(Async::Ready(Some(body.take().freeze()))) - } else { - Ok(Async::NotReady) - } - } - } - } -} - -macro_rules! byte ( - ($rdr:ident) => ({ - if $rdr.len() > 0 { - let b = $rdr[0]; - $rdr.split_to(1); - b - } else { - return Ok(Async::NotReady) - } - }) -); - -impl ChunkedState { - fn step( - &self, body: &mut BytesMut, size: &mut u64, buf: &mut Option - ) -> Poll { - use self::ChunkedState::*; - match *self { - Size => ChunkedState::read_size(body, size), - SizeLws => ChunkedState::read_size_lws(body), - Extension => ChunkedState::read_extension(body), - SizeLf => ChunkedState::read_size_lf(body, size), - Body => ChunkedState::read_body(body, size, buf), - BodyCr => ChunkedState::read_body_cr(body), - BodyLf => ChunkedState::read_body_lf(body), - EndCr => ChunkedState::read_end_cr(body), - EndLf => ChunkedState::read_end_lf(body), - End => Ok(Async::Ready(ChunkedState::End)), - } - } - fn read_size(rdr: &mut BytesMut, size: &mut u64) -> Poll { - let radix = 16; - match byte!(rdr) { - b @ b'0'...b'9' => { - *size *= radix; - *size += u64::from(b - b'0'); - } - b @ b'a'...b'f' => { - *size *= radix; - *size += u64::from(b + 10 - b'a'); - } - b @ b'A'...b'F' => { - *size *= radix; - *size += u64::from(b + 10 - b'A'); - } - b'\t' | b' ' => return Ok(Async::Ready(ChunkedState::SizeLws)), - b';' => return Ok(Async::Ready(ChunkedState::Extension)), - b'\r' => return Ok(Async::Ready(ChunkedState::SizeLf)), - _ => { - return Err(io::Error::new( - io::ErrorKind::InvalidInput, - "Invalid chunk size line: Invalid Size", - )); - } - } - Ok(Async::Ready(ChunkedState::Size)) - } - fn read_size_lws(rdr: &mut BytesMut) -> Poll { - trace!("read_size_lws"); - match byte!(rdr) { - // LWS can follow the chunk size, but no more digits can come - b'\t' | b' ' => Ok(Async::Ready(ChunkedState::SizeLws)), - b';' => Ok(Async::Ready(ChunkedState::Extension)), - b'\r' => Ok(Async::Ready(ChunkedState::SizeLf)), - _ => Err(io::Error::new( - io::ErrorKind::InvalidInput, - "Invalid chunk size linear white space", - )), - } - } - fn read_extension(rdr: &mut BytesMut) -> Poll { - match byte!(rdr) { - b'\r' => Ok(Async::Ready(ChunkedState::SizeLf)), - _ => Ok(Async::Ready(ChunkedState::Extension)), // no supported extensions - } - } - fn read_size_lf( - rdr: &mut BytesMut, size: &mut u64 - ) -> Poll { - match byte!(rdr) { - b'\n' if *size > 0 => Ok(Async::Ready(ChunkedState::Body)), - b'\n' if *size == 0 => Ok(Async::Ready(ChunkedState::EndCr)), - _ => Err(io::Error::new( - io::ErrorKind::InvalidInput, - "Invalid chunk size LF", - )), - } - } - - fn read_body( - rdr: &mut BytesMut, rem: &mut u64, buf: &mut Option - ) -> Poll { - trace!("Chunked read, remaining={:?}", rem); - - let len = rdr.len() as u64; - if len == 0 { - Ok(Async::Ready(ChunkedState::Body)) - } else { - let slice; - if *rem > len { - slice = rdr.take().freeze(); - *rem -= len; - } else { - slice = rdr.split_to(*rem as usize).freeze(); - *rem = 0; - } - *buf = Some(slice); - if *rem > 0 { - Ok(Async::Ready(ChunkedState::Body)) - } else { - Ok(Async::Ready(ChunkedState::BodyCr)) - } - } - } - - fn read_body_cr(rdr: &mut BytesMut) -> Poll { - match byte!(rdr) { - b'\r' => Ok(Async::Ready(ChunkedState::BodyLf)), - _ => Err(io::Error::new( - io::ErrorKind::InvalidInput, - "Invalid chunk body CR", - )), - } - } - fn read_body_lf(rdr: &mut BytesMut) -> Poll { - match byte!(rdr) { - b'\n' => Ok(Async::Ready(ChunkedState::Size)), - _ => Err(io::Error::new( - io::ErrorKind::InvalidInput, - "Invalid chunk body LF", - )), - } - } - fn read_end_cr(rdr: &mut BytesMut) -> Poll { - match byte!(rdr) { - b'\r' => Ok(Async::Ready(ChunkedState::EndLf)), - _ => Err(io::Error::new( - io::ErrorKind::InvalidInput, - "Invalid chunk end CR", - )), - } - } - fn read_end_lf(rdr: &mut BytesMut) -> Poll { - match byte!(rdr) { - b'\n' => Ok(Async::Ready(ChunkedState::End)), - _ => Err(io::Error::new( - io::ErrorKind::InvalidInput, - "Invalid chunk end LF", - )), } } } #[cfg(test)] mod tests { - use bytes::{Buf, Bytes, BytesMut}; - use futures::{Async, Stream}; + use bytes::{Bytes, BytesMut}; use http::{Method, Version}; - use std::net::Shutdown; - use std::{cmp, io, time}; - use tokio_io::{AsyncRead, AsyncWrite}; use super::*; use application::HttpApplication; use httpmessage::HttpMessage; + use server::h1decoder::Message; + use server::helpers::SharedHttpInnerMessage; use server::settings::WorkerSettings; - use server::{IoStream, KeepAlive}; + use server::KeepAlive; - struct Buffer { - buf: Bytes, - err: Option, - } - - impl Buffer { - fn new(data: &'static str) -> Buffer { - Buffer { - buf: Bytes::from(data), - err: None, + impl Message { + fn message(self) -> SharedHttpInnerMessage { + match self { + Message::Message { msg, payload: _ } => msg, + _ => panic!("error"), } } - fn feed_data(&mut self, data: &'static str) { - let mut b = BytesMut::from(self.buf.as_ref()); - b.extend(data.as_bytes()); - self.buf = b.take().freeze(); - } - } - - impl AsyncRead for Buffer {} - impl io::Read for Buffer { - fn read(&mut self, dst: &mut [u8]) -> Result { - if self.buf.is_empty() { - if self.err.is_some() { - Err(self.err.take().unwrap()) - } else { - Err(io::Error::new(io::ErrorKind::WouldBlock, "")) - } - } else { - let size = cmp::min(self.buf.len(), dst.len()); - let b = self.buf.split_to(size); - dst[..size].copy_from_slice(&b); - Ok(size) + fn is_payload(&self) -> bool { + match *self { + Message::Message { msg: _, payload } => payload, + _ => panic!("error"), } } - } - - impl IoStream for Buffer { - fn shutdown(&mut self, _: Shutdown) -> io::Result<()> { - Ok(()) - } - fn set_nodelay(&mut self, _: bool) -> io::Result<()> { - Ok(()) - } - fn set_linger(&mut self, _: Option) -> io::Result<()> { - Ok(()) - } - } - impl io::Write for Buffer { - fn write(&mut self, buf: &[u8]) -> io::Result { - Ok(buf.len()) - } - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } - } - impl AsyncWrite for Buffer { - fn shutdown(&mut self) -> Poll<(), io::Error> { - Ok(Async::Ready(())) - } - fn write_buf(&mut self, _: &mut B) -> Poll { - Ok(Async::NotReady) - } - } - - macro_rules! not_ready { - ($e:expr) => { - match $e { - Ok(Async::NotReady) => (), - Err(err) => unreachable!("Unexpected error: {:?}", err), - _ => unreachable!("Should not be ready"), + fn chunk(self) -> Bytes { + match self { + Message::Chunk(chunk) => chunk, + _ => panic!("error"), } - }; + } + fn eof(&self) -> bool { + match *self { + Message::Eof => true, + _ => false, + } + } } macro_rules! parse_ready { ($e:expr) => {{ let settings: WorkerSettings = WorkerSettings::new(Vec::new(), KeepAlive::Os); - match Reader::new().parse($e, &mut BytesMut::new(), &settings) { - Ok(Async::Ready(req)) => req, + match H1Decoder::new().decode($e, &settings) { + Ok(Some(msg)) => HttpRequest::from_message(msg.message()), Ok(_) => unreachable!("Eof during parsing http request"), Err(err) => unreachable!("Error during parsing http request: {:?}", err), } }}; } - macro_rules! reader_parse_ready { - ($e:expr) => { - match $e { - Ok(Async::Ready(req)) => req, - Ok(_) => unreachable!("Eof during parsing http request"), - Err(err) => { - unreachable!("Error during parsing http request: {:?}", err) - } - } - }; - } - macro_rules! expect_parse_err { ($e:expr) => {{ - let mut buf = BytesMut::new(); let settings: WorkerSettings = WorkerSettings::new(Vec::new(), KeepAlive::Os); - match Reader::new().parse($e, &mut buf, &settings) { + match H1Decoder::new().decode($e, &settings) { Err(err) => match err { - ReaderError::Error(_) => (), + DecoderError::Error(_) => (), _ => unreachable!("Parse error expected"), }, _ => unreachable!("Error expected"), @@ -1071,13 +474,13 @@ mod tests { #[test] fn test_parse() { - let mut buf = Buffer::new("GET /test HTTP/1.1\r\n\r\n"); - let mut readbuf = BytesMut::new(); + let mut buf = BytesMut::from("GET /test HTTP/1.1\r\n\r\n"); let settings = WorkerSettings::::new(Vec::new(), KeepAlive::Os); - let mut reader = Reader::new(); - match reader.parse(&mut buf, &mut readbuf, &settings) { - Ok(Async::Ready(req)) => { + let mut reader = H1Decoder::new(); + match reader.decode(&mut buf, &settings) { + Ok(Some(msg)) => { + let req = HttpRequest::from_message(msg.message()); assert_eq!(req.version(), Version::HTTP_11); assert_eq!(*req.method(), Method::GET); assert_eq!(req.path(), "/test"); @@ -1088,19 +491,19 @@ mod tests { #[test] fn test_parse_partial() { - let mut buf = Buffer::new("PUT /test HTTP/1"); - let mut readbuf = BytesMut::new(); + let mut buf = BytesMut::from("PUT /test HTTP/1"); let settings = WorkerSettings::::new(Vec::new(), KeepAlive::Os); - let mut reader = Reader::new(); - match reader.parse(&mut buf, &mut readbuf, &settings) { - Ok(Async::NotReady) => (), + let mut reader = H1Decoder::new(); + match reader.decode(&mut buf, &settings) { + Ok(None) => (), _ => unreachable!("Error"), } - buf.feed_data(".1\r\n\r\n"); - match reader.parse(&mut buf, &mut readbuf, &settings) { - Ok(Async::Ready(req)) => { + buf.extend(b".1\r\n\r\n"); + match reader.decode(&mut buf, &settings) { + Ok(Some(msg)) => { + let mut req = HttpRequest::from_message(msg.message()); assert_eq!(req.version(), Version::HTTP_11); assert_eq!(*req.method(), Method::PUT); assert_eq!(req.path(), "/test"); @@ -1111,13 +514,13 @@ mod tests { #[test] fn test_parse_post() { - let mut buf = Buffer::new("POST /test2 HTTP/1.0\r\n\r\n"); - let mut readbuf = BytesMut::new(); + let mut buf = BytesMut::from("POST /test2 HTTP/1.0\r\n\r\n"); let settings = WorkerSettings::::new(Vec::new(), KeepAlive::Os); - let mut reader = Reader::new(); - match reader.parse(&mut buf, &mut readbuf, &settings) { - Ok(Async::Ready(req)) => { + let mut reader = H1Decoder::new(); + match reader.decode(&mut buf, &settings) { + Ok(Some(msg)) => { + let mut req = HttpRequest::from_message(msg.message()); assert_eq!(req.version(), Version::HTTP_10); assert_eq!(*req.method(), Method::POST); assert_eq!(req.path(), "/test2"); @@ -1128,17 +531,26 @@ mod tests { #[test] fn test_parse_body() { - let mut buf = Buffer::new("GET /test HTTP/1.1\r\nContent-Length: 4\r\n\r\nbody"); - let mut readbuf = BytesMut::new(); + let mut buf = + BytesMut::from("GET /test HTTP/1.1\r\nContent-Length: 4\r\n\r\nbody"); let settings = WorkerSettings::::new(Vec::new(), KeepAlive::Os); - let mut reader = Reader::new(); - match reader.parse(&mut buf, &mut readbuf, &settings) { - Ok(Async::Ready(mut req)) => { + let mut reader = H1Decoder::new(); + match reader.decode(&mut buf, &settings) { + Ok(Some(msg)) => { + let mut req = HttpRequest::from_message(msg.message()); assert_eq!(req.version(), Version::HTTP_11); assert_eq!(*req.method(), Method::GET); assert_eq!(req.path(), "/test"); - assert_eq!(req.payload_mut().readall().unwrap().as_ref(), b"body"); + assert_eq!( + reader + .decode(&mut buf, &settings) + .unwrap() + .unwrap() + .chunk() + .as_ref(), + b"body" + ); } Ok(_) | Err(_) => unreachable!("Error during parsing http request"), } @@ -1147,17 +559,25 @@ mod tests { #[test] fn test_parse_body_crlf() { let mut buf = - Buffer::new("\r\nGET /test HTTP/1.1\r\nContent-Length: 4\r\n\r\nbody"); - let mut readbuf = BytesMut::new(); + BytesMut::from("\r\nGET /test HTTP/1.1\r\nContent-Length: 4\r\n\r\nbody"); let settings = WorkerSettings::::new(Vec::new(), KeepAlive::Os); - let mut reader = Reader::new(); - match reader.parse(&mut buf, &mut readbuf, &settings) { - Ok(Async::Ready(mut req)) => { + let mut reader = H1Decoder::new(); + match reader.decode(&mut buf, &settings) { + Ok(Some(msg)) => { + let mut req = HttpRequest::from_message(msg.message()); assert_eq!(req.version(), Version::HTTP_11); assert_eq!(*req.method(), Method::GET); assert_eq!(req.path(), "/test"); - assert_eq!(req.payload_mut().readall().unwrap().as_ref(), b"body"); + assert_eq!( + reader + .decode(&mut buf, &settings) + .unwrap() + .unwrap() + .chunk() + .as_ref(), + b"body" + ); } Ok(_) | Err(_) => unreachable!("Error during parsing http request"), } @@ -1165,16 +585,15 @@ mod tests { #[test] fn test_parse_partial_eof() { - let mut buf = Buffer::new("GET /test HTTP/1.1\r\n"); - let mut readbuf = BytesMut::new(); + let mut buf = BytesMut::from("GET /test HTTP/1.1\r\n"); let settings = WorkerSettings::::new(Vec::new(), KeepAlive::Os); + let mut reader = H1Decoder::new(); + assert!(reader.decode(&mut buf, &settings).unwrap().is_none()); - let mut reader = Reader::new(); - not_ready!{ reader.parse(&mut buf, &mut readbuf, &settings) } - - buf.feed_data("\r\n"); - match reader.parse(&mut buf, &mut readbuf, &settings) { - Ok(Async::Ready(req)) => { + buf.extend(b"\r\n"); + match reader.decode(&mut buf, &settings) { + Ok(Some(msg)) => { + let req = HttpRequest::from_message(msg.message()); assert_eq!(req.version(), Version::HTTP_11); assert_eq!(*req.method(), Method::GET); assert_eq!(req.path(), "/test"); @@ -1185,22 +604,22 @@ mod tests { #[test] fn test_headers_split_field() { - let mut buf = Buffer::new("GET /test HTTP/1.1\r\n"); - let mut readbuf = BytesMut::new(); + let mut buf = BytesMut::from("GET /test HTTP/1.1\r\n"); let settings = WorkerSettings::::new(Vec::new(), KeepAlive::Os); - let mut reader = Reader::new(); - not_ready!{ reader.parse(&mut buf, &mut readbuf, &settings) } + let mut reader = H1Decoder::new(); + assert!{ reader.decode(&mut buf, &settings).unwrap().is_none() } - buf.feed_data("t"); - not_ready!{ reader.parse(&mut buf, &mut readbuf, &settings) } + buf.extend(b"t"); + assert!{ reader.decode(&mut buf, &settings).unwrap().is_none() } - buf.feed_data("es"); - not_ready!{ reader.parse(&mut buf, &mut readbuf, &settings) } + buf.extend(b"es"); + assert!{ reader.decode(&mut buf, &settings).unwrap().is_none() } - buf.feed_data("t: value\r\n\r\n"); - match reader.parse(&mut buf, &mut readbuf, &settings) { - Ok(Async::Ready(req)) => { + buf.extend(b"t: value\r\n\r\n"); + match reader.decode(&mut buf, &settings) { + Ok(Some(msg)) => { + let req = HttpRequest::from_message(msg.message()); assert_eq!(req.version(), Version::HTTP_11); assert_eq!(*req.method(), Method::GET); assert_eq!(req.path(), "/test"); @@ -1215,32 +634,28 @@ mod tests { #[test] fn test_headers_multi_value() { - let mut buf = Buffer::new( + let mut buf = BytesMut::from( "GET /test HTTP/1.1\r\n\ Set-Cookie: c1=cookie1\r\n\ Set-Cookie: c2=cookie2\r\n\r\n", ); - let mut readbuf = BytesMut::new(); let settings = WorkerSettings::::new(Vec::new(), KeepAlive::Os); + let mut reader = H1Decoder::new(); + let msg = reader.decode(&mut buf, &settings).unwrap().unwrap(); + let req = HttpRequest::from_message(msg.message()); - let mut reader = Reader::new(); - match reader.parse(&mut buf, &mut readbuf, &settings) { - Ok(Async::Ready(req)) => { - let val: Vec<_> = req.headers() - .get_all("Set-Cookie") - .iter() - .map(|v| v.to_str().unwrap().to_owned()) - .collect(); - assert_eq!(val[0], "c1=cookie1"); - assert_eq!(val[1], "c2=cookie2"); - } - Ok(_) | Err(_) => unreachable!("Error during parsing http request"), - } + let val: Vec<_> = req.headers() + .get_all("Set-Cookie") + .iter() + .map(|v| v.to_str().unwrap().to_owned()) + .collect(); + assert_eq!(val[0], "c1=cookie1"); + assert_eq!(val[1], "c2=cookie2"); } #[test] fn test_conn_default_1_0() { - let mut buf = Buffer::new("GET /test HTTP/1.0\r\n\r\n"); + let mut buf = BytesMut::from("GET /test HTTP/1.0\r\n\r\n"); let req = parse_ready!(&mut buf); assert!(!req.keep_alive()); @@ -1248,7 +663,7 @@ mod tests { #[test] fn test_conn_default_1_1() { - let mut buf = Buffer::new("GET /test HTTP/1.1\r\n\r\n"); + let mut buf = BytesMut::from("GET /test HTTP/1.1\r\n\r\n"); let req = parse_ready!(&mut buf); assert!(req.keep_alive()); @@ -1256,7 +671,7 @@ mod tests { #[test] fn test_conn_close() { - let mut buf = Buffer::new( + let mut buf = BytesMut::from( "GET /test HTTP/1.1\r\n\ connection: close\r\n\r\n", ); @@ -1267,7 +682,7 @@ mod tests { #[test] fn test_conn_close_1_0() { - let mut buf = Buffer::new( + let mut buf = BytesMut::from( "GET /test HTTP/1.0\r\n\ connection: close\r\n\r\n", ); @@ -1278,7 +693,7 @@ mod tests { #[test] fn test_conn_keep_alive_1_0() { - let mut buf = Buffer::new( + let mut buf = BytesMut::from( "GET /test HTTP/1.0\r\n\ connection: keep-alive\r\n\r\n", ); @@ -1289,7 +704,7 @@ mod tests { #[test] fn test_conn_keep_alive_1_1() { - let mut buf = Buffer::new( + let mut buf = BytesMut::from( "GET /test HTTP/1.1\r\n\ connection: keep-alive\r\n\r\n", ); @@ -1300,7 +715,7 @@ mod tests { #[test] fn test_conn_other_1_0() { - let mut buf = Buffer::new( + let mut buf = BytesMut::from( "GET /test HTTP/1.0\r\n\ connection: other\r\n\r\n", ); @@ -1311,7 +726,7 @@ mod tests { #[test] fn test_conn_other_1_1() { - let mut buf = Buffer::new( + let mut buf = BytesMut::from( "GET /test HTTP/1.1\r\n\ connection: other\r\n\r\n", ); @@ -1322,32 +737,30 @@ mod tests { #[test] fn test_conn_upgrade() { - let mut buf = Buffer::new( + let mut buf = BytesMut::from( "GET /test HTTP/1.1\r\n\ upgrade: websockets\r\n\ connection: upgrade\r\n\r\n", ); let req = parse_ready!(&mut buf); - assert!(!req.payload().eof()); assert!(req.upgrade()); } #[test] fn test_conn_upgrade_connect_method() { - let mut buf = Buffer::new( + let mut buf = BytesMut::from( "CONNECT /test HTTP/1.1\r\n\ content-type: text/plain\r\n\r\n", ); let req = parse_ready!(&mut buf); assert!(req.upgrade()); - assert!(!req.payload().eof()); } #[test] fn test_request_chunked() { - let mut buf = Buffer::new( + let mut buf = BytesMut::from( "GET /test HTTP/1.1\r\n\ transfer-encoding: chunked\r\n\r\n", ); @@ -1360,7 +773,7 @@ mod tests { } // type in chunked - let mut buf = Buffer::new( + let mut buf = BytesMut::from( "GET /test HTTP/1.1\r\n\ transfer-encoding: chnked\r\n\r\n", ); @@ -1375,7 +788,7 @@ mod tests { #[test] fn test_headers_content_length_err_1() { - let mut buf = Buffer::new( + let mut buf = BytesMut::from( "GET /test HTTP/1.1\r\n\ content-length: line\r\n\r\n", ); @@ -1385,7 +798,7 @@ mod tests { #[test] fn test_headers_content_length_err_2() { - let mut buf = Buffer::new( + let mut buf = BytesMut::from( "GET /test HTTP/1.1\r\n\ content-length: -1\r\n\r\n", ); @@ -1395,7 +808,7 @@ mod tests { #[test] fn test_invalid_header() { - let mut buf = Buffer::new( + let mut buf = BytesMut::from( "GET /test HTTP/1.1\r\n\ test line\r\n\r\n", ); @@ -1405,7 +818,7 @@ mod tests { #[test] fn test_invalid_name() { - let mut buf = Buffer::new( + let mut buf = BytesMut::from( "GET /test HTTP/1.1\r\n\ test[]: line\r\n\r\n", ); @@ -1415,30 +828,39 @@ mod tests { #[test] fn test_http_request_bad_status_line() { - let mut buf = Buffer::new("getpath \r\n\r\n"); + let mut buf = BytesMut::from("getpath \r\n\r\n"); expect_parse_err!(&mut buf); } #[test] fn test_http_request_upgrade() { - let mut buf = Buffer::new( + let settings = WorkerSettings::::new(Vec::new(), KeepAlive::Os); + let mut buf = BytesMut::from( "GET /test HTTP/1.1\r\n\ connection: upgrade\r\n\ upgrade: websocket\r\n\r\n\ some raw data", ); - let mut req = parse_ready!(&mut buf); + let mut reader = H1Decoder::new(); + let msg = reader.decode(&mut buf, &settings).unwrap().unwrap(); + assert!(msg.is_payload()); + let req = HttpRequest::from_message(msg.message()); assert!(!req.keep_alive()); assert!(req.upgrade()); assert_eq!( - req.payload_mut().readall().unwrap().as_ref(), + reader + .decode(&mut buf, &settings) + .unwrap() + .unwrap() + .chunk() + .as_ref(), b"some raw data" ); } #[test] fn test_http_request_parser_utf8() { - let mut buf = Buffer::new( + let mut buf = BytesMut::from( "GET /test HTTP/1.1\r\n\ x-test: тест\r\n\r\n", ); @@ -1452,7 +874,7 @@ mod tests { #[test] fn test_http_request_parser_two_slashes() { - let mut buf = Buffer::new("GET //path HTTP/1.1\r\n\r\n"); + let mut buf = BytesMut::from("GET //path HTTP/1.1\r\n\r\n"); let req = parse_ready!(&mut buf); assert_eq!(req.path(), "//path"); @@ -1460,175 +882,175 @@ mod tests { #[test] fn test_http_request_parser_bad_method() { - let mut buf = Buffer::new("!12%()+=~$ /get HTTP/1.1\r\n\r\n"); + let mut buf = BytesMut::from("!12%()+=~$ /get HTTP/1.1\r\n\r\n"); expect_parse_err!(&mut buf); } #[test] fn test_http_request_parser_bad_version() { - let mut buf = Buffer::new("GET //get HT/11\r\n\r\n"); + let mut buf = BytesMut::from("GET //get HT/11\r\n\r\n"); expect_parse_err!(&mut buf); } #[test] fn test_http_request_chunked_payload() { - let mut buf = Buffer::new( + let mut buf = BytesMut::from( "GET /test HTTP/1.1\r\n\ transfer-encoding: chunked\r\n\r\n", ); - let mut readbuf = BytesMut::new(); let settings = WorkerSettings::::new(Vec::new(), KeepAlive::Os); - let mut reader = Reader::new(); - let mut req = - reader_parse_ready!(reader.parse(&mut buf, &mut readbuf, &settings)); + let mut reader = H1Decoder::new(); + let msg = reader.decode(&mut buf, &settings).unwrap().unwrap(); + assert!(msg.is_payload()); + let req = HttpRequest::from_message(msg.message()); assert!(req.chunked().unwrap()); - assert!(!req.payload().eof()); - buf.feed_data("4\r\ndata\r\n4\r\nline\r\n0\r\n\r\n"); - let _ = req.payload_mut().poll(); - not_ready!(reader.parse(&mut buf, &mut readbuf, &settings)); - assert!(!req.payload().eof()); + buf.extend(b"4\r\ndata\r\n4\r\nline\r\n0\r\n\r\n"); assert_eq!( - req.payload_mut().readall().unwrap().as_ref(), - b"dataline" + reader + .decode(&mut buf, &settings) + .unwrap() + .unwrap() + .chunk() + .as_ref(), + b"data" + ); + assert_eq!( + reader + .decode(&mut buf, &settings) + .unwrap() + .unwrap() + .chunk() + .as_ref(), + b"line" + ); + assert!( + reader + .decode(&mut buf, &settings) + .unwrap() + .unwrap() + .eof() ); - assert!(req.payload().eof()); } #[test] fn test_http_request_chunked_payload_and_next_message() { - let mut buf = Buffer::new( + let mut buf = BytesMut::from( "GET /test HTTP/1.1\r\n\ transfer-encoding: chunked\r\n\r\n", ); - let mut readbuf = BytesMut::new(); let settings = WorkerSettings::::new(Vec::new(), KeepAlive::Os); - - let mut reader = Reader::new(); - - let mut req = - reader_parse_ready!(reader.parse(&mut buf, &mut readbuf, &settings)); + let mut reader = H1Decoder::new(); + let msg = reader.decode(&mut buf, &settings).unwrap().unwrap(); + assert!(msg.is_payload()); + let req = HttpRequest::from_message(msg.message()); assert!(req.chunked().unwrap()); - assert!(!req.payload().eof()); - buf.feed_data( - "4\r\ndata\r\n4\r\nline\r\n0\r\n\r\n\ - POST /test2 HTTP/1.1\r\n\ - transfer-encoding: chunked\r\n\r\n", + buf.extend( + b"4\r\ndata\r\n4\r\nline\r\n0\r\n\r\n\ + POST /test2 HTTP/1.1\r\n\ + transfer-encoding: chunked\r\n\r\n" + .iter(), ); - let _ = req.payload_mut().poll(); + let msg = reader.decode(&mut buf, &settings).unwrap().unwrap(); + assert_eq!(msg.chunk().as_ref(), b"data"); + let msg = reader.decode(&mut buf, &settings).unwrap().unwrap(); + assert_eq!(msg.chunk().as_ref(), b"line"); + let msg = reader.decode(&mut buf, &settings).unwrap().unwrap(); + assert!(msg.eof()); - let req2 = reader_parse_ready!(reader.parse(&mut buf, &mut readbuf, &settings)); + let msg = reader.decode(&mut buf, &settings).unwrap().unwrap(); + assert!(msg.is_payload()); + let req2 = HttpRequest::from_message(msg.message()); + assert!(req2.chunked().unwrap()); assert_eq!(*req2.method(), Method::POST); assert!(req2.chunked().unwrap()); - assert!(!req2.payload().eof()); - - assert_eq!( - req.payload_mut().readall().unwrap().as_ref(), - b"dataline" - ); - assert!(req.payload().eof()); } #[test] fn test_http_request_chunked_payload_chunks() { - let mut buf = Buffer::new( + let mut buf = BytesMut::from( "GET /test HTTP/1.1\r\n\ transfer-encoding: chunked\r\n\r\n", ); - let mut readbuf = BytesMut::new(); let settings = WorkerSettings::::new(Vec::new(), KeepAlive::Os); - let mut reader = Reader::new(); - let mut req = - reader_parse_ready!(reader.parse(&mut buf, &mut readbuf, &settings)); - req.payload_mut().set_read_buffer_capacity(0); + let mut reader = H1Decoder::new(); + let msg = reader.decode(&mut buf, &settings).unwrap().unwrap(); + assert!(msg.is_payload()); + let req = HttpRequest::from_message(msg.message()); assert!(req.chunked().unwrap()); - assert!(!req.payload().eof()); - buf.feed_data("4\r\n1111\r\n"); - not_ready!(reader.parse(&mut buf, &mut readbuf, &settings)); - assert_eq!(req.payload_mut().readall().unwrap().as_ref(), b"1111"); + buf.extend(b"4\r\n1111\r\n"); + let msg = reader.decode(&mut buf, &settings).unwrap().unwrap(); + assert_eq!(msg.chunk().as_ref(), b"1111"); - buf.feed_data("4\r\ndata\r"); - not_ready!(reader.parse(&mut buf, &mut readbuf, &settings)); + buf.extend(b"4\r\ndata\r"); + let msg = reader.decode(&mut buf, &settings).unwrap().unwrap(); + assert_eq!(msg.chunk().as_ref(), b"data"); - buf.feed_data("\n4"); - not_ready!(reader.parse(&mut buf, &mut readbuf, &settings)); + buf.extend(b"\n4"); + assert!(reader.decode(&mut buf, &settings).unwrap().is_none()); - buf.feed_data("\r"); - not_ready!(reader.parse(&mut buf, &mut readbuf, &settings)); - buf.feed_data("\n"); - not_ready!(reader.parse(&mut buf, &mut readbuf, &settings)); + buf.extend(b"\r"); + assert!(reader.decode(&mut buf, &settings).unwrap().is_none()); + buf.extend(b"\n"); + assert!(reader.decode(&mut buf, &settings).unwrap().is_none()); - buf.feed_data("li"); - not_ready!(reader.parse(&mut buf, &mut readbuf, &settings)); - - buf.feed_data("ne\r\n0\r\n"); - not_ready!(reader.parse(&mut buf, &mut readbuf, &settings)); + buf.extend(b"li"); + let msg = reader.decode(&mut buf, &settings).unwrap().unwrap(); + assert_eq!(msg.chunk().as_ref(), b"li"); //trailers //buf.feed_data("test: test\r\n"); //not_ready!(reader.parse(&mut buf, &mut readbuf)); - let _ = req.payload_mut().poll(); - not_ready!(reader.parse(&mut buf, &mut readbuf, &settings)); + buf.extend(b"ne\r\n0\r\n"); + let msg = reader.decode(&mut buf, &settings).unwrap().unwrap(); + assert_eq!(msg.chunk().as_ref(), b"ne"); + assert!(reader.decode(&mut buf, &settings).unwrap().is_none()); - assert_eq!( - req.payload_mut().readall().unwrap().as_ref(), - b"dataline" + buf.extend(b"\r\n"); + assert!( + reader + .decode(&mut buf, &settings) + .unwrap() + .unwrap() + .eof() ); - assert!(!req.payload().eof()); - - buf.feed_data("\r\n"); - let _ = req.payload_mut().poll(); - not_ready!(reader.parse(&mut buf, &mut readbuf, &settings)); - assert!(req.payload().eof()); } #[test] fn test_parse_chunked_payload_chunk_extension() { - let mut buf = Buffer::new( - "GET /test HTTP/1.1\r\n\ - transfer-encoding: chunked\r\n\r\n", + let mut buf = BytesMut::from( + &"GET /test HTTP/1.1\r\n\ + transfer-encoding: chunked\r\n\r\n"[..], ); - let mut readbuf = BytesMut::new(); let settings = WorkerSettings::::new(Vec::new(), KeepAlive::Os); - let mut reader = Reader::new(); - let mut req = - reader_parse_ready!(reader.parse(&mut buf, &mut readbuf, &settings)); + let mut reader = H1Decoder::new(); + let msg = reader.decode(&mut buf, &settings).unwrap().unwrap(); + assert!(msg.is_payload()); + let req = HttpRequest::from_message(msg.message()); assert!(req.chunked().unwrap()); - assert!(!req.payload().eof()); - buf.feed_data("4;test\r\ndata\r\n4\r\nline\r\n0\r\n\r\n"); // test: test\r\n\r\n") - let _ = req.payload_mut().poll(); - not_ready!(reader.parse(&mut buf, &mut readbuf, &settings)); - assert!(!req.payload().eof()); - assert_eq!( - req.payload_mut().readall().unwrap().as_ref(), - b"dataline" - ); - assert!(req.payload().eof()); + buf.extend(b"4;test\r\ndata\r\n4\r\nline\r\n0\r\n\r\n"); // test: test\r\n\r\n") + let chunk = reader + .decode(&mut buf, &settings) + .unwrap() + .unwrap() + .chunk(); + assert_eq!(chunk, Bytes::from_static(b"data")); + let chunk = reader + .decode(&mut buf, &settings) + .unwrap() + .unwrap() + .chunk(); + assert_eq!(chunk, Bytes::from_static(b"line")); + let msg = reader.decode(&mut buf, &settings).unwrap().unwrap(); + assert!(msg.eof()); } - - /*#[test] - #[should_panic] - fn test_parse_multiline() { - let mut buf = Buffer::new( - "GET /test HTTP/1.1\r\n\ - test: line\r\n \ - continue\r\n\ - test2: data\r\n\ - \r\n", false); - - let mut reader = Reader::new(); - match reader.parse(&mut buf) { - Ok(res) => (), - Err(err) => unreachable!("{:?}", err), - } - }*/ } diff --git a/src/server/h1decoder.rs b/src/server/h1decoder.rs new file mode 100644 index 00000000..d610afc6 --- /dev/null +++ b/src/server/h1decoder.rs @@ -0,0 +1,487 @@ +use std::{io, mem}; + +use bytes::{Bytes, BytesMut}; +use futures::{Async, Poll}; +use httparse; + +use super::helpers::SharedHttpInnerMessage; +use super::settings::WorkerSettings; +use error::ParseError; +use http::header::{HeaderName, HeaderValue}; +use http::{header, HttpTryFrom, Method, Uri, Version}; +use uri::Url; + +const MAX_BUFFER_SIZE: usize = 131_072; +const MAX_HEADERS: usize = 96; + +pub(crate) struct H1Decoder { + decoder: Option, +} + +pub(crate) enum Message { + Message { + msg: SharedHttpInnerMessage, + payload: bool, + }, + Chunk(Bytes), + Eof, +} + +#[derive(Debug)] +pub(crate) enum DecoderError { + Io(io::Error), + Error(ParseError), +} + +impl From for DecoderError { + fn from(err: io::Error) -> DecoderError { + DecoderError::Io(err) + } +} + +impl H1Decoder { + pub fn new() -> H1Decoder { + H1Decoder { decoder: None } + } + + pub fn decode( + &mut self, src: &mut BytesMut, settings: &WorkerSettings, + ) -> Result, DecoderError> { + // read payload + if self.decoder.is_some() { + match self.decoder.as_mut().unwrap().decode(src)? { + Async::Ready(Some(bytes)) => return Ok(Some(Message::Chunk(bytes))), + Async::Ready(None) => { + self.decoder.take(); + return Ok(Some(Message::Eof)); + } + Async::NotReady => return Ok(None), + } + } + + match self.parse_message(src, settings) + .map_err(DecoderError::Error)? + { + Async::Ready((msg, decoder)) => { + if let Some(decoder) = decoder { + self.decoder = Some(decoder); + Ok(Some(Message::Message { + msg, + payload: true, + })) + } else { + Ok(Some(Message::Message { + msg, + payload: false, + })) + } + } + Async::NotReady => { + if src.len() >= MAX_BUFFER_SIZE { + error!("MAX_BUFFER_SIZE unprocessed data reached, closing"); + Err(DecoderError::Error(ParseError::TooLarge)) + } else { + Ok(None) + } + } + } + } + + fn parse_message( + &self, buf: &mut BytesMut, settings: &WorkerSettings, + ) -> Poll<(SharedHttpInnerMessage, Option), ParseError> { + // Parse http message + let mut has_upgrade = false; + let mut chunked = false; + let mut content_length = None; + + let msg = { + let bytes_ptr = buf.as_ref().as_ptr() as usize; + let mut headers: [httparse::Header; MAX_HEADERS] = + unsafe { mem::uninitialized() }; + + let (len, method, path, version, headers_len) = { + let b = unsafe { + let b: &[u8] = buf; + mem::transmute(b) + }; + let mut req = httparse::Request::new(&mut headers); + match req.parse(b)? { + httparse::Status::Complete(len) => { + let method = Method::from_bytes(req.method.unwrap().as_bytes()) + .map_err(|_| ParseError::Method)?; + let path = Url::new(Uri::try_from(req.path.unwrap())?); + let version = if req.version.unwrap() == 1 { + Version::HTTP_11 + } else { + Version::HTTP_10 + }; + (len, method, path, version, req.headers.len()) + } + httparse::Status::Partial => return Ok(Async::NotReady), + } + }; + + let slice = buf.split_to(len).freeze(); + + // convert headers + let msg = settings.get_http_message(); + { + let msg_mut = msg.get_mut(); + msg_mut.keep_alive = version != Version::HTTP_10; + + for header in headers[..headers_len].iter() { + if let Ok(name) = HeaderName::from_bytes(header.name.as_bytes()) { + has_upgrade = has_upgrade || name == header::UPGRADE; + + let v_start = header.value.as_ptr() as usize - bytes_ptr; + let v_end = v_start + header.value.len(); + let value = unsafe { + HeaderValue::from_shared_unchecked( + slice.slice(v_start, v_end), + ) + }; + match name { + header::CONTENT_LENGTH => { + if let Ok(s) = value.to_str() { + if let Ok(len) = s.parse::() { + content_length = Some(len) + } else { + debug!("illegal Content-Length: {:?}", len); + return Err(ParseError::Header); + } + } else { + debug!("illegal Content-Length: {:?}", len); + return Err(ParseError::Header); + } + } + // transfer-encoding + header::TRANSFER_ENCODING => { + if let Ok(s) = value.to_str() { + chunked = s.to_lowercase().contains("chunked"); + } else { + return Err(ParseError::Header); + } + } + // connection keep-alive state + header::CONNECTION => { + msg_mut.keep_alive = if let Ok(conn) = value.to_str() { + if version == Version::HTTP_10 + && conn.contains("keep-alive") + { + true + } else { + version == Version::HTTP_11 + && !(conn.contains("close") + || conn.contains("upgrade")) + } + } else { + false + }; + } + _ => (), + } + + msg_mut.headers.append(name, value); + } else { + return Err(ParseError::Header); + } + } + + msg_mut.url = path; + msg_mut.method = method; + msg_mut.version = version; + } + msg + }; + + // https://tools.ietf.org/html/rfc7230#section-3.3.3 + let decoder = if chunked { + // Chunked encoding + Some(EncodingDecoder::chunked()) + } else if let Some(len) = content_length { + // Content-Length + Some(EncodingDecoder::length(len)) + } else if has_upgrade || msg.get_ref().method == Method::CONNECT { + // upgrade(websocket) or connect + Some(EncodingDecoder::eof()) + } else { + None + }; + + Ok(Async::Ready((msg, decoder))) + } +} + +/// Decoders to handle different Transfer-Encodings. +/// +/// If a message body does not include a Transfer-Encoding, it *should* +/// include a Content-Length header. +#[derive(Debug, Clone, PartialEq)] +pub struct EncodingDecoder { + kind: Kind, +} + +impl EncodingDecoder { + pub fn length(x: u64) -> EncodingDecoder { + EncodingDecoder { + kind: Kind::Length(x), + } + } + + pub fn chunked() -> EncodingDecoder { + EncodingDecoder { + kind: Kind::Chunked(ChunkedState::Size, 0), + } + } + + pub fn eof() -> EncodingDecoder { + EncodingDecoder { + kind: Kind::Eof(false), + } + } +} + +#[derive(Debug, Clone, PartialEq)] +enum Kind { + /// A Reader used when a Content-Length header is passed with a positive + /// integer. + Length(u64), + /// A Reader used when Transfer-Encoding is `chunked`. + Chunked(ChunkedState, u64), + /// A Reader used for responses that don't indicate a length or chunked. + /// + /// Note: This should only used for `Response`s. It is illegal for a + /// `Request` to be made with both `Content-Length` and + /// `Transfer-Encoding: chunked` missing, as explained from the spec: + /// + /// > If a Transfer-Encoding header field is present in a response and + /// > the chunked transfer coding is not the final encoding, the + /// > message body length is determined by reading the connection until + /// > it is closed by the server. If a Transfer-Encoding header field + /// > is present in a request and the chunked transfer coding is not + /// > the final encoding, the message body length cannot be determined + /// > reliably; the server MUST respond with the 400 (Bad Request) + /// > status code and then close the connection. + Eof(bool), +} + +#[derive(Debug, PartialEq, Clone)] +enum ChunkedState { + Size, + SizeLws, + Extension, + SizeLf, + Body, + BodyCr, + BodyLf, + EndCr, + EndLf, + End, +} + +impl EncodingDecoder { + pub fn decode(&mut self, body: &mut BytesMut) -> Poll, io::Error> { + match self.kind { + Kind::Length(ref mut remaining) => { + if *remaining == 0 { + Ok(Async::Ready(None)) + } else { + if body.is_empty() { + return Ok(Async::NotReady); + } + let len = body.len() as u64; + let buf; + if *remaining > len { + buf = body.take().freeze(); + *remaining -= len; + } else { + buf = body.split_to(*remaining as usize).freeze(); + *remaining = 0; + } + trace!("Length read: {}", buf.len()); + Ok(Async::Ready(Some(buf))) + } + } + Kind::Chunked(ref mut state, ref mut size) => { + loop { + let mut buf = None; + // advances the chunked state + *state = try_ready!(state.step(body, size, &mut buf)); + if *state == ChunkedState::End { + trace!("End of chunked stream"); + return Ok(Async::Ready(None)); + } + if let Some(buf) = buf { + return Ok(Async::Ready(Some(buf))); + } + if body.is_empty() { + return Ok(Async::NotReady); + } + } + } + Kind::Eof(ref mut is_eof) => { + if *is_eof { + Ok(Async::Ready(None)) + } else if !body.is_empty() { + Ok(Async::Ready(Some(body.take().freeze()))) + } else { + Ok(Async::NotReady) + } + } + } + } +} + +macro_rules! byte ( + ($rdr:ident) => ({ + if $rdr.len() > 0 { + let b = $rdr[0]; + $rdr.split_to(1); + b + } else { + return Ok(Async::NotReady) + } + }) +); + +impl ChunkedState { + fn step( + &self, body: &mut BytesMut, size: &mut u64, buf: &mut Option, + ) -> Poll { + use self::ChunkedState::*; + match *self { + Size => ChunkedState::read_size(body, size), + SizeLws => ChunkedState::read_size_lws(body), + Extension => ChunkedState::read_extension(body), + SizeLf => ChunkedState::read_size_lf(body, size), + Body => ChunkedState::read_body(body, size, buf), + BodyCr => ChunkedState::read_body_cr(body), + BodyLf => ChunkedState::read_body_lf(body), + EndCr => ChunkedState::read_end_cr(body), + EndLf => ChunkedState::read_end_lf(body), + End => Ok(Async::Ready(ChunkedState::End)), + } + } + fn read_size(rdr: &mut BytesMut, size: &mut u64) -> Poll { + let radix = 16; + match byte!(rdr) { + b @ b'0'...b'9' => { + *size *= radix; + *size += u64::from(b - b'0'); + } + b @ b'a'...b'f' => { + *size *= radix; + *size += u64::from(b + 10 - b'a'); + } + b @ b'A'...b'F' => { + *size *= radix; + *size += u64::from(b + 10 - b'A'); + } + b'\t' | b' ' => return Ok(Async::Ready(ChunkedState::SizeLws)), + b';' => return Ok(Async::Ready(ChunkedState::Extension)), + b'\r' => return Ok(Async::Ready(ChunkedState::SizeLf)), + _ => { + return Err(io::Error::new( + io::ErrorKind::InvalidInput, + "Invalid chunk size line: Invalid Size", + )); + } + } + Ok(Async::Ready(ChunkedState::Size)) + } + fn read_size_lws(rdr: &mut BytesMut) -> Poll { + trace!("read_size_lws"); + match byte!(rdr) { + // LWS can follow the chunk size, but no more digits can come + b'\t' | b' ' => Ok(Async::Ready(ChunkedState::SizeLws)), + b';' => Ok(Async::Ready(ChunkedState::Extension)), + b'\r' => Ok(Async::Ready(ChunkedState::SizeLf)), + _ => Err(io::Error::new( + io::ErrorKind::InvalidInput, + "Invalid chunk size linear white space", + )), + } + } + fn read_extension(rdr: &mut BytesMut) -> Poll { + match byte!(rdr) { + b'\r' => Ok(Async::Ready(ChunkedState::SizeLf)), + _ => Ok(Async::Ready(ChunkedState::Extension)), // no supported extensions + } + } + fn read_size_lf( + rdr: &mut BytesMut, size: &mut u64, + ) -> Poll { + match byte!(rdr) { + b'\n' if *size > 0 => Ok(Async::Ready(ChunkedState::Body)), + b'\n' if *size == 0 => Ok(Async::Ready(ChunkedState::EndCr)), + _ => Err(io::Error::new( + io::ErrorKind::InvalidInput, + "Invalid chunk size LF", + )), + } + } + + fn read_body( + rdr: &mut BytesMut, rem: &mut u64, buf: &mut Option, + ) -> Poll { + trace!("Chunked read, remaining={:?}", rem); + + let len = rdr.len() as u64; + if len == 0 { + Ok(Async::Ready(ChunkedState::Body)) + } else { + let slice; + if *rem > len { + slice = rdr.take().freeze(); + *rem -= len; + } else { + slice = rdr.split_to(*rem as usize).freeze(); + *rem = 0; + } + *buf = Some(slice); + if *rem > 0 { + Ok(Async::Ready(ChunkedState::Body)) + } else { + Ok(Async::Ready(ChunkedState::BodyCr)) + } + } + } + + fn read_body_cr(rdr: &mut BytesMut) -> Poll { + match byte!(rdr) { + b'\r' => Ok(Async::Ready(ChunkedState::BodyLf)), + _ => Err(io::Error::new( + io::ErrorKind::InvalidInput, + "Invalid chunk body CR", + )), + } + } + fn read_body_lf(rdr: &mut BytesMut) -> Poll { + match byte!(rdr) { + b'\n' => Ok(Async::Ready(ChunkedState::Size)), + _ => Err(io::Error::new( + io::ErrorKind::InvalidInput, + "Invalid chunk body LF", + )), + } + } + fn read_end_cr(rdr: &mut BytesMut) -> Poll { + match byte!(rdr) { + b'\r' => Ok(Async::Ready(ChunkedState::EndLf)), + _ => Err(io::Error::new( + io::ErrorKind::InvalidInput, + "Invalid chunk end CR", + )), + } + } + fn read_end_lf(rdr: &mut BytesMut) -> Poll { + match byte!(rdr) { + b'\n' => Ok(Async::Ready(ChunkedState::End)), + _ => Err(io::Error::new( + io::ErrorKind::InvalidInput, + "Invalid chunk end LF", + )), + } + } +} diff --git a/src/server/mod.rs b/src/server/mod.rs index 85faf77b..36d80e2d 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -10,6 +10,7 @@ use tokio_io::{AsyncRead, AsyncWrite}; mod channel; pub(crate) mod encoding; pub(crate) mod h1; +pub(crate) mod h1decoder; mod h1writer; mod h2; mod h2writer; From de49796fd191d755b63c1818524ca2e762b62399 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sat, 28 Apr 2018 22:55:47 -0700 Subject: [PATCH 2/2] clippy warnings; fmt --- rustfmt.toml | 6 +- src/application.rs | 131 +++++---------------- src/body.rs | 4 +- src/client/connector.rs | 37 +++--- src/client/pipeline.rs | 14 +-- src/client/request.rs | 21 +--- src/client/response.rs | 21 ++-- src/client/writer.rs | 17 +-- src/context.rs | 9 +- src/de.rs | 49 ++++---- src/error.rs | 16 +-- src/extractor.rs | 73 ++++-------- src/fs.rs | 110 +++++------------- src/handler.rs | 17 ++- src/header/shared/entity.rs | 31 ++--- src/header/shared/httpdate.rs | 24 +--- src/header/shared/quality_item.rs | 27 ++--- src/helpers.rs | 186 +++++------------------------- src/httpcodes.rs | 161 ++++++++++++++------------ src/httpmessage.rs | 45 +++----- src/httprequest.rs | 41 ++----- src/httpresponse.rs | 115 +++++------------- src/info.rs | 18 ++- src/json.rs | 55 +++------ src/middleware/cors.rs | 126 +++++++------------- src/middleware/csrf.rs | 10 +- src/middleware/defaultheaders.rs | 6 +- src/middleware/errhandlers.rs | 4 +- src/middleware/identity.rs | 24 ++-- src/middleware/logger.rs | 27 ++--- src/middleware/mod.rs | 7 +- src/middleware/session.rs | 23 ++-- src/multipart.rs | 25 ++-- src/param.rs | 18 +-- src/payload.rs | 14 +-- src/pipeline.rs | 55 +++++---- src/pred.rs | 8 +- src/resource.rs | 11 +- src/route.rs | 25 ++-- src/router.rs | 88 +++++--------- src/server/channel.rs | 41 ++++--- src/server/encoding.rs | 13 +-- src/server/h1.rs | 77 ++++--------- src/server/h1decoder.rs | 45 ++++---- src/server/h1writer.rs | 21 ++-- src/server/h2.rs | 2 +- src/server/h2writer.rs | 9 +- src/server/helpers.rs | 59 +++------- src/server/settings.rs | 11 +- src/server/shared.rs | 4 +- src/server/srv.rs | 75 ++++++------ src/server/utils.rs | 2 +- src/server/worker.rs | 98 ++++++++-------- src/test.rs | 27 +++-- src/uri.rs | 5 +- src/with.rs | 36 +++--- src/ws/client.rs | 33 ++---- src/ws/context.rs | 14 +-- src/ws/frame.rs | 25 ++-- src/ws/mask.rs | 6 +- src/ws/mod.rs | 121 ++++++------------- src/ws/proto.rs | 6 +- tests/test_client.rs | 45 ++------ tests/test_handlers.rs | 60 +++------- tests/test_server.rs | 153 +++++++++--------------- tests/test_ws.rs | 57 +++------ tools/wsload/src/wsclient.rs | 110 ++++++++---------- 67 files changed, 988 insertions(+), 1866 deletions(-) diff --git a/rustfmt.toml b/rustfmt.toml index 98d2ba7d..97c6a5aa 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,7 +1,7 @@ max_width = 89 reorder_imports = true -reorder_imports_in_group = true -reorder_imported_names = true +#reorder_imports_in_group = true +#reorder_imported_names = true wrap_comments = true fn_args_density = "Compressed" -#use_small_heuristics = false +use_small_heuristics = false diff --git a/src/application.rs b/src/application.rs index 68aa4a57..33c4453c 100644 --- a/src/application.rs +++ b/src/application.rs @@ -1,6 +1,5 @@ use std::cell::UnsafeCell; use std::collections::HashMap; -use std::mem; use std::rc::Rc; use handler::Reply; @@ -74,7 +73,7 @@ impl HttpApplication { if m { let path: &'static str = unsafe { - mem::transmute(&req.path()[inner.prefix + prefix.len()..]) + &*(&req.path()[inner.prefix + prefix.len()..] as *const _) }; if path.is_empty() { req.match_info_mut().add("tail", ""); @@ -112,12 +111,7 @@ impl HttpHandler for HttpApplication { let mut req = req.with_state(Rc::clone(&self.state), self.router.clone()); let tp = self.get_handler(&mut req); let inner = Rc::clone(&self.inner); - Ok(Box::new(Pipeline::new( - req, - Rc::clone(&self.middlewares), - inner, - tp, - ))) + Ok(Box::new(Pipeline::new(req, Rc::clone(&self.middlewares), inner, tp))) } else { Err(req) } @@ -280,7 +274,7 @@ where { { let parts: &mut ApplicationParts = unsafe { - mem::transmute(self.parts.as_mut().expect("Use after finish")) + &mut *(self.parts.as_mut().expect("Use after finish") as *mut _) }; // get resource handler @@ -455,20 +449,14 @@ where } let parts = self.parts.as_mut().expect("Use after finish"); - parts - .handlers - .push((path, Box::new(WrapHandler::new(handler)))); + parts.handlers.push((path, Box::new(WrapHandler::new(handler)))); } self } /// Register a middleware. pub fn middleware>(mut self, mw: M) -> App { - self.parts - .as_mut() - .expect("Use after finish") - .middlewares - .push(Box::new(mw)); + self.parts.as_mut().expect("Use after finish").middlewares.push(Box::new(mw)); self } @@ -623,9 +611,8 @@ mod tests { #[test] fn test_default_resource() { - let mut app = App::new() - .resource("/test", |r| r.f(|_| HttpResponse::Ok())) - .finish(); + let mut app = + App::new().resource("/test", |r| r.f(|_| HttpResponse::Ok())).finish(); let req = TestRequest::with_uri("/test").finish(); let resp = app.run(req); @@ -633,20 +620,14 @@ mod tests { let req = TestRequest::with_uri("/blah").finish(); let resp = app.run(req); - assert_eq!( - resp.as_response().unwrap().status(), - StatusCode::NOT_FOUND - ); + assert_eq!(resp.as_response().unwrap().status(), StatusCode::NOT_FOUND); let mut app = App::new() .default_resource(|r| r.f(|_| HttpResponse::MethodNotAllowed())) .finish(); let req = TestRequest::with_uri("/blah").finish(); let resp = app.run(req); - assert_eq!( - resp.as_response().unwrap().status(), - StatusCode::METHOD_NOT_ALLOWED - ); + assert_eq!(resp.as_response().unwrap().status(), StatusCode::METHOD_NOT_ALLOWED); } #[test] @@ -660,9 +641,8 @@ mod tests { #[test] fn test_state() { - let mut app = App::with_state(10) - .resource("/", |r| r.f(|_| HttpResponse::Ok())) - .finish(); + let mut app = + App::with_state(10).resource("/", |r| r.f(|_| HttpResponse::Ok())).finish(); let req = HttpRequest::default().with_state(Rc::clone(&app.state), app.router.clone()); let resp = app.run(req); @@ -694,9 +674,7 @@ mod tests { #[test] fn test_handler() { - let mut app = App::new() - .handler("/test", |_| HttpResponse::Ok()) - .finish(); + let mut app = App::new().handler("/test", |_| HttpResponse::Ok()).finish(); let req = TestRequest::with_uri("/test").finish(); let resp = app.run(req); @@ -712,24 +690,16 @@ mod tests { let req = TestRequest::with_uri("/testapp").finish(); let resp = app.run(req); - assert_eq!( - resp.as_response().unwrap().status(), - StatusCode::NOT_FOUND - ); + assert_eq!(resp.as_response().unwrap().status(), StatusCode::NOT_FOUND); let req = TestRequest::with_uri("/blah").finish(); let resp = app.run(req); - assert_eq!( - resp.as_response().unwrap().status(), - StatusCode::NOT_FOUND - ); + assert_eq!(resp.as_response().unwrap().status(), StatusCode::NOT_FOUND); } #[test] fn test_handler2() { - let mut app = App::new() - .handler("test", |_| HttpResponse::Ok()) - .finish(); + let mut app = App::new().handler("test", |_| HttpResponse::Ok()).finish(); let req = TestRequest::with_uri("/test").finish(); let resp = app.run(req); @@ -745,17 +715,11 @@ mod tests { let req = TestRequest::with_uri("/testapp").finish(); let resp = app.run(req); - assert_eq!( - resp.as_response().unwrap().status(), - StatusCode::NOT_FOUND - ); + assert_eq!(resp.as_response().unwrap().status(), StatusCode::NOT_FOUND); let req = TestRequest::with_uri("/blah").finish(); let resp = app.run(req); - assert_eq!( - resp.as_response().unwrap().status(), - StatusCode::NOT_FOUND - ); + assert_eq!(resp.as_response().unwrap().status(), StatusCode::NOT_FOUND); } #[test] @@ -779,68 +743,41 @@ mod tests { let req = TestRequest::with_uri("/prefix/testapp").finish(); let resp = app.run(req); - assert_eq!( - resp.as_response().unwrap().status(), - StatusCode::NOT_FOUND - ); + assert_eq!(resp.as_response().unwrap().status(), StatusCode::NOT_FOUND); let req = TestRequest::with_uri("/prefix/blah").finish(); let resp = app.run(req); - assert_eq!( - resp.as_response().unwrap().status(), - StatusCode::NOT_FOUND - ); + assert_eq!(resp.as_response().unwrap().status(), StatusCode::NOT_FOUND); } #[test] fn test_route() { let mut app = App::new() - .route("/test", Method::GET, |_: HttpRequest| { - HttpResponse::Ok() - }) - .route("/test", Method::POST, |_: HttpRequest| { - HttpResponse::Created() - }) + .route("/test", Method::GET, |_: HttpRequest| HttpResponse::Ok()) + .route("/test", Method::POST, |_: HttpRequest| HttpResponse::Created()) .finish(); - let req = TestRequest::with_uri("/test") - .method(Method::GET) - .finish(); + let req = TestRequest::with_uri("/test").method(Method::GET).finish(); let resp = app.run(req); assert_eq!(resp.as_response().unwrap().status(), StatusCode::OK); - let req = TestRequest::with_uri("/test") - .method(Method::POST) - .finish(); + let req = TestRequest::with_uri("/test").method(Method::POST).finish(); let resp = app.run(req); - assert_eq!( - resp.as_response().unwrap().status(), - StatusCode::CREATED - ); + assert_eq!(resp.as_response().unwrap().status(), StatusCode::CREATED); - let req = TestRequest::with_uri("/test") - .method(Method::HEAD) - .finish(); + let req = TestRequest::with_uri("/test").method(Method::HEAD).finish(); let resp = app.run(req); - assert_eq!( - resp.as_response().unwrap().status(), - StatusCode::NOT_FOUND - ); + assert_eq!(resp.as_response().unwrap().status(), StatusCode::NOT_FOUND); } #[test] fn test_handler_prefix() { - let mut app = App::new() - .prefix("/app") - .handler("/test", |_| HttpResponse::Ok()) - .finish(); + let mut app = + App::new().prefix("/app").handler("/test", |_| HttpResponse::Ok()).finish(); let req = TestRequest::with_uri("/test").finish(); let resp = app.run(req); - assert_eq!( - resp.as_response().unwrap().status(), - StatusCode::NOT_FOUND - ); + assert_eq!(resp.as_response().unwrap().status(), StatusCode::NOT_FOUND); let req = TestRequest::with_uri("/app/test").finish(); let resp = app.run(req); @@ -856,16 +793,10 @@ mod tests { let req = TestRequest::with_uri("/app/testapp").finish(); let resp = app.run(req); - assert_eq!( - resp.as_response().unwrap().status(), - StatusCode::NOT_FOUND - ); + assert_eq!(resp.as_response().unwrap().status(), StatusCode::NOT_FOUND); let req = TestRequest::with_uri("/app/blah").finish(); let resp = app.run(req); - assert_eq!( - resp.as_response().unwrap().status(), - StatusCode::NOT_FOUND - ); + assert_eq!(resp.as_response().unwrap().status(), StatusCode::NOT_FOUND); } } diff --git a/src/body.rs b/src/body.rs index cf54361d..6974fc7a 100644 --- a/src/body.rs +++ b/src/body.rs @@ -258,9 +258,7 @@ impl Responder for Binary { type Error = Error; fn respond_to(self, _: HttpRequest) -> Result { - Ok(HttpResponse::Ok() - .content_type("application/octet-stream") - .body(self)) + Ok(HttpResponse::Ok().content_type("application/octet-stream").body(self)) } } diff --git a/src/client/connector.rs b/src/client/connector.rs index e9eb0813..07ecca93 100644 --- a/src/client/connector.rs +++ b/src/client/connector.rs @@ -94,13 +94,17 @@ pub struct Pause { impl Pause { /// Create message with pause duration parameter pub fn new(time: Duration) -> Pause { - Pause { time: Some(time) } + Pause { + time: Some(time), + } } } impl Default for Pause { fn default() -> Pause { - Pause { time: None } + Pause { + time: None, + } } } @@ -427,8 +431,7 @@ impl ClientConnector { } else { 0 }; - self.acquired_per_host - .insert(key.clone(), per_host + 1); + self.acquired_per_host.insert(key.clone(), per_host + 1); } fn release_key(&mut self, key: &Key) { @@ -439,8 +442,7 @@ impl ClientConnector { return; }; if per_host > 1 { - self.acquired_per_host - .insert(key.clone(), per_host - 1); + self.acquired_per_host.insert(key.clone(), per_host - 1); } else { self.acquired_per_host.remove(key); } @@ -516,9 +518,7 @@ impl ClientConnector { fn collect_periodic(&mut self, ctx: &mut Context) { self.collect(true); // re-schedule next collect period - ctx.run_later(Duration::from_secs(1), |act, ctx| { - act.collect_periodic(ctx) - }); + ctx.run_later(Duration::from_secs(1), |act, ctx| act.collect_periodic(ctx)); // send stats let stats = mem::replace(&mut self.stats, ClientConnectorStats::default()); @@ -570,7 +570,7 @@ impl ClientConnector { } fn wait_for( - &mut self, key: Key, wait: Duration, conn_timeout: Duration + &mut self, key: Key, wait: Duration, conn_timeout: Duration, ) -> oneshot::Receiver> { // connection is not available, wait let (tx, rx) = oneshot::channel(); @@ -583,10 +583,7 @@ impl ClientConnector { wait, conn_timeout, }; - self.waiters - .entry(key) - .or_insert_with(VecDeque::new) - .push_back(waiter); + self.waiters.entry(key).or_insert_with(VecDeque::new).push_back(waiter); rx } } @@ -810,7 +807,7 @@ impl fut::ActorFuture for Maintenance { type Actor = ClientConnector; fn poll( - &mut self, act: &mut ClientConnector, ctx: &mut Context + &mut self, act: &mut ClientConnector, ctx: &mut Context, ) -> Poll { // check pause duration let done = if let Some(Some(ref pause)) = act.paused { @@ -1105,10 +1102,7 @@ impl Pool { if self.to_close.borrow().is_empty() { None } else { - Some(mem::replace( - &mut *self.to_close.borrow_mut(), - Vec::new(), - )) + Some(mem::replace(&mut *self.to_close.borrow_mut(), Vec::new())) } } @@ -1116,10 +1110,7 @@ impl Pool { if self.to_release.borrow().is_empty() { None } else { - Some(mem::replace( - &mut *self.to_release.borrow_mut(), - Vec::new(), - )) + Some(mem::replace(&mut *self.to_release.borrow_mut(), Vec::new())) } } diff --git a/src/client/pipeline.rs b/src/client/pipeline.rs index 1db68b43..a9468805 100644 --- a/src/client/pipeline.rs +++ b/src/client/pipeline.rs @@ -18,9 +18,9 @@ use error::Error; use error::PayloadError; use header::ContentEncoding; use httpmessage::HttpMessage; -use server::WriterState; use server::encoding::PayloadStream; use server::shared::SharedBytes; +use server::WriterState; /// A set of errors that can occur during request sending and response reading #[derive(Fail, Debug)] @@ -80,7 +80,7 @@ impl SendRequest { } pub(crate) fn with_connector( - req: ClientRequest, conn: Addr + req: ClientRequest, conn: Addr, ) -> SendRequest { SendRequest { req, @@ -269,11 +269,7 @@ impl Pipeline { #[inline] fn parse(&mut self) -> Poll { if let Some(ref mut conn) = self.conn { - match self.parser - .as_mut() - .unwrap() - .parse(conn, &mut self.parser_buf) - { + match self.parser.as_mut().unwrap().parse(conn, &mut self.parser_buf) { Ok(Async::Ready(resp)) => { // check content-encoding if self.should_decompress { @@ -469,9 +465,7 @@ impl Pipeline { } // flush io but only if we need to - match self.writer - .poll_completed(self.conn.as_mut().unwrap(), false) - { + match self.writer.poll_completed(self.conn.as_mut().unwrap(), false) { Ok(Async::Ready(_)) => { if self.disconnected || (self.body_completed && self.writer.is_completed()) diff --git a/src/client/request.rs b/src/client/request.rs index 526a8d99..c32b0fad 100644 --- a/src/client/request.rs +++ b/src/client/request.rs @@ -499,10 +499,7 @@ impl ClientRequestBuilder { jar.add(cookie.into_owned()); self.cookies = Some(jar) } else { - self.cookies - .as_mut() - .unwrap() - .add(cookie.into_owned()); + self.cookies.as_mut().unwrap().add(cookie.into_owned()); } self } @@ -594,11 +591,7 @@ impl ClientRequestBuilder { if self.default_headers { // enable br only for https let https = if let Some(parts) = parts(&mut self.request, &self.err) { - parts - .uri - .scheme_part() - .map(|s| s == &uri::Scheme::HTTPS) - .unwrap_or(true) + parts.uri.scheme_part().map(|s| s == &uri::Scheme::HTTPS).unwrap_or(true) } else { true }; @@ -610,9 +603,7 @@ impl ClientRequestBuilder { } } - let mut request = self.request - .take() - .expect("cannot reuse request builder"); + let mut request = self.request.take().expect("cannot reuse request builder"); // set cookies if let Some(ref mut jar) = self.cookies { @@ -657,9 +648,7 @@ impl ClientRequestBuilder { S: Stream + 'static, E: Into, { - self.body(Body::Streaming(Box::new( - stream.map_err(|e| e.into()), - ))) + self.body(Body::Streaming(Box::new(stream.map_err(|e| e.into())))) } /// Set an empty body and generate `ClientRequest` @@ -682,7 +671,7 @@ impl ClientRequestBuilder { #[inline] fn parts<'a>( - parts: &'a mut Option, err: &Option + parts: &'a mut Option, err: &Option, ) -> Option<&'a mut ClientRequest> { if err.is_some() { return None; diff --git a/src/client/response.rs b/src/client/response.rs index 4d186d19..f76d058e 100644 --- a/src/client/response.rs +++ b/src/client/response.rs @@ -103,12 +103,7 @@ impl ClientResponse { impl fmt::Debug for ClientResponse { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let res = writeln!( - f, - "\nClientResponse {:?} {}", - self.version(), - self.status() - ); + let res = writeln!(f, "\nClientResponse {:?} {}", self.version(), self.status()); let _ = writeln!(f, " headers:"); for (key, val) in self.headers().iter() { let _ = writeln!(f, " {:?}: {:?}", key, val); @@ -138,14 +133,12 @@ mod tests { #[test] fn test_debug() { let resp = ClientResponse::new(ClientMessage::default()); - resp.as_mut().headers.insert( - header::COOKIE, - HeaderValue::from_static("cookie1=value1"), - ); - resp.as_mut().headers.insert( - header::COOKIE, - HeaderValue::from_static("cookie2=value2"), - ); + resp.as_mut() + .headers + .insert(header::COOKIE, HeaderValue::from_static("cookie1=value1")); + resp.as_mut() + .headers + .insert(header::COOKIE, HeaderValue::from_static("cookie2=value2")); let dbg = format!("{:?}", resp); assert!(dbg.contains("ClientResponse")); diff --git a/src/client/writer.rs b/src/client/writer.rs index 36c9d6ee..adcc454e 100644 --- a/src/client/writer.rs +++ b/src/client/writer.rs @@ -114,10 +114,7 @@ impl HttpClientWriter { self.buffer, "{} {} {:?}\r", msg.method(), - msg.uri() - .path_and_query() - .map(|u| u.as_str()) - .unwrap_or("/"), + msg.uri().path_and_query().map(|u| u.as_str()).unwrap_or("/"), msg.version() )?; @@ -253,10 +250,8 @@ fn content_encoder(buf: SharedBytes, req: &mut ClientRequest) -> ContentEncoder } let mut b = BytesMut::new(); let _ = write!(b, "{}", bytes.len()); - req.headers_mut().insert( - CONTENT_LENGTH, - HeaderValue::try_from(b.freeze()).unwrap(), - ); + req.headers_mut() + .insert(CONTENT_LENGTH, HeaderValue::try_from(b.freeze()).unwrap()); TransferEncoding::eof(buf) } Body::Streaming(_) | Body::Actor(_) => { @@ -279,10 +274,8 @@ fn content_encoder(buf: SharedBytes, req: &mut ClientRequest) -> ContentEncoder }; if encoding.is_compression() { - req.headers_mut().insert( - CONTENT_ENCODING, - HeaderValue::from_static(encoding.as_str()), - ); + req.headers_mut() + .insert(CONTENT_ENCODING, HeaderValue::from_static(encoding.as_str())); } req.replace_body(body); diff --git a/src/context.rs b/src/context.rs index b095c29b..933fed50 100644 --- a/src/context.rs +++ b/src/context.rs @@ -3,7 +3,6 @@ use futures::unsync::oneshot; use futures::{Async, Future, Poll}; use smallvec::SmallVec; use std::marker::PhantomData; -use std::mem; use actix::dev::{ContextImpl, SyncEnvelope, ToEnvelope}; use actix::fut::ActorFuture; @@ -174,7 +173,9 @@ where if self.stream.is_none() { self.stream = Some(SmallVec::new()); } - self.stream.as_mut().map(|s| s.push(frame)); + if let Some(s) = self.stream.as_mut() { + s.push(frame) + } self.inner.modify(); } @@ -199,7 +200,7 @@ where fn poll(&mut self) -> Poll>, Error> { let ctx: &mut HttpContext = - unsafe { mem::transmute(self as &mut HttpContext) }; + unsafe { &mut *(self as &mut HttpContext as *mut _) }; if self.inner.alive() { match self.inner.poll(ctx) { @@ -261,7 +262,7 @@ impl ActorFuture for Drain { #[inline] fn poll( - &mut self, _: &mut A, _: &mut ::Context + &mut self, _: &mut A, _: &mut ::Context, ) -> Poll { self.fut.poll().map_err(|_| ()) } diff --git a/src/de.rs b/src/de.rs index 47a3f4ff..fa81b77e 100644 --- a/src/de.rs +++ b/src/de.rs @@ -41,7 +41,9 @@ pub struct PathDeserializer<'de, S: 'de> { impl<'de, S: 'de> PathDeserializer<'de, S> { pub fn new(req: &'de HttpRequest) -> Self { - PathDeserializer { req } + PathDeserializer { + req, + } } } @@ -59,7 +61,7 @@ impl<'de, S: 'de> Deserializer<'de> for PathDeserializer<'de, S> { } fn deserialize_struct( - self, _: &'static str, _: &'static [&'static str], visitor: V + self, _: &'static str, _: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, @@ -75,7 +77,7 @@ impl<'de, S: 'de> Deserializer<'de> for PathDeserializer<'de, S> { } fn deserialize_unit_struct( - self, _: &'static str, visitor: V + self, _: &'static str, visitor: V, ) -> Result where V: Visitor<'de>, @@ -84,7 +86,7 @@ impl<'de, S: 'de> Deserializer<'de> for PathDeserializer<'de, S> { } fn deserialize_newtype_struct( - self, _: &'static str, visitor: V + self, _: &'static str, visitor: V, ) -> Result where V: Visitor<'de>, @@ -93,7 +95,7 @@ impl<'de, S: 'de> Deserializer<'de> for PathDeserializer<'de, S> { } fn deserialize_tuple( - self, len: usize, visitor: V + self, len: usize, visitor: V, ) -> Result where V: Visitor<'de>, @@ -114,7 +116,7 @@ impl<'de, S: 'de> Deserializer<'de> for PathDeserializer<'de, S> { } fn deserialize_tuple_struct( - self, _: &'static str, len: usize, visitor: V + self, _: &'static str, len: usize, visitor: V, ) -> Result where V: Visitor<'de>, @@ -135,7 +137,7 @@ impl<'de, S: 'de> Deserializer<'de> for PathDeserializer<'de, S> { } fn deserialize_enum( - self, _: &'static str, _: &'static [&'static str], _: V + self, _: &'static str, _: &'static [&'static str], _: V, ) -> Result where V: Visitor<'de>, @@ -202,11 +204,12 @@ impl<'de> de::MapAccess<'de> for ParamsDeserializer<'de> { where K: de::DeserializeSeed<'de>, { - self.current = self.params - .next() - .map(|&(ref k, ref v)| (k.as_ref(), v.as_ref())); + self.current = + self.params.next().map(|&(ref k, ref v)| (k.as_ref(), v.as_ref())); match self.current { - Some((key, _)) => Ok(Some(seed.deserialize(Key { key })?)), + Some((key, _)) => Ok(Some(seed.deserialize(Key { + key, + })?)), None => Ok(None), } } @@ -216,7 +219,9 @@ impl<'de> de::MapAccess<'de> for ParamsDeserializer<'de> { V: de::DeserializeSeed<'de>, { if let Some((_, value)) = self.current.take() { - seed.deserialize(Value { value }) + seed.deserialize(Value { + value, + }) } else { Err(de::value::Error::custom("unexpected item")) } @@ -301,7 +306,7 @@ impl<'de> Deserializer<'de> for Value<'de> { } fn deserialize_unit_struct( - self, _: &'static str, visitor: V + self, _: &'static str, visitor: V, ) -> Result where V: Visitor<'de>, @@ -331,7 +336,7 @@ impl<'de> Deserializer<'de> for Value<'de> { } fn deserialize_enum( - self, _: &'static str, _: &'static [&'static str], visitor: V + self, _: &'static str, _: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, @@ -342,7 +347,7 @@ impl<'de> Deserializer<'de> for Value<'de> { } fn deserialize_newtype_struct( - self, _: &'static str, visitor: V + self, _: &'static str, visitor: V, ) -> Result where V: Visitor<'de>, @@ -358,7 +363,7 @@ impl<'de> Deserializer<'de> for Value<'de> { } fn deserialize_struct( - self, _: &'static str, _: &'static [&'static str], _: V + self, _: &'static str, _: &'static [&'static str], _: V, ) -> Result where V: Visitor<'de>, @@ -367,14 +372,12 @@ impl<'de> Deserializer<'de> for Value<'de> { } fn deserialize_tuple_struct( - self, _: &'static str, _: usize, _: V + self, _: &'static str, _: usize, _: V, ) -> Result where V: Visitor<'de>, { - Err(de::value::Error::custom( - "unsupported type: tuple struct", - )) + Err(de::value::Error::custom("unsupported type: tuple struct")) } unsupported_type!(deserialize_any, "any"); @@ -416,7 +419,9 @@ impl<'de> de::EnumAccess<'de> for ValueEnum<'de> { V: de::DeserializeSeed<'de>, { Ok(( - seed.deserialize(Key { key: self.value })?, + seed.deserialize(Key { + key: self.value, + })?, UnitVariant, )) } @@ -446,7 +451,7 @@ impl<'de> de::VariantAccess<'de> for UnitVariant { } fn struct_variant( - self, _: &'static [&'static str], _: V + self, _: &'static [&'static str], _: V, ) -> Result where V: Visitor<'de>, diff --git a/src/error.rs b/src/error.rs index 5f660c48..2fa4ba2e 100644 --- a/src/error.rs +++ b/src/error.rs @@ -68,12 +68,7 @@ impl fmt::Debug for Error { if let Some(bt) = self.cause.backtrace() { write!(f, "{:?}\n\n{:?}", &self.cause, bt) } else { - write!( - f, - "{:?}\n\n{:?}", - &self.cause, - self.backtrace.as_ref().unwrap() - ) + write!(f, "{:?}\n\n{:?}", &self.cause, self.backtrace.as_ref().unwrap()) } } } @@ -298,17 +293,16 @@ pub enum HttpRangeError { /// Returned if first-byte-pos of all of the byte-range-spec /// values is greater than the content size. /// See `https://github.com/golang/go/commit/aa9b3d7` - #[fail(display = "First-byte-pos of all of the byte-range-spec values is greater than the content size")] + #[fail( + display = "First-byte-pos of all of the byte-range-spec values is greater than the content size" + )] NoOverlap, } /// Return `BadRequest` for `HttpRangeError` impl ResponseError for HttpRangeError { fn error_response(&self) -> HttpResponse { - HttpResponse::with_body( - StatusCode::BAD_REQUEST, - "Invalid Range header provided", - ) + HttpResponse::with_body(StatusCode::BAD_REQUEST, "Invalid Range header provided") } } diff --git a/src/extractor.rs b/src/extractor.rs index 1aef7ac5..7dd59038 100644 --- a/src/extractor.rs +++ b/src/extractor.rs @@ -110,7 +110,9 @@ where result( de::Deserialize::deserialize(PathDeserializer::new(&req)) .map_err(|e| e.into()) - .map(|inner| Path { inner }), + .map(|inner| Path { + inner, + }), ) } } @@ -246,12 +248,7 @@ where #[inline] fn from_request(req: &HttpRequest, cfg: &Self::Config) -> Self::Result { - Box::new( - UrlEncoded::new(req.clone()) - .limit(cfg.limit) - .from_err() - .map(Form), - ) + Box::new(UrlEncoded::new(req.clone()).limit(cfg.limit).from_err().map(Form)) } } @@ -296,7 +293,9 @@ impl FormConfig { impl Default for FormConfig { fn default() -> Self { - FormConfig { limit: 262_144 } + FormConfig { + limit: 262_144, + } } } @@ -337,11 +336,7 @@ impl FromRequest for Bytes { return Either::A(result(Err(e))); } - Either::B(Box::new( - MessageBody::new(req.clone()) - .limit(cfg.limit) - .from_err(), - )) + Either::B(Box::new(MessageBody::new(req.clone()).limit(cfg.limit).from_err())) } } @@ -387,18 +382,14 @@ impl FromRequest for String { // check charset let encoding = match req.encoding() { Err(_) => { - return Either::A(result(Err(ErrorBadRequest( - "Unknown request charset", - )))) + return Either::A(result(Err(ErrorBadRequest("Unknown request charset")))) } Ok(encoding) => encoding, }; Either::B(Box::new( - MessageBody::new(req.clone()) - .limit(cfg.limit) - .from_err() - .and_then(move |body| { + MessageBody::new(req.clone()).limit(cfg.limit).from_err().and_then( + move |body| { let enc: *const Encoding = encoding as *const Encoding; if enc == UTF_8 { Ok(str::from_utf8(body.as_ref()) @@ -409,7 +400,8 @@ impl FromRequest for String { .decode(&body, DecoderTrap::Strict) .map_err(|_| ErrorBadRequest("Can not decode body"))?) } - }), + }, + ), )) } } @@ -485,8 +477,7 @@ mod tests { fn test_bytes() { let cfg = PayloadConfig::default(); let mut req = TestRequest::with_header(header::CONTENT_LENGTH, "11").finish(); - req.payload_mut() - .unread_data(Bytes::from_static(b"hello=world")); + req.payload_mut().unread_data(Bytes::from_static(b"hello=world")); match Bytes::from_request(&req, &cfg).poll().unwrap() { Async::Ready(s) => { @@ -500,8 +491,7 @@ mod tests { fn test_string() { let cfg = PayloadConfig::default(); let mut req = TestRequest::with_header(header::CONTENT_LENGTH, "11").finish(); - req.payload_mut() - .unread_data(Bytes::from_static(b"hello=world")); + req.payload_mut().unread_data(Bytes::from_static(b"hello=world")); match String::from_request(&req, &cfg).poll().unwrap() { Async::Ready(s) => { @@ -518,8 +508,7 @@ mod tests { "application/x-www-form-urlencoded", ).header(header::CONTENT_LENGTH, "11") .finish(); - req.payload_mut() - .unread_data(Bytes::from_static(b"hello=world")); + req.payload_mut().unread_data(Bytes::from_static(b"hello=world")); let mut cfg = FormConfig::default(); cfg.limit(4096); @@ -573,17 +562,11 @@ mod tests { let mut resource = ResourceHandler::<()>::default(); resource.name("index"); let mut routes = Vec::new(); - routes.push(( - Resource::new("index", "/{key}/{value}/"), - Some(resource), - )); + routes.push((Resource::new("index", "/{key}/{value}/"), Some(resource))); let (router, _) = Router::new("", ServerSettings::default(), routes); assert!(router.recognize(&mut req).is_some()); - match Path::::from_request(&req, &()) - .poll() - .unwrap() - { + match Path::::from_request(&req, &()).poll().unwrap() { Async::Ready(s) => { assert_eq!(s.key, "name"); assert_eq!(s.value, "user1"); @@ -591,10 +574,7 @@ mod tests { _ => unreachable!(), } - match Path::<(String, String)>::from_request(&req, &()) - .poll() - .unwrap() - { + match Path::<(String, String)>::from_request(&req, &()).poll().unwrap() { Async::Ready(s) => { assert_eq!(s.0, "name"); assert_eq!(s.1, "user1"); @@ -620,10 +600,7 @@ mod tests { _ => unreachable!(), } - match Path::<(String, u8)>::from_request(&req, &()) - .poll() - .unwrap() - { + match Path::<(String, u8)>::from_request(&req, &()).poll().unwrap() { Async::Ready(s) => { assert_eq!(s.0, "name"); assert_eq!(s.1, 32); @@ -631,15 +608,9 @@ mod tests { _ => unreachable!(), } - match Path::>::from_request(&req, &()) - .poll() - .unwrap() - { + match Path::>::from_request(&req, &()).poll().unwrap() { Async::Ready(s) => { - assert_eq!( - s.into_inner(), - vec!["name".to_owned(), "32".to_owned()] - ); + assert_eq!(s.into_inner(), vec!["name".to_owned(), "32".to_owned()]); } _ => unreachable!(), } diff --git a/src/fs.rs b/src/fs.rs index ce0e42d5..700b69ed 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -202,15 +202,12 @@ impl Responder for NamedFile { if self.status_code != StatusCode::OK { let mut resp = HttpResponse::build(self.status_code); resp.if_some(self.path().extension(), |ext, resp| { - resp.set(header::ContentType(get_mime_type( - &ext.to_string_lossy(), - ))); + resp.set(header::ContentType(get_mime_type(&ext.to_string_lossy()))); }); let reader = ChunkedReadFile { size: self.md.len(), offset: 0, - cpu_pool: self.cpu_pool - .unwrap_or_else(|| req.cpu_pool().clone()), + cpu_pool: self.cpu_pool.unwrap_or_else(|| req.cpu_pool().clone()), file: Some(self.file), fut: None, }; @@ -253,9 +250,7 @@ impl Responder for NamedFile { let mut resp = HttpResponse::build(self.status_code); resp.if_some(self.path().extension(), |ext, resp| { - resp.set(header::ContentType(get_mime_type( - &ext.to_string_lossy(), - ))); + resp.set(header::ContentType(get_mime_type(&ext.to_string_lossy()))); }).if_some(last_modified, |lm, resp| { resp.set(header::LastModified(lm)); }) @@ -275,8 +270,7 @@ impl Responder for NamedFile { let reader = ChunkedReadFile { size: self.md.len(), offset: 0, - cpu_pool: self.cpu_pool - .unwrap_or_else(|| req.cpu_pool().clone()), + cpu_pool: self.cpu_pool.unwrap_or_else(|| req.cpu_pool().clone()), file: Some(self.file), fut: None, }; @@ -344,7 +338,10 @@ pub struct Directory { impl Directory { pub fn new(base: PathBuf, path: PathBuf) -> Directory { - Directory { base, path } + Directory { + base, + path, + } } fn can_list(&self, entry: &io::Result) -> bool { @@ -414,9 +411,7 @@ impl Responder for Directory { \n", index_of, index_of, body ); - Ok(HttpResponse::Ok() - .content_type("text/html; charset=utf-8") - .body(html)) + Ok(HttpResponse::Ok().content_type("text/html; charset=utf-8").body(html)) } } @@ -541,13 +536,12 @@ impl Handler for StaticFiles { if !self.accessible { Ok(self.default.handle(req)) } else { - let relpath = match req.match_info() - .get("tail") - .map(|tail| PathBuf::from_param(tail)) - { - Some(Ok(path)) => path, - _ => return Ok(self.default.handle(req)), - }; + let relpath = + match req.match_info().get("tail").map(|tail| PathBuf::from_param(tail)) + { + Some(Ok(path)) => path, + _ => return Ok(self.default.handle(req)), + }; // full filepath let path = self.directory.join(&relpath).canonicalize()?; @@ -597,9 +591,8 @@ mod tests { #[test] fn test_named_file() { assert!(NamedFile::open("test--").is_err()); - let mut file = NamedFile::open("Cargo.toml") - .unwrap() - .set_cpu_pool(CpuPool::new(1)); + let mut file = + NamedFile::open("Cargo.toml").unwrap().set_cpu_pool(CpuPool::new(1)); { file.file(); let _f: &File = &file; @@ -609,10 +602,7 @@ mod tests { } let resp = file.respond_to(HttpRequest::default()).unwrap(); - assert_eq!( - resp.headers().get(header::CONTENT_TYPE).unwrap(), - "text/x-toml" - ) + assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(), "text/x-toml") } #[test] @@ -630,10 +620,7 @@ mod tests { } let resp = file.respond_to(HttpRequest::default()).unwrap(); - assert_eq!( - resp.headers().get(header::CONTENT_TYPE).unwrap(), - "text/x-toml" - ); + assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(), "text/x-toml"); assert_eq!(resp.status(), StatusCode::NOT_FOUND); } @@ -676,9 +663,7 @@ mod tests { req.match_info_mut().add("tail", ""); st.show_index = true; - let resp = st.handle(req) - .respond_to(HttpRequest::default()) - .unwrap(); + let resp = st.handle(req).respond_to(HttpRequest::default()).unwrap(); let resp = resp.as_response().expect("HTTP Response"); assert_eq!( resp.headers().get(header::CONTENT_TYPE).unwrap(), @@ -694,28 +679,18 @@ mod tests { let mut req = HttpRequest::default(); req.match_info_mut().add("tail", "tests"); - let resp = st.handle(req) - .respond_to(HttpRequest::default()) - .unwrap(); + let resp = st.handle(req).respond_to(HttpRequest::default()).unwrap(); let resp = resp.as_response().expect("HTTP Response"); assert_eq!(resp.status(), StatusCode::FOUND); - assert_eq!( - resp.headers().get(header::LOCATION).unwrap(), - "/tests/index.html" - ); + assert_eq!(resp.headers().get(header::LOCATION).unwrap(), "/tests/index.html"); let mut req = HttpRequest::default(); req.match_info_mut().add("tail", "tests/"); - let resp = st.handle(req) - .respond_to(HttpRequest::default()) - .unwrap(); + let resp = st.handle(req).respond_to(HttpRequest::default()).unwrap(); let resp = resp.as_response().expect("HTTP Response"); assert_eq!(resp.status(), StatusCode::FOUND); - assert_eq!( - resp.headers().get(header::LOCATION).unwrap(), - "/tests/index.html" - ); + assert_eq!(resp.headers().get(header::LOCATION).unwrap(), "/tests/index.html"); } #[test] @@ -724,9 +699,7 @@ mod tests { let mut req = HttpRequest::default(); req.match_info_mut().add("tail", "tools/wsload"); - let resp = st.handle(req) - .respond_to(HttpRequest::default()) - .unwrap(); + let resp = st.handle(req).respond_to(HttpRequest::default()).unwrap(); let resp = resp.as_response().expect("HTTP Response"); assert_eq!(resp.status(), StatusCode::FOUND); assert_eq!( @@ -746,23 +719,13 @@ mod tests { let request = srv.get().uri(srv.url("/public")).finish().unwrap(); let response = srv.execute(request.send()).unwrap(); assert_eq!(response.status(), StatusCode::FOUND); - let loc = response - .headers() - .get(header::LOCATION) - .unwrap() - .to_str() - .unwrap(); + let loc = response.headers().get(header::LOCATION).unwrap().to_str().unwrap(); assert_eq!(loc, "/public/Cargo.toml"); let request = srv.get().uri(srv.url("/public/")).finish().unwrap(); let response = srv.execute(request.send()).unwrap(); assert_eq!(response.status(), StatusCode::FOUND); - let loc = response - .headers() - .get(header::LOCATION) - .unwrap() - .to_str() - .unwrap(); + let loc = response.headers().get(header::LOCATION).unwrap().to_str().unwrap(); assert_eq!(loc, "/public/Cargo.toml"); } @@ -775,23 +738,13 @@ mod tests { let request = srv.get().uri(srv.url("/test")).finish().unwrap(); let response = srv.execute(request.send()).unwrap(); assert_eq!(response.status(), StatusCode::FOUND); - let loc = response - .headers() - .get(header::LOCATION) - .unwrap() - .to_str() - .unwrap(); + let loc = response.headers().get(header::LOCATION).unwrap().to_str().unwrap(); assert_eq!(loc, "/test/Cargo.toml"); let request = srv.get().uri(srv.url("/test/")).finish().unwrap(); let response = srv.execute(request.send()).unwrap(); assert_eq!(response.status(), StatusCode::FOUND); - let loc = response - .headers() - .get(header::LOCATION) - .unwrap() - .to_str() - .unwrap(); + let loc = response.headers().get(header::LOCATION).unwrap().to_str().unwrap(); assert_eq!(loc, "/test/Cargo.toml"); } @@ -801,10 +754,7 @@ mod tests { App::new().handler("test", StaticFiles::new(".").index_file("Cargo.toml")) }); - let request = srv.get() - .uri(srv.url("/test/%43argo.toml")) - .finish() - .unwrap(); + let request = srv.get().uri(srv.url("/test/%43argo.toml")).finish().unwrap(); let response = srv.execute(request.send()).unwrap(); assert_eq!(response.status(), StatusCode::OK); } diff --git a/src/handler.rs b/src/handler.rs index 6da1f886..854f3a11 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -1,5 +1,5 @@ -use futures::Poll; use futures::future::{err, ok, Future, FutureResult}; +use futures::Poll; use std::marker::PhantomData; use std::ops::Deref; @@ -296,14 +296,13 @@ where #[inline] fn respond_to(self, req: HttpRequest) -> Result { - let fut = self.map_err(|e| e.into()) - .then(move |r| match r.respond_to(req) { - Ok(reply) => match reply.into().0 { - ReplyItem::Message(resp) => ok(resp), - _ => panic!("Nested async replies are not supported"), - }, - Err(e) => err(e), - }); + let fut = self.map_err(|e| e.into()).then(move |r| match r.respond_to(req) { + Ok(reply) => match reply.into().0 { + ReplyItem::Message(resp) => ok(resp), + _ => panic!("Nested async replies are not supported"), + }, + Err(e) => err(e), + }); Ok(Reply::async(fut)) } } diff --git a/src/header/shared/entity.rs b/src/header/shared/entity.rs index 347c4c02..c80bb182 100644 --- a/src/header/shared/entity.rs +++ b/src/header/shared/entity.rs @@ -57,7 +57,10 @@ impl EntityTag { /// If the tag contains invalid characters. pub fn new(weak: bool, tag: String) -> EntityTag { assert!(check_slice_validity(&tag), "Invalid tag: {:?}", tag); - EntityTag { weak, tag } + EntityTag { + weak, + tag, + } } /// Constructs a new weak EntityTag. @@ -196,11 +199,7 @@ mod tests { fn test_etag_parse_failures() { // Expected failures assert!("no-dquotes".parse::().is_err()); - assert!( - "w/\"the-first-w-is-case-sensitive\"" - .parse::() - .is_err() - ); + assert!("w/\"the-first-w-is-case-sensitive\"".parse::().is_err()); assert!("".parse::().is_err()); assert!("\"unmatched-dquotes1".parse::().is_err()); assert!("unmatched-dquotes2\"".parse::().is_err()); @@ -209,26 +208,14 @@ mod tests { #[test] fn test_etag_fmt() { - assert_eq!( - format!("{}", EntityTag::strong("foobar".to_owned())), - "\"foobar\"" - ); - assert_eq!( - format!("{}", EntityTag::strong("".to_owned())), - "\"\"" - ); + assert_eq!(format!("{}", EntityTag::strong("foobar".to_owned())), "\"foobar\""); + assert_eq!(format!("{}", EntityTag::strong("".to_owned())), "\"\""); assert_eq!( format!("{}", EntityTag::weak("weak-etag".to_owned())), "W/\"weak-etag\"" ); - assert_eq!( - format!("{}", EntityTag::weak("\u{0065}".to_owned())), - "W/\"\x65\"" - ); - assert_eq!( - format!("{}", EntityTag::weak("".to_owned())), - "W/\"\"" - ); + assert_eq!(format!("{}", EntityTag::weak("\u{0065}".to_owned())), "W/\"\x65\""); + assert_eq!(format!("{}", EntityTag::weak("".to_owned())), "W/\"\""); } #[test] diff --git a/src/header/shared/httpdate.rs b/src/header/shared/httpdate.rs index 5de1e3f9..a6309ae0 100644 --- a/src/header/shared/httpdate.rs +++ b/src/header/shared/httpdate.rs @@ -64,11 +64,7 @@ impl IntoHeaderValue for HttpDate { fn try_into(self) -> Result { let mut wrt = BytesMut::with_capacity(29).writer(); write!(wrt, "{}", self.0.rfc822()).unwrap(); - unsafe { - Ok(HeaderValue::from_shared_unchecked( - wrt.get_mut().take().freeze(), - )) - } + unsafe { Ok(HeaderValue::from_shared_unchecked(wrt.get_mut().take().freeze())) } } } @@ -104,24 +100,12 @@ mod tests { #[test] fn test_date() { + assert_eq!("Sun, 07 Nov 1994 08:48:37 GMT".parse::().unwrap(), NOV_07); assert_eq!( - "Sun, 07 Nov 1994 08:48:37 GMT" - .parse::() - .unwrap(), - NOV_07 - ); - assert_eq!( - "Sunday, 07-Nov-94 08:48:37 GMT" - .parse::() - .unwrap(), - NOV_07 - ); - assert_eq!( - "Sun Nov 7 08:48:37 1994" - .parse::() - .unwrap(), + "Sunday, 07-Nov-94 08:48:37 GMT".parse::().unwrap(), NOV_07 ); + assert_eq!("Sun Nov 7 08:48:37 1994".parse::().unwrap(), NOV_07); assert!("this-is-no-date".parse::().is_err()); } } diff --git a/src/header/shared/quality_item.rs b/src/header/shared/quality_item.rs index 5f1e5977..1734db45 100644 --- a/src/header/shared/quality_item.rs +++ b/src/header/shared/quality_item.rs @@ -47,7 +47,10 @@ impl QualityItem { /// The item can be of any type. /// The quality should be a value in the range [0, 1]. pub fn new(item: T, quality: Quality) -> QualityItem { - QualityItem { item, quality } + QualityItem { + item, + quality, + } } } @@ -63,11 +66,7 @@ impl fmt::Display for QualityItem { match self.quality.0 { 1000 => Ok(()), 0 => f.write_str("; q=0"), - x => write!( - f, - "; q=0.{}", - format!("{:03}", x).trim_right_matches('0') - ), + x => write!(f, "; q=0.{}", format!("{:03}", x).trim_right_matches('0')), } } } @@ -120,10 +119,7 @@ fn from_f32(f: f32) -> Quality { // this function is only used internally. A check that `f` is within range // should be done before calling this method. Just in case, this // debug_assert should catch if we were forgetful - debug_assert!( - f >= 0f32 && f <= 1f32, - "q value must be between 0.0 and 1.0" - ); + debug_assert!(f >= 0f32 && f <= 1f32, "q value must be between 0.0 and 1.0"); Quality((f * 1000f32) as u16) } @@ -156,10 +152,7 @@ mod internal { impl IntoQuality for f32 { fn into_quality(self) -> Quality { - assert!( - self >= 0f32 && self <= 1f32, - "float must be between 0.0 and 1.0" - ); + assert!(self >= 0f32 && self <= 1f32, "float must be between 0.0 and 1.0"); super::from_f32(self) } } @@ -295,10 +288,6 @@ mod tests { #[test] fn test_fuzzing_bugs() { assert!("99999;".parse::>().is_err()); - assert!( - "\x0d;;;=\u{d6aa}==" - .parse::>() - .is_err() - ) + assert!("\x0d;;;=\u{d6aa}==".parse::>().is_err()) } } diff --git a/src/helpers.rs b/src/helpers.rs index fda28f38..dc392d7a 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -190,16 +190,8 @@ mod tests { // trailing slashes let params = vec![ ("/resource1", "", StatusCode::OK), - ( - "/resource1/", - "/resource1", - StatusCode::MOVED_PERMANENTLY, - ), - ( - "/resource2", - "/resource2/", - StatusCode::MOVED_PERMANENTLY, - ), + ("/resource1/", "/resource1", StatusCode::MOVED_PERMANENTLY), + ("/resource2", "/resource2/", StatusCode::MOVED_PERMANENTLY), ("/resource2/", "", StatusCode::OK), ("/resource1?p1=1&p2=2", "", StatusCode::OK), ( @@ -222,11 +214,7 @@ mod tests { if !target.is_empty() { assert_eq!( target, - r.headers() - .get(header::LOCATION) - .unwrap() - .to_str() - .unwrap() + r.headers().get(header::LOCATION).unwrap().to_str().unwrap() ); } } @@ -238,11 +226,7 @@ mod tests { .resource("/resource1", |r| r.method(Method::GET).f(index)) .resource("/resource2/", |r| r.method(Method::GET).f(index)) .default_resource(|r| { - r.h(NormalizePath::new( - false, - true, - StatusCode::MOVED_PERMANENTLY, - )) + r.h(NormalizePath::new(false, true, StatusCode::MOVED_PERMANENTLY)) }) .finish(); @@ -276,46 +260,14 @@ mod tests { // trailing slashes let params = vec![ ("/resource1/a/b", "", StatusCode::OK), - ( - "/resource1/", - "/resource1", - StatusCode::MOVED_PERMANENTLY, - ), - ( - "/resource1//", - "/resource1", - StatusCode::MOVED_PERMANENTLY, - ), - ( - "//resource1//a//b", - "/resource1/a/b", - StatusCode::MOVED_PERMANENTLY, - ), - ( - "//resource1//a//b/", - "/resource1/a/b", - StatusCode::MOVED_PERMANENTLY, - ), - ( - "//resource1//a//b//", - "/resource1/a/b", - StatusCode::MOVED_PERMANENTLY, - ), - ( - "///resource1//a//b", - "/resource1/a/b", - StatusCode::MOVED_PERMANENTLY, - ), - ( - "/////resource1/a///b", - "/resource1/a/b", - StatusCode::MOVED_PERMANENTLY, - ), - ( - "/////resource1/a//b/", - "/resource1/a/b", - StatusCode::MOVED_PERMANENTLY, - ), + ("/resource1/", "/resource1", StatusCode::MOVED_PERMANENTLY), + ("/resource1//", "/resource1", StatusCode::MOVED_PERMANENTLY), + ("//resource1//a//b", "/resource1/a/b", StatusCode::MOVED_PERMANENTLY), + ("//resource1//a//b/", "/resource1/a/b", StatusCode::MOVED_PERMANENTLY), + ("//resource1//a//b//", "/resource1/a/b", StatusCode::MOVED_PERMANENTLY), + ("///resource1//a//b", "/resource1/a/b", StatusCode::MOVED_PERMANENTLY), + ("/////resource1/a///b", "/resource1/a/b", StatusCode::MOVED_PERMANENTLY), + ("/////resource1/a//b/", "/resource1/a/b", StatusCode::MOVED_PERMANENTLY), ("/resource1/a/b?p=1", "", StatusCode::OK), ( "//resource1//a//b?p=1", @@ -356,11 +308,7 @@ mod tests { if !target.is_empty() { assert_eq!( target, - r.headers() - .get(header::LOCATION) - .unwrap() - .to_str() - .unwrap() + r.headers().get(header::LOCATION).unwrap().to_str().unwrap() ); } } @@ -379,88 +327,24 @@ mod tests { // trailing slashes let params = vec![ ("/resource1/a/b", "", StatusCode::OK), - ( - "/resource1/a/b/", - "/resource1/a/b", - StatusCode::MOVED_PERMANENTLY, - ), - ( - "//resource2//a//b", - "/resource2/a/b/", - StatusCode::MOVED_PERMANENTLY, - ), - ( - "//resource2//a//b/", - "/resource2/a/b/", - StatusCode::MOVED_PERMANENTLY, - ), - ( - "//resource2//a//b//", - "/resource2/a/b/", - StatusCode::MOVED_PERMANENTLY, - ), - ( - "///resource1//a//b", - "/resource1/a/b", - StatusCode::MOVED_PERMANENTLY, - ), - ( - "///resource1//a//b/", - "/resource1/a/b", - StatusCode::MOVED_PERMANENTLY, - ), - ( - "/////resource1/a///b", - "/resource1/a/b", - StatusCode::MOVED_PERMANENTLY, - ), - ( - "/////resource1/a///b/", - "/resource1/a/b", - StatusCode::MOVED_PERMANENTLY, - ), - ( - "/resource2/a/b", - "/resource2/a/b/", - StatusCode::MOVED_PERMANENTLY, - ), + ("/resource1/a/b/", "/resource1/a/b", StatusCode::MOVED_PERMANENTLY), + ("//resource2//a//b", "/resource2/a/b/", StatusCode::MOVED_PERMANENTLY), + ("//resource2//a//b/", "/resource2/a/b/", StatusCode::MOVED_PERMANENTLY), + ("//resource2//a//b//", "/resource2/a/b/", StatusCode::MOVED_PERMANENTLY), + ("///resource1//a//b", "/resource1/a/b", StatusCode::MOVED_PERMANENTLY), + ("///resource1//a//b/", "/resource1/a/b", StatusCode::MOVED_PERMANENTLY), + ("/////resource1/a///b", "/resource1/a/b", StatusCode::MOVED_PERMANENTLY), + ("/////resource1/a///b/", "/resource1/a/b", StatusCode::MOVED_PERMANENTLY), + ("/resource2/a/b", "/resource2/a/b/", StatusCode::MOVED_PERMANENTLY), ("/resource2/a/b/", "", StatusCode::OK), - ( - "//resource2//a//b", - "/resource2/a/b/", - StatusCode::MOVED_PERMANENTLY, - ), - ( - "//resource2//a//b/", - "/resource2/a/b/", - StatusCode::MOVED_PERMANENTLY, - ), - ( - "///resource2//a//b", - "/resource2/a/b/", - StatusCode::MOVED_PERMANENTLY, - ), - ( - "///resource2//a//b/", - "/resource2/a/b/", - StatusCode::MOVED_PERMANENTLY, - ), - ( - "/////resource2/a///b", - "/resource2/a/b/", - StatusCode::MOVED_PERMANENTLY, - ), - ( - "/////resource2/a///b/", - "/resource2/a/b/", - StatusCode::MOVED_PERMANENTLY, - ), + ("//resource2//a//b", "/resource2/a/b/", StatusCode::MOVED_PERMANENTLY), + ("//resource2//a//b/", "/resource2/a/b/", StatusCode::MOVED_PERMANENTLY), + ("///resource2//a//b", "/resource2/a/b/", StatusCode::MOVED_PERMANENTLY), + ("///resource2//a//b/", "/resource2/a/b/", StatusCode::MOVED_PERMANENTLY), + ("/////resource2/a///b", "/resource2/a/b/", StatusCode::MOVED_PERMANENTLY), + ("/////resource2/a///b/", "/resource2/a/b/", StatusCode::MOVED_PERMANENTLY), ("/resource1/a/b?p=1", "", StatusCode::OK), - ( - "/resource1/a/b/?p=1", - "/resource1/a/b?p=1", - StatusCode::MOVED_PERMANENTLY, - ), + ("/resource1/a/b/?p=1", "/resource1/a/b?p=1", StatusCode::MOVED_PERMANENTLY), ( "//resource2//a//b?p=1", "/resource2/a/b/?p=1", @@ -496,11 +380,7 @@ mod tests { "/resource1/a/b?p=1", StatusCode::MOVED_PERMANENTLY, ), - ( - "/resource2/a/b?p=1", - "/resource2/a/b/?p=1", - StatusCode::MOVED_PERMANENTLY, - ), + ("/resource2/a/b?p=1", "/resource2/a/b/?p=1", StatusCode::MOVED_PERMANENTLY), ( "//resource2//a//b?p=1", "/resource2/a/b/?p=1", @@ -540,11 +420,7 @@ mod tests { if !target.is_empty() { assert_eq!( target, - r.headers() - .get(header::LOCATION) - .unwrap() - .to_str() - .unwrap() + r.headers().get(header::LOCATION).unwrap().to_str().unwrap() ); } } diff --git a/src/httpcodes.rs b/src/httpcodes.rs index 058d1d2f..6ad9a28c 100644 --- a/src/httpcodes.rs +++ b/src/httpcodes.rs @@ -14,32 +14,37 @@ pub const HttpOk: StaticResponse = StaticResponse(StatusCode::OK); pub const HttpCreated: StaticResponse = StaticResponse(StatusCode::CREATED); #[deprecated(since = "0.5.0", note = "please use `HttpResponse::Accepted()` instead")] pub const HttpAccepted: StaticResponse = StaticResponse(StatusCode::ACCEPTED); -#[deprecated(since = "0.5.0", - note = "please use `HttpResponse::pNonAuthoritativeInformation()` instead")] +#[deprecated( + since = "0.5.0", + note = "please use `HttpResponse::pNonAuthoritativeInformation()` instead" +)] pub const HttpNonAuthoritativeInformation: StaticResponse = StaticResponse(StatusCode::NON_AUTHORITATIVE_INFORMATION); #[deprecated(since = "0.5.0", note = "please use `HttpResponse::NoContent()` instead")] pub const HttpNoContent: StaticResponse = StaticResponse(StatusCode::NO_CONTENT); -#[deprecated(since = "0.5.0", - note = "please use `HttpResponse::ResetContent()` instead")] +#[deprecated(since = "0.5.0", note = "please use `HttpResponse::ResetContent()` instead")] pub const HttpResetContent: StaticResponse = StaticResponse(StatusCode::RESET_CONTENT); -#[deprecated(since = "0.5.0", - note = "please use `HttpResponse::PartialContent()` instead")] +#[deprecated( + since = "0.5.0", note = "please use `HttpResponse::PartialContent()` instead" +)] pub const HttpPartialContent: StaticResponse = StaticResponse(StatusCode::PARTIAL_CONTENT); #[deprecated(since = "0.5.0", note = "please use `HttpResponse::MultiStatus()` instead")] pub const HttpMultiStatus: StaticResponse = StaticResponse(StatusCode::MULTI_STATUS); -#[deprecated(since = "0.5.0", - note = "please use `HttpResponse::AlreadyReported()` instead")] +#[deprecated( + since = "0.5.0", note = "please use `HttpResponse::AlreadyReported()` instead" +)] pub const HttpAlreadyReported: StaticResponse = StaticResponse(StatusCode::ALREADY_REPORTED); -#[deprecated(since = "0.5.0", - note = "please use `HttpResponse::MultipleChoices()` instead")] +#[deprecated( + since = "0.5.0", note = "please use `HttpResponse::MultipleChoices()` instead" +)] pub const HttpMultipleChoices: StaticResponse = StaticResponse(StatusCode::MULTIPLE_CHOICES); -#[deprecated(since = "0.5.0", - note = "please use `HttpResponse::MovedPermanently()` instead")] +#[deprecated( + since = "0.5.0", note = "please use `HttpResponse::MovedPermanently()` instead" +)] pub const HttpMovedPermanently: StaticResponse = StaticResponse(StatusCode::MOVED_PERMANENTLY); #[deprecated(since = "0.5.0", note = "please use `HttpResponse::Found()` instead")] @@ -50,106 +55,125 @@ pub const HttpSeeOther: StaticResponse = StaticResponse(StatusCode::SEE_OTHER); pub const HttpNotModified: StaticResponse = StaticResponse(StatusCode::NOT_MODIFIED); #[deprecated(since = "0.5.0", note = "please use `HttpResponse::UseProxy()` instead")] pub const HttpUseProxy: StaticResponse = StaticResponse(StatusCode::USE_PROXY); -#[deprecated(since = "0.5.0", - note = "please use `HttpResponse::TemporaryRedirect()` instead")] +#[deprecated( + since = "0.5.0", note = "please use `HttpResponse::TemporaryRedirect()` instead" +)] pub const HttpTemporaryRedirect: StaticResponse = StaticResponse(StatusCode::TEMPORARY_REDIRECT); -#[deprecated(since = "0.5.0", - note = "please use `HttpResponse::PermanentRedirect()` instead")] +#[deprecated( + since = "0.5.0", note = "please use `HttpResponse::PermanentRedirect()` instead" +)] pub const HttpPermanentRedirect: StaticResponse = StaticResponse(StatusCode::PERMANENT_REDIRECT); #[deprecated(since = "0.5.0", note = "please use `HttpResponse::BadRequest()` instead")] pub const HttpBadRequest: StaticResponse = StaticResponse(StatusCode::BAD_REQUEST); -#[deprecated(since = "0.5.0", - note = "please use `HttpResponse::Unauthorized()` instead")] +#[deprecated(since = "0.5.0", note = "please use `HttpResponse::Unauthorized()` instead")] pub const HttpUnauthorized: StaticResponse = StaticResponse(StatusCode::UNAUTHORIZED); -#[deprecated(since = "0.5.0", - note = "please use `HttpResponse::PaymentRequired()` instead")] +#[deprecated( + since = "0.5.0", note = "please use `HttpResponse::PaymentRequired()` instead" +)] pub const HttpPaymentRequired: StaticResponse = StaticResponse(StatusCode::PAYMENT_REQUIRED); #[deprecated(since = "0.5.0", note = "please use `HttpResponse::Forbidden()` instead")] pub const HttpForbidden: StaticResponse = StaticResponse(StatusCode::FORBIDDEN); #[deprecated(since = "0.5.0", note = "please use `HttpResponse::NotFound()` instead")] pub const HttpNotFound: StaticResponse = StaticResponse(StatusCode::NOT_FOUND); -#[deprecated(since = "0.5.0", - note = "please use `HttpResponse::MethodNotAllowed()` instead")] +#[deprecated( + since = "0.5.0", note = "please use `HttpResponse::MethodNotAllowed()` instead" +)] pub const HttpMethodNotAllowed: StaticResponse = StaticResponse(StatusCode::METHOD_NOT_ALLOWED); -#[deprecated(since = "0.5.0", - note = "please use `HttpResponse::NotAcceptable()` instead")] +#[deprecated( + since = "0.5.0", note = "please use `HttpResponse::NotAcceptable()` instead" +)] pub const HttpNotAcceptable: StaticResponse = StaticResponse(StatusCode::NOT_ACCEPTABLE); -#[deprecated(since = "0.5.0", - note = "please use `HttpResponse::ProxyAuthenticationRequired()` instead")] +#[deprecated( + since = "0.5.0", + note = "please use `HttpResponse::ProxyAuthenticationRequired()` instead" +)] pub const HttpProxyAuthenticationRequired: StaticResponse = StaticResponse(StatusCode::PROXY_AUTHENTICATION_REQUIRED); -#[deprecated(since = "0.5.0", - note = "please use `HttpResponse::RequestTimeout()` instead")] +#[deprecated( + since = "0.5.0", note = "please use `HttpResponse::RequestTimeout()` instead" +)] pub const HttpRequestTimeout: StaticResponse = StaticResponse(StatusCode::REQUEST_TIMEOUT); #[deprecated(since = "0.5.0", note = "please use `HttpResponse::Conflict()` instead")] pub const HttpConflict: StaticResponse = StaticResponse(StatusCode::CONFLICT); #[deprecated(since = "0.5.0", note = "please use `HttpResponse::Gone()` instead")] pub const HttpGone: StaticResponse = StaticResponse(StatusCode::GONE); -#[deprecated(since = "0.5.0", - note = "please use `HttpResponse::LengthRequired()` instead")] +#[deprecated( + since = "0.5.0", note = "please use `HttpResponse::LengthRequired()` instead" +)] pub const HttpLengthRequired: StaticResponse = StaticResponse(StatusCode::LENGTH_REQUIRED); -#[deprecated(since = "0.5.0", - note = "please use `HttpResponse::PreconditionFailed()` instead")] +#[deprecated( + since = "0.5.0", note = "please use `HttpResponse::PreconditionFailed()` instead" +)] pub const HttpPreconditionFailed: StaticResponse = StaticResponse(StatusCode::PRECONDITION_FAILED); -#[deprecated(since = "0.5.0", - note = "please use `HttpResponse::PayloadTooLarge()` instead")] +#[deprecated( + since = "0.5.0", note = "please use `HttpResponse::PayloadTooLarge()` instead" +)] pub const HttpPayloadTooLarge: StaticResponse = StaticResponse(StatusCode::PAYLOAD_TOO_LARGE); #[deprecated(since = "0.5.0", note = "please use `HttpResponse::UriTooLong()` instead")] pub const HttpUriTooLong: StaticResponse = StaticResponse(StatusCode::URI_TOO_LONG); -#[deprecated(since = "0.5.0", - note = "please use `HttpResponse::UnsupportedMediaType()` instead")] +#[deprecated( + since = "0.5.0", note = "please use `HttpResponse::UnsupportedMediaType()` instead" +)] pub const HttpUnsupportedMediaType: StaticResponse = StaticResponse(StatusCode::UNSUPPORTED_MEDIA_TYPE); -#[deprecated(since = "0.5.0", - note = "please use `HttpResponse::RangeNotSatisfiable()` instead")] +#[deprecated( + since = "0.5.0", note = "please use `HttpResponse::RangeNotSatisfiable()` instead" +)] pub const HttpRangeNotSatisfiable: StaticResponse = StaticResponse(StatusCode::RANGE_NOT_SATISFIABLE); -#[deprecated(since = "0.5.0", - note = "please use `HttpResponse::ExpectationFailed()` instead")] +#[deprecated( + since = "0.5.0", note = "please use `HttpResponse::ExpectationFailed()` instead" +)] pub const HttpExpectationFailed: StaticResponse = StaticResponse(StatusCode::EXPECTATION_FAILED); -#[deprecated(since = "0.5.0", - note = "please use `HttpResponse::InternalServerError()` instead")] +#[deprecated( + since = "0.5.0", note = "please use `HttpResponse::InternalServerError()` instead" +)] pub const HttpInternalServerError: StaticResponse = StaticResponse(StatusCode::INTERNAL_SERVER_ERROR); -#[deprecated(since = "0.5.0", - note = "please use `HttpResponse::NotImplemented()` instead")] +#[deprecated( + since = "0.5.0", note = "please use `HttpResponse::NotImplemented()` instead" +)] pub const HttpNotImplemented: StaticResponse = StaticResponse(StatusCode::NOT_IMPLEMENTED); #[deprecated(since = "0.5.0", note = "please use `HttpResponse::BadGateway()` instead")] pub const HttpBadGateway: StaticResponse = StaticResponse(StatusCode::BAD_GATEWAY); -#[deprecated(since = "0.5.0", - note = "please use `HttpResponse::ServiceUnavailable()` instead")] +#[deprecated( + since = "0.5.0", note = "please use `HttpResponse::ServiceUnavailable()` instead" +)] pub const HttpServiceUnavailable: StaticResponse = StaticResponse(StatusCode::SERVICE_UNAVAILABLE); -#[deprecated(since = "0.5.0", - note = "please use `HttpResponse::GatewayTimeout()` instead")] +#[deprecated( + since = "0.5.0", note = "please use `HttpResponse::GatewayTimeout()` instead" +)] pub const HttpGatewayTimeout: StaticResponse = StaticResponse(StatusCode::GATEWAY_TIMEOUT); -#[deprecated(since = "0.5.0", - note = "please use `HttpResponse::VersionNotSupported()` instead")] +#[deprecated( + since = "0.5.0", note = "please use `HttpResponse::VersionNotSupported()` instead" +)] pub const HttpVersionNotSupported: StaticResponse = StaticResponse(StatusCode::HTTP_VERSION_NOT_SUPPORTED); -#[deprecated(since = "0.5.0", - note = "please use `HttpResponse::VariantAlsoNegotiates()` instead")] +#[deprecated( + since = "0.5.0", note = "please use `HttpResponse::VariantAlsoNegotiates()` instead" +)] pub const HttpVariantAlsoNegotiates: StaticResponse = StaticResponse(StatusCode::VARIANT_ALSO_NEGOTIATES); -#[deprecated(since = "0.5.0", - note = "please use `HttpResponse::InsufficientStorage()` instead")] +#[deprecated( + since = "0.5.0", note = "please use `HttpResponse::InsufficientStorage()` instead" +)] pub const HttpInsufficientStorage: StaticResponse = StaticResponse(StatusCode::INSUFFICIENT_STORAGE); -#[deprecated(since = "0.5.0", - note = "please use `HttpResponse::LoopDetected()` instead")] +#[deprecated(since = "0.5.0", note = "please use `HttpResponse::LoopDetected()` instead")] pub const HttpLoopDetected: StaticResponse = StaticResponse(StatusCode::LOOP_DETECTED); #[deprecated(since = "0.5.0", note = "please use `HttpResponse` instead")] @@ -221,10 +245,7 @@ impl HttpResponse { STATIC_RESP!(Ok, StatusCode::OK); STATIC_RESP!(Created, StatusCode::CREATED); STATIC_RESP!(Accepted, StatusCode::ACCEPTED); - STATIC_RESP!( - NonAuthoritativeInformation, - StatusCode::NON_AUTHORITATIVE_INFORMATION - ); + STATIC_RESP!(NonAuthoritativeInformation, StatusCode::NON_AUTHORITATIVE_INFORMATION); STATIC_RESP!(NoContent, StatusCode::NO_CONTENT); STATIC_RESP!(ResetContent, StatusCode::RESET_CONTENT); @@ -249,10 +270,7 @@ impl HttpResponse { STATIC_RESP!(Forbidden, StatusCode::FORBIDDEN); STATIC_RESP!(MethodNotAllowed, StatusCode::METHOD_NOT_ALLOWED); STATIC_RESP!(NotAcceptable, StatusCode::NOT_ACCEPTABLE); - STATIC_RESP!( - ProxyAuthenticationRequired, - StatusCode::PROXY_AUTHENTICATION_REQUIRED - ); + STATIC_RESP!(ProxyAuthenticationRequired, StatusCode::PROXY_AUTHENTICATION_REQUIRED); STATIC_RESP!(RequestTimeout, StatusCode::REQUEST_TIMEOUT); STATIC_RESP!(Conflict, StatusCode::CONFLICT); STATIC_RESP!(Gone, StatusCode::GONE); @@ -260,10 +278,7 @@ impl HttpResponse { STATIC_RESP!(PreconditionFailed, StatusCode::PRECONDITION_FAILED); STATIC_RESP!(PayloadTooLarge, StatusCode::PAYLOAD_TOO_LARGE); STATIC_RESP!(UriTooLong, StatusCode::URI_TOO_LONG); - STATIC_RESP!( - UnsupportedMediaType, - StatusCode::UNSUPPORTED_MEDIA_TYPE - ); + STATIC_RESP!(UnsupportedMediaType, StatusCode::UNSUPPORTED_MEDIA_TYPE); STATIC_RESP!(RangeNotSatisfiable, StatusCode::RANGE_NOT_SATISFIABLE); STATIC_RESP!(ExpectationFailed, StatusCode::EXPECTATION_FAILED); @@ -272,14 +287,8 @@ impl HttpResponse { STATIC_RESP!(BadGateway, StatusCode::BAD_GATEWAY); STATIC_RESP!(ServiceUnavailable, StatusCode::SERVICE_UNAVAILABLE); STATIC_RESP!(GatewayTimeout, StatusCode::GATEWAY_TIMEOUT); - STATIC_RESP!( - VersionNotSupported, - StatusCode::HTTP_VERSION_NOT_SUPPORTED - ); - STATIC_RESP!( - VariantAlsoNegotiates, - StatusCode::VARIANT_ALSO_NEGOTIATES - ); + STATIC_RESP!(VersionNotSupported, StatusCode::HTTP_VERSION_NOT_SUPPORTED); + STATIC_RESP!(VariantAlsoNegotiates, StatusCode::VARIANT_ALSO_NEGOTIATES); STATIC_RESP!(InsufficientStorage, StatusCode::INSUFFICIENT_STORAGE); STATIC_RESP!(LoopDetected, StatusCode::LOOP_DETECTED); } diff --git a/src/httpmessage.rs b/src/httpmessage.rs index b590172b..c8c836d9 100644 --- a/src/httpmessage.rs +++ b/src/httpmessage.rs @@ -1,8 +1,8 @@ use bytes::{Bytes, BytesMut}; -use encoding::EncodingRef; use encoding::all::UTF_8; use encoding::label::encoding_from_whatwg_label; use encoding::types::{DecoderTrap, Encoding}; +use encoding::EncodingRef; use futures::{Future, Poll, Stream}; use http::{header, HeaderMap}; use http_range::HttpRange; @@ -96,10 +96,8 @@ pub trait HttpMessage { /// `size` is full size of response (file). fn range(&self, size: u64) -> Result, HttpRangeError> { if let Some(range) = self.headers().get(header::RANGE) { - HttpRange::parse( - unsafe { str::from_utf8_unchecked(range.as_bytes()) }, - size, - ).map_err(|e| e.into()) + HttpRange::parse(unsafe { str::from_utf8_unchecked(range.as_bytes()) }, size) + .map_err(|e| e.into()) } else { Ok(Vec::new()) } @@ -325,10 +323,7 @@ where )); } - self.fut - .as_mut() - .expect("UrlEncoded could not be used second time") - .poll() + self.fut.as_mut().expect("UrlEncoded could not be used second time").poll() } } @@ -385,8 +380,7 @@ where if req.content_type().to_lowercase() != "application/x-www-form-urlencoded" { return Err(UrlencodedError::ContentType); } - let encoding = req.encoding() - .map_err(|_| UrlencodedError::ContentType)?; + let encoding = req.encoding().map_err(|_| UrlencodedError::ContentType)?; // future let limit = self.limit; @@ -415,18 +409,15 @@ where self.fut = Some(Box::new(fut)); } - self.fut - .as_mut() - .expect("UrlEncoded could not be used second time") - .poll() + self.fut.as_mut().expect("UrlEncoded could not be used second time").poll() } } #[cfg(test)] mod tests { use super::*; - use encoding::Encoding; use encoding::all::ISO_8859_2; + use encoding::Encoding; use futures::Async; use http::{Method, Uri, Version}; use httprequest::HttpRequest; @@ -488,19 +479,13 @@ mod tests { #[test] fn test_encoding_error() { let req = TestRequest::with_header("content-type", "applicatjson").finish(); - assert_eq!( - Some(ContentTypeError::ParseError), - req.encoding().err() - ); + assert_eq!(Some(ContentTypeError::ParseError), req.encoding().err()); let req = TestRequest::with_header( "content-type", "application/json; charset=kkkttktk", ).finish(); - assert_eq!( - Some(ContentTypeError::UnknownEncoding), - req.encoding().err() - ); + assert_eq!(Some(ContentTypeError::UnknownEncoding), req.encoding().err()); } #[test] @@ -621,8 +606,7 @@ mod tests { "application/x-www-form-urlencoded", ).header(header::CONTENT_LENGTH, "11") .finish(); - req.payload_mut() - .unread_data(Bytes::from_static(b"hello=world")); + req.payload_mut().unread_data(Bytes::from_static(b"hello=world")); let result = req.urlencoded::().poll().ok().unwrap(); assert_eq!( @@ -637,8 +621,7 @@ mod tests { "application/x-www-form-urlencoded; charset=utf-8", ).header(header::CONTENT_LENGTH, "11") .finish(); - req.payload_mut() - .unread_data(Bytes::from_static(b"hello=world")); + req.payload_mut().unread_data(Bytes::from_static(b"hello=world")); let result = req.urlencoded().poll().ok().unwrap(); assert_eq!( @@ -664,16 +647,14 @@ mod tests { } let mut req = HttpRequest::default(); - req.payload_mut() - .unread_data(Bytes::from_static(b"test")); + req.payload_mut().unread_data(Bytes::from_static(b"test")); match req.body().poll().ok().unwrap() { Async::Ready(bytes) => assert_eq!(bytes, Bytes::from_static(b"test")), _ => unreachable!("error"), } let mut req = HttpRequest::default(); - req.payload_mut() - .unread_data(Bytes::from_static(b"11111111111111")); + req.payload_mut().unread_data(Bytes::from_static(b"11111111111111")); match req.body().limit(5).poll().err().unwrap() { PayloadError::Overflow => (), _ => unreachable!("error"), diff --git a/src/httprequest.rs b/src/httprequest.rs index ee2bd5a7..d41a748a 100644 --- a/src/httprequest.rs +++ b/src/httprequest.rs @@ -1,4 +1,5 @@ //! HTTP Request message related code. +#![cfg_attr(feature = "cargo-clippy", allow(transmute_ptr_to_ptr))] use bytes::Bytes; use cookie::Cookie; use failure; @@ -314,7 +315,7 @@ impl HttpRequest { /// } /// ``` pub fn url_for( - &self, name: &str, elements: U + &self, name: &str, elements: U, ) -> Result where U: IntoIterator, @@ -326,12 +327,7 @@ impl HttpRequest { let path = self.router().unwrap().resource_path(name, elements)?; if path.starts_with('/') { let conn = self.connection_info(); - Ok(Url::parse(&format!( - "{}://{}{}", - conn.scheme(), - conn.host(), - path - ))?) + Ok(Url::parse(&format!("{}://{}{}", conn.scheme(), conn.host(), path))?) } else { Ok(Url::parse(&path)?) } @@ -681,12 +677,8 @@ mod tests { let mut resource = ResourceHandler::<()>::default(); resource.name("index"); - let routes = vec![ - ( - Resource::new("index", "/user/{name}.{ext}"), - Some(resource), - ), - ]; + let routes = + vec![(Resource::new("index", "/user/{name}.{ext}"), Some(resource))]; let (router, _) = Router::new("/", ServerSettings::default(), routes); assert!(router.has_route("/user/test.html")); assert!(!router.has_route("/test/unknown")); @@ -715,12 +707,8 @@ mod tests { let mut resource = ResourceHandler::<()>::default(); resource.name("index"); - let routes = vec![ - ( - Resource::new("index", "/user/{name}.{ext}"), - Some(resource), - ), - ]; + let routes = + vec![(Resource::new("index", "/user/{name}.{ext}"), Some(resource))]; let (router, _) = Router::new("/prefix/", ServerSettings::default(), routes); assert!(router.has_route("/user/test.html")); assert!(!router.has_route("/prefix/user/test.html")); @@ -739,20 +727,15 @@ mod tests { let mut resource = ResourceHandler::<()>::default(); resource.name("index"); - let routes = vec![ - ( - Resource::external("youtube", "https://youtube.com/watch/{video_id}"), - None, - ), - ]; + let routes = vec![( + Resource::external("youtube", "https://youtube.com/watch/{video_id}"), + None, + )]; let (router, _) = Router::new::<()>("", ServerSettings::default(), routes); assert!(!router.has_route("https://youtube.com/watch/unknown")); let req = req.with_state(Rc::new(()), router); let url = req.url_for("youtube", &["oHg5SJYRHA0"]); - assert_eq!( - url.ok().unwrap().as_str(), - "https://youtube.com/watch/oHg5SJYRHA0" - ); + assert_eq!(url.ok().unwrap().as_str(), "https://youtube.com/watch/oHg5SJYRHA0"); } } diff --git a/src/httpresponse.rs b/src/httpresponse.rs index c53975e1..a1f1cfb4 100644 --- a/src/httpresponse.rs +++ b/src/httpresponse.rs @@ -150,10 +150,7 @@ impl HttpResponse { if let Some(reason) = self.get_ref().reason { reason } else { - self.get_ref() - .status - .canonical_reason() - .unwrap_or("") + self.get_ref().status.canonical_reason().unwrap_or("") } } @@ -466,10 +463,7 @@ impl HttpResponseBuilder { jar.add(cookie.into_owned()); self.cookies = Some(jar) } else { - self.cookies - .as_mut() - .unwrap() - .add(cookie.into_owned()); + self.cookies.as_mut().unwrap().add(cookie.into_owned()); } self } @@ -534,9 +528,7 @@ impl HttpResponseBuilder { if let Some(e) = self.err.take() { return Error::from(e).into(); } - let mut response = self.response - .take() - .expect("cannot reuse response builder"); + let mut response = self.response.take().expect("cannot reuse response builder"); if let Some(ref jar) = self.cookies { for cookie in jar.delta() { match HeaderValue::from_str(&cookie.to_string()) { @@ -558,9 +550,7 @@ impl HttpResponseBuilder { S: Stream + 'static, E: Into, { - self.body(Body::Streaming(Box::new( - stream.map_err(|e| e.into()), - ))) + self.body(Body::Streaming(Box::new(stream.map_err(|e| e.into())))) } /// Set a json body and generate `HttpResponse` @@ -607,7 +597,7 @@ impl HttpResponseBuilder { #[inline] #[cfg_attr(feature = "cargo-clippy", allow(borrowed_box))] fn parts<'a>( - parts: &'a mut Option>, err: &Option + parts: &'a mut Option>, err: &Option, ) -> Option<&'a mut Box> { if err.is_some() { return None; @@ -643,9 +633,7 @@ impl Responder for HttpResponseBuilder { impl From<&'static str> for HttpResponse { fn from(val: &'static str) -> Self { - HttpResponse::Ok() - .content_type("text/plain; charset=utf-8") - .body(val) + HttpResponse::Ok().content_type("text/plain; charset=utf-8").body(val) } } @@ -662,9 +650,7 @@ impl Responder for &'static str { impl From<&'static [u8]> for HttpResponse { fn from(val: &'static [u8]) -> Self { - HttpResponse::Ok() - .content_type("application/octet-stream") - .body(val) + HttpResponse::Ok().content_type("application/octet-stream").body(val) } } @@ -681,9 +667,7 @@ impl Responder for &'static [u8] { impl From for HttpResponse { fn from(val: String) -> Self { - HttpResponse::Ok() - .content_type("text/plain; charset=utf-8") - .body(val) + HttpResponse::Ok().content_type("text/plain; charset=utf-8").body(val) } } @@ -719,9 +703,7 @@ impl<'a> Responder for &'a String { impl From for HttpResponse { fn from(val: Bytes) -> Self { - HttpResponse::Ok() - .content_type("application/octet-stream") - .body(val) + HttpResponse::Ok().content_type("application/octet-stream").body(val) } } @@ -738,9 +720,7 @@ impl Responder for Bytes { impl From for HttpResponse { fn from(val: BytesMut) -> Self { - HttpResponse::Ok() - .content_type("application/octet-stream") - .body(val) + HttpResponse::Ok().content_type("application/octet-stream").body(val) } } @@ -772,9 +752,7 @@ impl<'a> From<&'a ClientResponse> for HttpResponseBuilder { impl<'a, S> From<&'a HttpRequest> for HttpResponseBuilder { fn from(req: &'a HttpRequest) -> HttpResponseBuilder { if let Some(router) = req.router() { - router - .server_settings() - .get_response_builder(StatusCode::OK) + router.server_settings().get_response_builder(StatusCode::OK) } else { HttpResponse::Ok() } @@ -822,14 +800,12 @@ thread_local!(static POOL: Rc> = HttpResponsePool:: impl HttpResponsePool { pub fn pool() -> Rc> { - Rc::new(UnsafeCell::new(HttpResponsePool( - VecDeque::with_capacity(128), - ))) + Rc::new(UnsafeCell::new(HttpResponsePool(VecDeque::with_capacity(128)))) } #[inline] pub fn get_builder( - pool: &Rc>, status: StatusCode + pool: &Rc>, status: StatusCode, ) -> HttpResponseBuilder { let p = unsafe { &mut *pool.as_ref().get() }; if let Some(mut msg) = p.0.pop_front() { @@ -853,7 +829,7 @@ impl HttpResponsePool { #[inline] pub fn get_response( - pool: &Rc>, status: StatusCode, body: Body + pool: &Rc>, status: StatusCode, body: Body, ) -> HttpResponse { let p = unsafe { &mut *pool.as_ref().get() }; if let Some(mut msg) = p.0.pop_front() { @@ -879,7 +855,7 @@ impl HttpResponsePool { #[inline(always)] #[cfg_attr(feature = "cargo-clippy", allow(boxed_local, inline_always))] fn release( - pool: &Rc>, mut inner: Box + pool: &Rc>, mut inner: Box, ) { let pool = unsafe { &mut *pool.as_ref().get() }; if pool.0.len() < 128 { @@ -975,9 +951,7 @@ mod tests { #[test] fn test_force_close() { - let resp = HttpResponse::build(StatusCode::OK) - .force_close() - .finish(); + let resp = HttpResponse::build(StatusCode::OK).force_close().finish(); assert!(!resp.keep_alive().unwrap()) } @@ -986,10 +960,7 @@ mod tests { let resp = HttpResponse::build(StatusCode::OK) .content_type("text/plain") .body(Body::Empty); - assert_eq!( - resp.headers().get(CONTENT_TYPE).unwrap(), - "text/plain" - ) + assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "text/plain") } #[test] @@ -1073,10 +1044,7 @@ mod tests { HeaderValue::from_static("application/octet-stream") ); assert_eq!(resp.status(), StatusCode::OK); - assert_eq!( - resp.body().binary().unwrap(), - &Binary::from(b"test".as_ref()) - ); + assert_eq!(resp.body().binary().unwrap(), &Binary::from(b"test".as_ref())); let resp: HttpResponse = b"test".as_ref().respond_to(req.clone()).ok().unwrap(); assert_eq!(resp.status(), StatusCode::OK); @@ -1085,10 +1053,7 @@ mod tests { HeaderValue::from_static("application/octet-stream") ); assert_eq!(resp.status(), StatusCode::OK); - assert_eq!( - resp.body().binary().unwrap(), - &Binary::from(b"test".as_ref()) - ); + assert_eq!(resp.body().binary().unwrap(), &Binary::from(b"test".as_ref())); let resp: HttpResponse = "test".to_owned().into(); assert_eq!(resp.status(), StatusCode::OK); @@ -1097,26 +1062,16 @@ mod tests { HeaderValue::from_static("text/plain; charset=utf-8") ); assert_eq!(resp.status(), StatusCode::OK); - assert_eq!( - resp.body().binary().unwrap(), - &Binary::from("test".to_owned()) - ); + assert_eq!(resp.body().binary().unwrap(), &Binary::from("test".to_owned())); - let resp: HttpResponse = "test" - .to_owned() - .respond_to(req.clone()) - .ok() - .unwrap(); + let resp: HttpResponse = "test".to_owned().respond_to(req.clone()).ok().unwrap(); assert_eq!(resp.status(), StatusCode::OK); assert_eq!( resp.headers().get(CONTENT_TYPE).unwrap(), HeaderValue::from_static("text/plain; charset=utf-8") ); assert_eq!(resp.status(), StatusCode::OK); - assert_eq!( - resp.body().binary().unwrap(), - &Binary::from("test".to_owned()) - ); + assert_eq!(resp.body().binary().unwrap(), &Binary::from("test".to_owned())); let resp: HttpResponse = (&"test".to_owned()).into(); assert_eq!(resp.status(), StatusCode::OK); @@ -1125,25 +1080,17 @@ mod tests { HeaderValue::from_static("text/plain; charset=utf-8") ); assert_eq!(resp.status(), StatusCode::OK); - assert_eq!( - resp.body().binary().unwrap(), - &Binary::from(&"test".to_owned()) - ); + assert_eq!(resp.body().binary().unwrap(), &Binary::from(&"test".to_owned())); - let resp: HttpResponse = (&"test".to_owned()) - .respond_to(req.clone()) - .ok() - .unwrap(); + let resp: HttpResponse = + (&"test".to_owned()).respond_to(req.clone()).ok().unwrap(); assert_eq!(resp.status(), StatusCode::OK); assert_eq!( resp.headers().get(CONTENT_TYPE).unwrap(), HeaderValue::from_static("text/plain; charset=utf-8") ); assert_eq!(resp.status(), StatusCode::OK); - assert_eq!( - resp.body().binary().unwrap(), - &Binary::from(&"test".to_owned()) - ); + assert_eq!(resp.body().binary().unwrap(), &Binary::from(&"test".to_owned())); let b = Bytes::from_static(b"test"); let resp: HttpResponse = b.into(); @@ -1179,10 +1126,7 @@ mod tests { HeaderValue::from_static("application/octet-stream") ); assert_eq!(resp.status(), StatusCode::OK); - assert_eq!( - resp.body().binary().unwrap(), - &Binary::from(BytesMut::from("test")) - ); + assert_eq!(resp.body().binary().unwrap(), &Binary::from(BytesMut::from("test"))); let b = BytesMut::from("test"); let resp: HttpResponse = b.respond_to(req.clone()).ok().unwrap(); @@ -1192,10 +1136,7 @@ mod tests { HeaderValue::from_static("application/octet-stream") ); assert_eq!(resp.status(), StatusCode::OK); - assert_eq!( - resp.body().binary().unwrap(), - &Binary::from(BytesMut::from("test")) - ); + assert_eq!(resp.body().binary().unwrap(), &Binary::from(BytesMut::from("test"))); } #[test] diff --git a/src/info.rs b/src/info.rs index 76288539..7d3affab 100644 --- a/src/info.rs +++ b/src/info.rs @@ -53,8 +53,8 @@ impl<'a> ConnectionInfo<'a> { // scheme if scheme.is_none() { - if let Some(h) = req.headers() - .get(HeaderName::from_str(X_FORWARDED_PROTO).unwrap()) + if let Some(h) = + req.headers().get(HeaderName::from_str(X_FORWARDED_PROTO).unwrap()) { if let Ok(h) = h.to_str() { scheme = h.split(',').next().map(|v| v.trim()); @@ -74,8 +74,8 @@ impl<'a> ConnectionInfo<'a> { // host if host.is_none() { - if let Some(h) = req.headers() - .get(HeaderName::from_str(X_FORWARDED_HOST).unwrap()) + if let Some(h) = + req.headers().get(HeaderName::from_str(X_FORWARDED_HOST).unwrap()) { if let Ok(h) = h.to_str() { host = h.split(',').next().map(|v| v.trim()); @@ -98,8 +98,8 @@ impl<'a> ConnectionInfo<'a> { // remote addr if remote.is_none() { - if let Some(h) = req.headers() - .get(HeaderName::from_str(X_FORWARDED_FOR).unwrap()) + if let Some(h) = + req.headers().get(HeaderName::from_str(X_FORWARDED_FOR).unwrap()) { if let Ok(h) = h.to_str() { remote = h.split(',').next().map(|v| v.trim()); @@ -189,10 +189,8 @@ mod tests { assert_eq!(info.remote(), Some("192.0.2.60")); let mut req = HttpRequest::default(); - req.headers_mut().insert( - header::HOST, - HeaderValue::from_static("rust-lang.org"), - ); + req.headers_mut() + .insert(header::HOST, HeaderValue::from_static("rust-lang.org")); let info = ConnectionInfo::new(&req); assert_eq!(info.scheme(), "http"); diff --git a/src/json.rs b/src/json.rs index 96ac415f..9f0906c1 100644 --- a/src/json.rs +++ b/src/json.rs @@ -6,8 +6,8 @@ use std::ops::{Deref, DerefMut}; use std::rc::Rc; use mime; -use serde::Serialize; use serde::de::DeserializeOwned; +use serde::Serialize; use serde_json; use error::{Error, JsonPayloadError, PayloadError}; @@ -308,10 +308,7 @@ where self.fut = Some(Box::new(fut)); } - self.fut - .as_mut() - .expect("JsonBody could not be used second time") - .poll() + self.fut.as_mut().expect("JsonBody could not be used second time").poll() } } @@ -362,10 +359,7 @@ mod tests { fn test_json_body() { let req = HttpRequest::default(); let mut json = req.json::(); - assert_eq!( - json.poll().err().unwrap(), - JsonPayloadError::ContentType - ); + assert_eq!(json.poll().err().unwrap(), JsonPayloadError::ContentType); let mut req = HttpRequest::default(); req.headers_mut().insert( @@ -373,20 +367,15 @@ mod tests { header::HeaderValue::from_static("application/text"), ); let mut json = req.json::(); - assert_eq!( - json.poll().err().unwrap(), - JsonPayloadError::ContentType - ); + assert_eq!(json.poll().err().unwrap(), JsonPayloadError::ContentType); let mut req = HttpRequest::default(); req.headers_mut().insert( header::CONTENT_TYPE, header::HeaderValue::from_static("application/json"), ); - req.headers_mut().insert( - header::CONTENT_LENGTH, - header::HeaderValue::from_static("10000"), - ); + req.headers_mut() + .insert(header::CONTENT_LENGTH, header::HeaderValue::from_static("10000")); let mut json = req.json::().limit(100); assert_eq!(json.poll().err().unwrap(), JsonPayloadError::Overflow); @@ -395,12 +384,9 @@ mod tests { header::CONTENT_TYPE, header::HeaderValue::from_static("application/json"), ); - req.headers_mut().insert( - header::CONTENT_LENGTH, - header::HeaderValue::from_static("16"), - ); - req.payload_mut() - .unread_data(Bytes::from_static(b"{\"name\": \"test\"}")); + req.headers_mut() + .insert(header::CONTENT_LENGTH, header::HeaderValue::from_static("16")); + req.payload_mut().unread_data(Bytes::from_static(b"{\"name\": \"test\"}")); let mut json = req.json::(); assert_eq!( json.poll().ok().unwrap(), @@ -417,12 +403,7 @@ mod tests { let mut handler = With::new(|data: Json| data, cfg); let req = HttpRequest::default(); - let err = handler - .handle(req) - .as_response() - .unwrap() - .error() - .is_some(); + let err = handler.handle(req).as_response().unwrap().error().is_some(); assert!(err); let mut req = HttpRequest::default(); @@ -430,18 +411,10 @@ mod tests { header::CONTENT_TYPE, header::HeaderValue::from_static("application/json"), ); - req.headers_mut().insert( - header::CONTENT_LENGTH, - header::HeaderValue::from_static("16"), - ); - req.payload_mut() - .unread_data(Bytes::from_static(b"{\"name\": \"test\"}")); - let ok = handler - .handle(req) - .as_response() - .unwrap() - .error() - .is_none(); + req.headers_mut() + .insert(header::CONTENT_LENGTH, header::HeaderValue::from_static("16")); + req.payload_mut().unread_data(Bytes::from_static(b"{\"name\": \"test\"}")); + let ok = handler.handle(req).as_response().unwrap().error().is_none(); assert!(ok) } } diff --git a/src/middleware/cors.rs b/src/middleware/cors.rs index 243ea1e8..aa0bd494 100644 --- a/src/middleware/cors.rs +++ b/src/middleware/cors.rs @@ -64,26 +64,36 @@ use resource::ResourceHandler; #[derive(Debug, Fail)] pub enum CorsError { /// The HTTP request header `Origin` is required but was not provided - #[fail(display = "The HTTP request header `Origin` is required but was not provided")] + #[fail( + display = "The HTTP request header `Origin` is required but was not provided" + )] MissingOrigin, /// The HTTP request header `Origin` could not be parsed correctly. #[fail(display = "The HTTP request header `Origin` could not be parsed correctly.")] BadOrigin, /// The request header `Access-Control-Request-Method` is required but is /// missing - #[fail(display = "The request header `Access-Control-Request-Method` is required but is missing")] + #[fail( + display = "The request header `Access-Control-Request-Method` is required but is missing" + )] MissingRequestMethod, /// The request header `Access-Control-Request-Method` has an invalid value - #[fail(display = "The request header `Access-Control-Request-Method` has an invalid value")] + #[fail( + display = "The request header `Access-Control-Request-Method` has an invalid value" + )] BadRequestMethod, /// The request header `Access-Control-Request-Headers` has an invalid /// value - #[fail(display = "The request header `Access-Control-Request-Headers` has an invalid value")] + #[fail( + display = "The request header `Access-Control-Request-Headers` has an invalid value" + )] BadRequestHeaders, /// The request header `Access-Control-Request-Headers` is required but is /// missing. - #[fail(display = "The request header `Access-Control-Request-Headers` is required but is - missing")] + #[fail( + display = "The request header `Access-Control-Request-Headers` is required but is + missing" + )] MissingRequestHeaders, /// Origin is not allowed to make this request #[fail(display = "Origin is not allowed to make this request")] @@ -265,9 +275,7 @@ impl Cors { /// `ResourceHandler::middleware()` method, but in that case *Cors* /// middleware wont be able to handle *OPTIONS* requests. pub fn register(self, resource: &mut ResourceHandler) { - resource - .method(Method::OPTIONS) - .h(|_| HttpResponse::Ok()); + resource.method(Method::OPTIONS).h(|_| HttpResponse::Ok()); resource.middleware(self); } @@ -292,11 +300,9 @@ impl Cors { } fn validate_allowed_method( - &self, req: &mut HttpRequest + &self, req: &mut HttpRequest, ) -> Result<(), CorsError> { - if let Some(hdr) = req.headers() - .get(header::ACCESS_CONTROL_REQUEST_METHOD) - { + if let Some(hdr) = req.headers().get(header::ACCESS_CONTROL_REQUEST_METHOD) { if let Ok(meth) = hdr.to_str() { if let Ok(method) = Method::try_from(meth) { return self.inner @@ -313,13 +319,13 @@ impl Cors { } fn validate_allowed_headers( - &self, req: &mut HttpRequest + &self, req: &mut HttpRequest, ) -> Result<(), CorsError> { match self.inner.headers { AllOrSome::All => Ok(()), AllOrSome::Some(ref allowed_headers) => { - if let Some(hdr) = req.headers() - .get(header::ACCESS_CONTROL_REQUEST_HEADERS) + if let Some(hdr) = + req.headers().get(header::ACCESS_CONTROL_REQUEST_HEADERS) { if let Ok(headers) = hdr.to_str() { let mut hdrs = HashSet::new(); @@ -361,8 +367,8 @@ impl Middleware for Cors { .as_str()[1..], ).unwrap(), ) - } else if let Some(hdr) = req.headers() - .get(header::ACCESS_CONTROL_REQUEST_HEADERS) + } else if let Some(hdr) = + req.headers().get(header::ACCESS_CONTROL_REQUEST_HEADERS) { Some(hdr.clone()) } else { @@ -419,7 +425,7 @@ impl Middleware for Cors { } fn response( - &self, req: &mut HttpRequest, mut resp: HttpResponse + &self, req: &mut HttpRequest, mut resp: HttpResponse, ) -> Result { match self.inner.origins { AllOrSome::All => { @@ -506,7 +512,7 @@ pub struct CorsBuilder { } fn cors<'a>( - parts: &'a mut Option, err: &Option + parts: &'a mut Option, err: &Option, ) -> Option<&'a mut Inner> { if err.is_some() { return None; @@ -813,17 +819,13 @@ impl CorsBuilder { } if let AllOrSome::Some(ref origins) = cors.origins { - let s = origins - .iter() - .fold(String::new(), |s, v| s + &format!("{}", v)); + let s = origins.iter().fold(String::new(), |s, v| s + &v.to_string()); cors.origins_str = Some(HeaderValue::try_from(s.as_str()).unwrap()); } if !self.expose_hdrs.is_empty() { cors.expose_hdrs = Some( - self.expose_hdrs - .iter() - .fold(String::new(), |s, v| s + v.as_str())[1..] + self.expose_hdrs.iter().fold(String::new(), |s, v| s + v.as_str())[1..] .to_owned(), ); } @@ -901,27 +903,19 @@ mod tests { #[test] #[should_panic(expected = "Credentials are allowed, but the Origin is set to")] fn cors_validates_illegal_allow_credentials() { - Cors::build() - .supports_credentials() - .send_wildcard() - .finish(); + Cors::build().supports_credentials().send_wildcard().finish(); } #[test] #[should_panic(expected = "No resources are registered")] fn no_resource() { - Cors::build() - .supports_credentials() - .send_wildcard() - .register(); + Cors::build().supports_credentials().send_wildcard().register(); } #[test] #[should_panic(expected = "Cors::for_app(app)")] fn no_resource2() { - Cors::build() - .resource("/test", |r| r.f(|_| HttpResponse::Ok())) - .register(); + Cors::build().resource("/test", |r| r.f(|_| HttpResponse::Ok())).register(); } #[test] @@ -958,27 +952,18 @@ mod tests { let mut req = TestRequest::with_header("Origin", "https://www.example.com") .header(header::ACCESS_CONTROL_REQUEST_METHOD, "POST") - .header( - header::ACCESS_CONTROL_REQUEST_HEADERS, - "AUTHORIZATION,ACCEPT", - ) + .header(header::ACCESS_CONTROL_REQUEST_HEADERS, "AUTHORIZATION,ACCEPT") .method(Method::OPTIONS) .finish(); let resp = cors.start(&mut req).unwrap().response(); assert_eq!( &b"*"[..], - resp.headers() - .get(header::ACCESS_CONTROL_ALLOW_ORIGIN) - .unwrap() - .as_bytes() + resp.headers().get(header::ACCESS_CONTROL_ALLOW_ORIGIN).unwrap().as_bytes() ); assert_eq!( &b"3600"[..], - resp.headers() - .get(header::ACCESS_CONTROL_MAX_AGE) - .unwrap() - .as_bytes() + resp.headers().get(header::ACCESS_CONTROL_MAX_AGE).unwrap().as_bytes() ); //assert_eq!( // &b"authorization,accept,content-type"[..], @@ -995,9 +980,7 @@ mod tests { #[test] #[should_panic(expected = "MissingOrigin")] fn test_validate_missing_origin() { - let cors = Cors::build() - .allowed_origin("https://www.example.com") - .finish(); + let cors = Cors::build().allowed_origin("https://www.example.com").finish(); let mut req = HttpRequest::default(); cors.start(&mut req).unwrap(); @@ -1006,9 +989,7 @@ mod tests { #[test] #[should_panic(expected = "OriginNotAllowed")] fn test_validate_not_allowed_origin() { - let cors = Cors::build() - .allowed_origin("https://www.example.com") - .finish(); + let cors = Cors::build().allowed_origin("https://www.example.com").finish(); let mut req = TestRequest::with_header("Origin", "https://www.unknown.com") .method(Method::GET) @@ -1018,9 +999,7 @@ mod tests { #[test] fn test_validate_origin() { - let cors = Cors::build() - .allowed_origin("https://www.example.com") - .finish(); + let cors = Cors::build().allowed_origin("https://www.example.com").finish(); let mut req = TestRequest::with_header("Origin", "https://www.example.com") .method(Method::GET) @@ -1036,11 +1015,7 @@ mod tests { let mut req = TestRequest::default().method(Method::GET).finish(); let resp: HttpResponse = HttpResponse::Ok().into(); let resp = cors.response(&mut req, resp).unwrap().response(); - assert!( - resp.headers() - .get(header::ACCESS_CONTROL_ALLOW_ORIGIN) - .is_none() - ); + assert!(resp.headers().get(header::ACCESS_CONTROL_ALLOW_ORIGIN).is_none()); let mut req = TestRequest::with_header("Origin", "https://www.example.com") .method(Method::OPTIONS) @@ -1048,10 +1023,7 @@ mod tests { let resp = cors.response(&mut req, resp).unwrap().response(); assert_eq!( &b"https://www.example.com"[..], - resp.headers() - .get(header::ACCESS_CONTROL_ALLOW_ORIGIN) - .unwrap() - .as_bytes() + resp.headers().get(header::ACCESS_CONTROL_ALLOW_ORIGIN).unwrap().as_bytes() ); } @@ -1074,19 +1046,12 @@ mod tests { let resp = cors.response(&mut req, resp).unwrap().response(); assert_eq!( &b"*"[..], - resp.headers() - .get(header::ACCESS_CONTROL_ALLOW_ORIGIN) - .unwrap() - .as_bytes() - ); - assert_eq!( - &b"Origin"[..], - resp.headers().get(header::VARY).unwrap().as_bytes() + resp.headers().get(header::ACCESS_CONTROL_ALLOW_ORIGIN).unwrap().as_bytes() ); + assert_eq!(&b"Origin"[..], resp.headers().get(header::VARY).unwrap().as_bytes()); - let resp: HttpResponse = HttpResponse::Ok() - .header(header::VARY, "Accept") - .finish(); + let resp: HttpResponse = + HttpResponse::Ok().header(header::VARY, "Accept").finish(); let resp = cors.response(&mut req, resp).unwrap().response(); assert_eq!( &b"Accept, Origin"[..], @@ -1101,10 +1066,7 @@ mod tests { let resp = cors.response(&mut req, resp).unwrap().response(); assert_eq!( &b"https://www.example.com"[..], - resp.headers() - .get(header::ACCESS_CONTROL_ALLOW_ORIGIN) - .unwrap() - .as_bytes() + resp.headers().get(header::ACCESS_CONTROL_ALLOW_ORIGIN).unwrap().as_bytes() ); } diff --git a/src/middleware/csrf.rs b/src/middleware/csrf.rs index 9ff23b53..255b4564 100644 --- a/src/middleware/csrf.rs +++ b/src/middleware/csrf.rs @@ -89,10 +89,7 @@ fn origin(headers: &HeaderMap) -> Option, CsrfError>> { headers .get(header::ORIGIN) .map(|origin| { - origin - .to_str() - .map_err(|_| CsrfError::BadOrigin) - .map(|o| o.into()) + origin.to_str().map_err(|_| CsrfError::BadOrigin).map(|o| o.into()) }) .or_else(|| { headers.get(header::REFERER).map(|referer| { @@ -261,9 +258,8 @@ mod tests { fn test_upgrade() { let strict_csrf = CsrfFilter::new().allowed_origin("https://www.example.com"); - let lax_csrf = CsrfFilter::new() - .allowed_origin("https://www.example.com") - .allow_upgrade(); + let lax_csrf = + CsrfFilter::new().allowed_origin("https://www.example.com").allow_upgrade(); let mut req = TestRequest::with_header("Origin", "https://cswsh.com") .header("Connection", "Upgrade") diff --git a/src/middleware/defaultheaders.rs b/src/middleware/defaultheaders.rs index 4e17a553..ebe3ea1d 100644 --- a/src/middleware/defaultheaders.rs +++ b/src/middleware/defaultheaders.rs @@ -76,7 +76,7 @@ impl DefaultHeaders { impl Middleware for DefaultHeaders { fn response( - &self, _: &mut HttpRequest, mut resp: HttpResponse + &self, _: &mut HttpRequest, mut resp: HttpResponse, ) -> Result { for (key, value) in self.headers.iter() { if !resp.headers().contains_key(key) { @@ -112,9 +112,7 @@ mod tests { }; assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001"); - let resp = HttpResponse::Ok() - .header(CONTENT_TYPE, "0002") - .finish(); + let resp = HttpResponse::Ok().header(CONTENT_TYPE, "0002").finish(); let resp = match mw.response(&mut req, resp) { Ok(Response::Done(resp)) => resp, _ => panic!(), diff --git a/src/middleware/errhandlers.rs b/src/middleware/errhandlers.rs index fdc43ed2..22d0e1af 100644 --- a/src/middleware/errhandlers.rs +++ b/src/middleware/errhandlers.rs @@ -69,7 +69,7 @@ impl ErrorHandlers { impl Middleware for ErrorHandlers { fn response( - &self, req: &mut HttpRequest, resp: HttpResponse + &self, req: &mut HttpRequest, resp: HttpResponse, ) -> Result { if let Some(handler) = self.handlers.get(&resp.status()) { handler(req, resp) @@ -82,8 +82,8 @@ impl Middleware for ErrorHandlers { #[cfg(test)] mod tests { use super::*; - use http::StatusCode; use http::header::CONTENT_TYPE; + use http::StatusCode; fn render_500(_: &mut HttpRequest, resp: HttpResponse) -> Result { let mut builder = resp.into_builder(); diff --git a/src/middleware/identity.rs b/src/middleware/identity.rs index e428847a..06c5a4fa 100644 --- a/src/middleware/identity.rs +++ b/src/middleware/identity.rs @@ -49,8 +49,8 @@ use std::rc::Rc; use cookie::{Cookie, CookieJar, Key}; +use futures::future::{err as FutErr, ok as FutOk, FutureResult}; use futures::Future; -use futures::future::{FutureResult, err as FutErr, ok as FutOk}; use time::Duration; use error::{Error, Result}; @@ -164,7 +164,9 @@ pub struct IdentityService { impl IdentityService { /// Create new identity service with specified backend. pub fn new(backend: T) -> Self { - IdentityService { backend } + IdentityService { + backend, + } } } @@ -179,20 +181,18 @@ impl> Middleware for IdentityService { fn start(&self, req: &mut HttpRequest) -> Result { let mut req = req.clone(); - let fut = self.backend - .from_request(&mut req) - .then(move |res| match res { - Ok(id) => { - req.extensions().insert(IdentityBox(Box::new(id))); - FutOk(None) - } - Err(err) => FutErr(err), - }); + let fut = self.backend.from_request(&mut req).then(move |res| match res { + Ok(id) => { + req.extensions().insert(IdentityBox(Box::new(id))); + FutOk(None) + } + Err(err) => FutErr(err), + }); Ok(Started::Future(Box::new(fut))) } fn response( - &self, req: &mut HttpRequest, resp: HttpResponse + &self, req: &mut HttpRequest, resp: HttpResponse, ) -> Result { if let Some(mut id) = req.extensions().remove::() { id.0.write(resp) diff --git a/src/middleware/logger.rs b/src/middleware/logger.rs index 28964718..7b5d6c4c 100644 --- a/src/middleware/logger.rs +++ b/src/middleware/logger.rs @@ -254,10 +254,9 @@ impl FormatText { "-".fmt(fmt) } } - FormatText::RequestTime => entry_time - .strftime("[%d/%b/%Y:%H:%M:%S %z]") - .unwrap() - .fmt(fmt), + FormatText::RequestTime => { + entry_time.strftime("[%d/%b/%Y:%H:%M:%S %z]").unwrap().fmt(fmt) + } FormatText::RequestHeader(ref name) => { let s = if let Some(val) = req.headers().get(name) { if let Ok(s) = val.to_str() { @@ -314,10 +313,8 @@ mod tests { let logger = Logger::new("%% %{User-Agent}i %{X-Test}o %{HOME}e %D test"); let mut headers = HeaderMap::new(); - headers.insert( - header::USER_AGENT, - header::HeaderValue::from_static("ACTIX-WEB"), - ); + headers + .insert(header::USER_AGENT, header::HeaderValue::from_static("ACTIX-WEB")); let mut req = HttpRequest::new( Method::GET, Uri::from_str("/").unwrap(), @@ -354,10 +351,8 @@ mod tests { let format = Format::default(); let mut headers = HeaderMap::new(); - headers.insert( - header::USER_AGENT, - header::HeaderValue::from_static("ACTIX-WEB"), - ); + headers + .insert(header::USER_AGENT, header::HeaderValue::from_static("ACTIX-WEB")); let req = HttpRequest::new( Method::GET, Uri::from_str("/").unwrap(), @@ -365,9 +360,7 @@ mod tests { headers, None, ); - let resp = HttpResponse::build(StatusCode::OK) - .force_close() - .finish(); + let resp = HttpResponse::build(StatusCode::OK).force_close().finish(); let entry_time = time::now(); let render = |fmt: &mut Formatter| { @@ -388,9 +381,7 @@ mod tests { HeaderMap::new(), None, ); - let resp = HttpResponse::build(StatusCode::OK) - .force_close() - .finish(); + let resp = HttpResponse::build(StatusCode::OK).force_close().finish(); let entry_time = time::now(); let render = |fmt: &mut Formatter| { diff --git a/src/middleware/mod.rs b/src/middleware/mod.rs index c437b254..b9d3847d 100644 --- a/src/middleware/mod.rs +++ b/src/middleware/mod.rs @@ -21,8 +21,9 @@ pub use self::logger::Logger; #[cfg(feature = "session")] #[doc(hidden)] -#[deprecated(since = "0.5.4", - note = "please use `actix_web::middleware::session` instead")] +#[deprecated( + since = "0.5.4", note = "please use `actix_web::middleware::session` instead" +)] pub use self::session::{CookieSessionBackend, CookieSessionError, RequestSession, Session, SessionBackend, SessionImpl, SessionStorage}; @@ -65,7 +66,7 @@ pub trait Middleware: 'static { /// Method is called when handler returns response, /// but before sending http message to peer. fn response( - &self, req: &mut HttpRequest, resp: HttpResponse + &self, req: &mut HttpRequest, resp: HttpResponse, ) -> Result { Ok(Response::Done(resp)) } diff --git a/src/middleware/session.rs b/src/middleware/session.rs index c71ed5a6..9cc7acb1 100644 --- a/src/middleware/session.rs +++ b/src/middleware/session.rs @@ -69,8 +69,8 @@ use std::rc::Rc; use std::sync::Arc; use cookie::{Cookie, CookieJar, Key}; +use futures::future::{err as FutErr, ok as FutOk, FutureResult}; use futures::Future; -use futures::future::{FutureResult, err as FutErr, ok as FutOk}; use http::header::{self, HeaderValue}; use serde::{Deserialize, Serialize}; use serde_json; @@ -202,21 +202,18 @@ impl> Middleware for SessionStorage { fn start(&self, req: &mut HttpRequest) -> Result { let mut req = req.clone(); - let fut = self.0 - .from_request(&mut req) - .then(move |res| match res { - Ok(sess) => { - req.extensions() - .insert(Arc::new(SessionImplBox(Box::new(sess)))); - FutOk(None) - } - Err(err) => FutErr(err), - }); + let fut = self.0.from_request(&mut req).then(move |res| match res { + Ok(sess) => { + req.extensions().insert(Arc::new(SessionImplBox(Box::new(sess)))); + FutOk(None) + } + Err(err) => FutErr(err), + }); Ok(Started::Future(Box::new(fut))) } fn response( - &self, req: &mut HttpRequest, resp: HttpResponse + &self, req: &mut HttpRequest, resp: HttpResponse, ) -> Result { if let Some(s_box) = req.extensions().remove::>() { s_box.0.write(resp) @@ -349,7 +346,7 @@ impl CookieSessionInner { } fn set_cookie( - &self, resp: &mut HttpResponse, state: &HashMap + &self, resp: &mut HttpResponse, state: &HashMap, ) -> Result<()> { let value = serde_json::to_string(&state).map_err(CookieSessionError::Serialize)?; diff --git a/src/multipart.rs b/src/multipart.rs index 87d4b1ad..0fc98000 100644 --- a/src/multipart.rs +++ b/src/multipart.rs @@ -7,8 +7,8 @@ use std::{cmp, fmt}; use bytes::Bytes; use futures::task::{current as current_task, Task}; use futures::{Async, Poll, Stream}; -use http::HttpTryFrom; use http::header::{self, HeaderMap, HeaderName, HeaderValue}; +use http::HttpTryFrom; use httparse; use mime; @@ -122,11 +122,7 @@ where if let Some(err) = self.error.take() { Err(err) } else if self.safety.current() { - self.inner - .as_mut() - .unwrap() - .borrow_mut() - .poll(&self.safety) + self.inner.as_mut().unwrap().borrow_mut().poll(&self.safety) } else { Ok(Async::NotReady) } @@ -168,7 +164,7 @@ where } fn read_boundary( - payload: &mut PayloadHelper, boundary: &str + payload: &mut PayloadHelper, boundary: &str, ) -> Poll { // TODO: need to read epilogue match payload.readline()? { @@ -192,7 +188,7 @@ where } fn skip_until_boundary( - payload: &mut PayloadHelper, boundary: &str + payload: &mut PayloadHelper, boundary: &str, ) -> Poll { let mut eof = false; loop { @@ -230,7 +226,7 @@ where } fn poll( - &mut self, safety: &Safety + &mut self, safety: &Safety, ) -> Poll>, MultipartError> { if self.state == InnerState::Eof { Ok(Async::Ready(None)) @@ -450,7 +446,7 @@ where S: Stream, { fn new( - payload: PayloadRef, boundary: String, headers: &HeaderMap + payload: PayloadRef, boundary: String, headers: &HeaderMap, ) -> Result, PayloadError> { let len = if let Some(len) = headers.get(header::CONTENT_LENGTH) { if let Ok(s) = len.to_str() { @@ -477,7 +473,7 @@ where /// Reads body part content chunk of the specified size. /// The body part must has `Content-Length` header with proper value. fn read_len( - payload: &mut PayloadHelper, size: &mut u64 + payload: &mut PayloadHelper, size: &mut u64, ) -> Poll, MultipartError> { if *size == 0 { Ok(Async::Ready(None)) @@ -502,7 +498,7 @@ where /// Reads content chunk of body part with unknown length. /// The `Content-Length` header for body part is not necessary. fn read_stream( - payload: &mut PayloadHelper, boundary: &str + payload: &mut PayloadHelper, boundary: &str, ) -> Poll, MultipartError> { match payload.read_until(b"\r")? { Async::NotReady => Ok(Async::NotReady), @@ -675,10 +671,7 @@ mod tests { } let mut headers = HeaderMap::new(); - headers.insert( - header::CONTENT_TYPE, - header::HeaderValue::from_static("test"), - ); + headers.insert(header::CONTENT_TYPE, header::HeaderValue::from_static("test")); match Multipart::boundary(&headers) { Err(MultipartError::ParseContentType) => (), diff --git a/src/param.rs b/src/param.rs index 41100763..99cc3def 100644 --- a/src/param.rs +++ b/src/param.rs @@ -94,8 +94,7 @@ impl<'a, 'b, 'c: 'a> Index<&'b str> for &'c Params<'a> { type Output = str; fn index(&self, name: &'b str) -> &str { - self.get(name) - .expect("Value for parameter is not available") + self.get(name).expect("Value for parameter is not available") } } @@ -202,18 +201,9 @@ mod tests { PathBuf::from_param("/test/*tt"), Err(UriSegmentError::BadStart('*')) ); - assert_eq!( - PathBuf::from_param("/test/tt:"), - Err(UriSegmentError::BadEnd(':')) - ); - assert_eq!( - PathBuf::from_param("/test/tt<"), - Err(UriSegmentError::BadEnd('<')) - ); - assert_eq!( - PathBuf::from_param("/test/tt>"), - Err(UriSegmentError::BadEnd('>')) - ); + assert_eq!(PathBuf::from_param("/test/tt:"), Err(UriSegmentError::BadEnd(':'))); + assert_eq!(PathBuf::from_param("/test/tt<"), Err(UriSegmentError::BadEnd('<'))); + assert_eq!(PathBuf::from_param("/test/tt>"), Err(UriSegmentError::BadEnd('>'))); assert_eq!( PathBuf::from_param("/seg1/seg2/"), Ok(PathBuf::from_iter(vec!["seg1", "seg2"])) diff --git a/src/payload.rs b/src/payload.rs index a394c106..d3b5a59b 100644 --- a/src/payload.rs +++ b/src/payload.rs @@ -47,7 +47,9 @@ impl Payload { PayloadSender { inner: Rc::downgrade(&shared), }, - Payload { inner: shared }, + Payload { + inner: shared, + }, ) } @@ -534,10 +536,7 @@ mod tests { assert_eq!(format!("{}", err.cause().unwrap()), "ParseError"); let err = PayloadError::Incomplete; - assert_eq!( - format!("{}", err), - "A payload reached EOF, but is not complete." - ); + assert_eq!(format!("{}", err), "A payload reached EOF, but is not complete."); } #[test] @@ -671,10 +670,7 @@ mod tests { let (mut sender, payload) = Payload::new(false); let mut payload = PayloadHelper::new(payload); - assert_eq!( - Async::NotReady, - payload.read_until(b"ne").ok().unwrap() - ); + assert_eq!(Async::NotReady, payload.read_until(b"ne").ok().unwrap()); sender.feed_data(Bytes::from("line1")); sender.feed_data(Bytes::from("line2")); diff --git a/src/pipeline.rs b/src/pipeline.rs index 3e90a6dc..36cb037a 100644 --- a/src/pipeline.rs +++ b/src/pipeline.rs @@ -67,7 +67,7 @@ impl> PipelineState { } struct PipelineInfo { - req: HttpRequest, + req: UnsafeCell>, count: u16, mws: Rc>>>, context: Option>, @@ -79,7 +79,7 @@ struct PipelineInfo { impl PipelineInfo { fn new(req: HttpRequest) -> PipelineInfo { PipelineInfo { - req, + req: UnsafeCell::new(req), count: 0, mws: Rc::new(Vec::new()), error: None, @@ -89,11 +89,17 @@ impl PipelineInfo { } } + #[inline] + fn req(&self) -> &HttpRequest { + unsafe { &*self.req.get() } + } + + #[inline] #[cfg_attr(feature = "cargo-clippy", allow(mut_from_ref))] fn req_mut(&self) -> &mut HttpRequest { #[allow(mutable_transmutes)] unsafe { - mem::transmute(&self.req) + &mut *self.req.get() } } @@ -116,8 +122,8 @@ impl> Pipeline { handler: Rc>, htype: HandlerType, ) -> Pipeline { let mut info = PipelineInfo { - req, mws, + req: UnsafeCell::new(req), count: 0, error: None, context: None, @@ -159,7 +165,7 @@ impl> HttpHandlerTask for Pipeline { } fn poll_io(&mut self, io: &mut Writer) -> Poll { - let info: &mut PipelineInfo<_> = unsafe { mem::transmute(&mut self.0) }; + let info: &mut PipelineInfo<_> = unsafe { &mut *(&mut self.0 as *mut _) }; loop { if self.1.is_response() { @@ -197,7 +203,7 @@ impl> HttpHandlerTask for Pipeline { } fn poll(&mut self) -> Poll<(), Error> { - let info: &mut PipelineInfo<_> = unsafe { mem::transmute(&mut self.0) }; + let info: &mut PipelineInfo<_> = unsafe { &mut *(&mut self.0 as *mut _) }; loop { match self.1 { @@ -228,17 +234,17 @@ struct StartMiddlewares { impl> StartMiddlewares { fn init( - info: &mut PipelineInfo, hnd: Rc>, htype: HandlerType + info: &mut PipelineInfo, hnd: Rc>, htype: HandlerType, ) -> PipelineState { // execute middlewares, we need this stage because middlewares could be // non-async and we can move to next state immediately let len = info.mws.len() as u16; loop { if info.count == len { - let reply = unsafe { &mut *hnd.get() }.handle(info.req.clone(), htype); + let reply = unsafe { &mut *hnd.get() }.handle(info.req().clone(), htype); return WaitingResponse::init(info, reply); } else { - match info.mws[info.count as usize].start(&mut info.req) { + match info.mws[info.count as usize].start(info.req_mut()) { Ok(Started::Done) => info.count += 1, Ok(Started::Response(resp)) => { return RunMiddlewares::init(info, resp) @@ -278,7 +284,7 @@ impl> StartMiddlewares { } if info.count == len { let reply = unsafe { &mut *self.hnd.get() } - .handle(info.req.clone(), self.htype); + .handle(info.req().clone(), self.htype); return Some(WaitingResponse::init(info, reply)); } else { loop { @@ -462,7 +468,7 @@ impl ProcessResponse { } fn poll_io( - mut self, io: &mut Writer, info: &mut PipelineInfo + mut self, io: &mut Writer, info: &mut PipelineInfo, ) -> Result, PipelineState> { loop { if self.drain.is_none() && self.running != RunningState::Paused { @@ -482,8 +488,7 @@ impl ProcessResponse { Err(err) => { info.error = Some(err.into()); return Ok(FinishingMiddlewares::init( - info, - self.resp, + info, self.resp, )); } }; @@ -525,8 +530,7 @@ impl ProcessResponse { if let Err(err) = io.write_eof() { info.error = Some(err.into()); return Ok(FinishingMiddlewares::init( - info, - self.resp, + info, self.resp, )); } break; @@ -537,8 +541,7 @@ impl ProcessResponse { Err(err) => { info.error = Some(err.into()); return Ok(FinishingMiddlewares::init( - info, - self.resp, + info, self.resp, )); } Ok(result) => result, @@ -572,8 +575,7 @@ impl ProcessResponse { info.error = Some(err.into()); return Ok( FinishingMiddlewares::init( - info, - self.resp, + info, self.resp, ), ); } @@ -585,8 +587,7 @@ impl ProcessResponse { info.error = Some(err.into()); return Ok( FinishingMiddlewares::init( - info, - self.resp, + info, self.resp, ), ); } @@ -611,8 +612,7 @@ impl ProcessResponse { Err(err) => { info.error = Some(err); return Ok(FinishingMiddlewares::init( - info, - self.resp, + info, self.resp, )); } } @@ -796,18 +796,15 @@ mod tests { .unwrap() .run(lazy(|| { let mut info = PipelineInfo::new(HttpRequest::default()); - Completed::<(), Inner<()>>::init(&mut info) - .is_none() - .unwrap(); + Completed::<(), Inner<()>>::init(&mut info).is_none().unwrap(); let req = HttpRequest::default(); let mut ctx = HttpContext::new(req.clone(), MyActor); let addr: Addr = ctx.address(); let mut info = PipelineInfo::new(req); info.context = Some(Box::new(ctx)); - let mut state = Completed::<(), Inner<()>>::init(&mut info) - .completed() - .unwrap(); + let mut state = + Completed::<(), Inner<()>>::init(&mut info).completed().unwrap(); assert!(state.poll(&mut info).is_none()); let pp = Pipeline(info, PipelineState::Completed(state)); diff --git a/src/pred.rs b/src/pred.rs index a712bba6..90a0d61f 100644 --- a/src/pred.rs +++ b/src/pred.rs @@ -171,7 +171,7 @@ pub fn Method(method: http::Method) -> MethodPredicate { /// Return predicate that matches if request contains specified header and /// value. pub fn Header( - name: &'static str, value: &'static str + name: &'static str, value: &'static str, ) -> HeaderPredicate { HeaderPredicate( header::HeaderName::try_from(name).unwrap(), @@ -181,11 +181,7 @@ pub fn Header( } #[doc(hidden)] -pub struct HeaderPredicate( - header::HeaderName, - header::HeaderValue, - PhantomData, -); +pub struct HeaderPredicate(header::HeaderName, header::HeaderValue, PhantomData); impl Predicate for HeaderPredicate { fn check(&self, req: &mut HttpRequest) -> bool { diff --git a/src/resource.rs b/src/resource.rs index c7b886a9..7ce44c0f 100644 --- a/src/resource.rs +++ b/src/resource.rs @@ -132,10 +132,7 @@ impl ResourceHandler { /// ``` pub fn method(&mut self, method: Method) -> &mut Route { self.routes.push(Route::default()); - self.routes - .last_mut() - .unwrap() - .filter(pred::Method(method)) + self.routes.last_mut().unwrap().filter(pred::Method(method)) } /// Register a new route and add handler object. @@ -188,13 +185,11 @@ impl ResourceHandler { /// This is similar to `App's` middlewares, but /// middlewares get invoked on resource level. pub fn middleware>(&mut self, mw: M) { - Rc::get_mut(&mut self.middlewares) - .unwrap() - .push(Box::new(mw)); + Rc::get_mut(&mut self.middlewares).unwrap().push(Box::new(mw)); } pub(crate) fn handle( - &mut self, mut req: HttpRequest, default: Option<&mut ResourceHandler> + &mut self, mut req: HttpRequest, default: Option<&mut ResourceHandler>, ) -> Reply { for route in &mut self.routes { if route.check(&mut req) { diff --git a/src/route.rs b/src/route.rs index 526eb137..346edecd 100644 --- a/src/route.rs +++ b/src/route.rs @@ -50,7 +50,7 @@ impl Route { #[inline] pub(crate) fn compose( - &mut self, req: HttpRequest, mws: Rc>>> + &mut self, req: HttpRequest, mws: Rc>>>, ) -> Reply { Reply::async(Compose::new(req, mws, self.handler.clone())) } @@ -170,7 +170,7 @@ impl Route { /// } /// ``` pub fn with2( - &mut self, handler: F + &mut self, handler: F, ) -> (ExtractorConfig, ExtractorConfig) where F: Fn(T1, T2) -> R + 'static, @@ -180,22 +180,14 @@ impl Route { { let cfg1 = ExtractorConfig::default(); let cfg2 = ExtractorConfig::default(); - self.h(With2::new( - handler, - Clone::clone(&cfg1), - Clone::clone(&cfg2), - )); + self.h(With2::new(handler, Clone::clone(&cfg1), Clone::clone(&cfg2))); (cfg1, cfg2) } /// Set handler function, use request extractor for all paramters. pub fn with3( - &mut self, handler: F - ) -> ( - ExtractorConfig, - ExtractorConfig, - ExtractorConfig, - ) + &mut self, handler: F, + ) -> (ExtractorConfig, ExtractorConfig, ExtractorConfig) where F: Fn(T1, T2, T3) -> R + 'static, R: Responder + 'static, @@ -288,7 +280,7 @@ impl ComposeState { impl Compose { fn new( - req: HttpRequest, mws: Rc>>>, handler: InnerHandler + req: HttpRequest, mws: Rc>>>, handler: InnerHandler, ) -> Self { let mut info = ComposeInfo { count: 0, @@ -298,7 +290,10 @@ impl Compose { }; let state = StartMiddlewares::init(&mut info); - Compose { state, info } + Compose { + state, + info, + } } } diff --git a/src/router.rs b/src/router.rs index 4257d739..35f9d7f5 100644 --- a/src/router.rs +++ b/src/router.rs @@ -80,7 +80,11 @@ impl Router { return None; } let path: &str = unsafe { mem::transmute(&req.path()[self.0.prefix_len..]) }; - let route_path = if path.is_empty() { "/" } else { path }; + let route_path = if path.is_empty() { + "/" + } else { + path + }; for (idx, pattern) in self.0.patterns.iter().enumerate() { if pattern.match_with_params(route_path, req.match_info_mut()) { @@ -98,7 +102,11 @@ impl Router { /// following path would be recognizable `/test/name` but `has_route()` call /// would return `false`. pub fn has_route(&self, path: &str) -> bool { - let path = if path.is_empty() { "/" } else { path }; + let path = if path.is_empty() { + "/" + } else { + path + }; for pattern in &self.0.patterns { if pattern.is_match(path) { @@ -113,7 +121,7 @@ impl Router { /// Check [`HttpRequest::url_for()`](../struct.HttpRequest.html#method. /// url_for) for detailed information. pub fn resource_path( - &self, name: &str, elements: U + &self, name: &str, elements: U, ) -> Result where U: IntoIterator, @@ -245,7 +253,7 @@ impl Resource { } pub fn match_with_params<'a>( - &'a self, path: &'a str, params: &'a mut Params<'a> + &'a self, path: &'a str, params: &'a mut Params<'a>, ) -> bool { match self.tp { PatternType::Static(ref s) => s == path, @@ -270,7 +278,7 @@ impl Resource { /// Build reousrce path. pub fn resource_path( - &self, router: &Router, elements: U + &self, router: &Router, elements: U, ) -> Result where U: IntoIterator, @@ -383,34 +391,19 @@ mod tests { #[test] fn test_recognizer() { let routes = vec![ - ( - Resource::new("", "/name"), - Some(ResourceHandler::default()), - ), - ( - Resource::new("", "/name/{val}"), - Some(ResourceHandler::default()), - ), + (Resource::new("", "/name"), Some(ResourceHandler::default())), + (Resource::new("", "/name/{val}"), Some(ResourceHandler::default())), ( Resource::new("", "/name/{val}/index.html"), Some(ResourceHandler::default()), ), - ( - Resource::new("", "/file/{file}.{ext}"), - Some(ResourceHandler::default()), - ), + (Resource::new("", "/file/{file}.{ext}"), Some(ResourceHandler::default())), ( Resource::new("", "/v{val}/{val2}/index.html"), Some(ResourceHandler::default()), ), - ( - Resource::new("", "/v/{tail:.*}"), - Some(ResourceHandler::default()), - ), - ( - Resource::new("", "{test}/index.html"), - Some(ResourceHandler::default()), - ), + (Resource::new("", "/v/{tail:.*}"), Some(ResourceHandler::default())), + (Resource::new("", "{test}/index.html"), Some(ResourceHandler::default())), ]; let (rec, _) = Router::new::<()>("", ServerSettings::default(), routes); @@ -439,10 +432,7 @@ mod tests { let mut req = TestRequest::with_uri("/v/blah-blah/index.html").finish(); assert_eq!(rec.recognize(&mut req), Some(5)); - assert_eq!( - req.match_info().get("tail").unwrap(), - "blah-blah/index.html" - ); + assert_eq!(req.match_info().get("tail").unwrap(), "blah-blah/index.html"); let mut req = TestRequest::with_uri("/bbb/index.html").finish(); assert_eq!(rec.recognize(&mut req), Some(6)); @@ -452,14 +442,8 @@ mod tests { #[test] fn test_recognizer_2() { let routes = vec![ - ( - Resource::new("", "/index.json"), - Some(ResourceHandler::default()), - ), - ( - Resource::new("", "/{source}.json"), - Some(ResourceHandler::default()), - ), + (Resource::new("", "/index.json"), Some(ResourceHandler::default())), + (Resource::new("", "/{source}.json"), Some(ResourceHandler::default())), ]; let (rec, _) = Router::new::<()>("", ServerSettings::default(), routes); @@ -473,14 +457,8 @@ mod tests { #[test] fn test_recognizer_with_prefix() { let routes = vec![ - ( - Resource::new("", "/name"), - Some(ResourceHandler::default()), - ), - ( - Resource::new("", "/name/{val}"), - Some(ResourceHandler::default()), - ), + (Resource::new("", "/name"), Some(ResourceHandler::default())), + (Resource::new("", "/name/{val}"), Some(ResourceHandler::default())), ]; let (rec, _) = Router::new::<()>("/test", ServerSettings::default(), routes); @@ -497,14 +475,8 @@ mod tests { // same patterns let routes = vec![ - ( - Resource::new("", "/name"), - Some(ResourceHandler::default()), - ), - ( - Resource::new("", "/name/{val}"), - Some(ResourceHandler::default()), - ), + (Resource::new("", "/name"), Some(ResourceHandler::default())), + (Resource::new("", "/name/{val}"), Some(ResourceHandler::default())), ]; let (rec, _) = Router::new::<()>("/test2", ServerSettings::default(), routes); @@ -573,14 +545,8 @@ mod tests { #[test] fn test_request_resource() { let routes = vec![ - ( - Resource::new("r1", "/index.json"), - Some(ResourceHandler::default()), - ), - ( - Resource::new("r2", "/test.json"), - Some(ResourceHandler::default()), - ), + (Resource::new("r1", "/index.json"), Some(ResourceHandler::default())), + (Resource::new("r2", "/test.json"), Some(ResourceHandler::default())), ]; let (router, _) = Router::new::<()>("", ServerSettings::default(), routes); diff --git a/src/server/channel.rs b/src/server/channel.rs index 7a4bc64b..03ec69d9 100644 --- a/src/server/channel.rs +++ b/src/server/channel.rs @@ -7,7 +7,7 @@ use futures::{Async, Future, Poll}; use tokio_io::{AsyncRead, AsyncWrite}; use super::settings::WorkerSettings; -use super::{utils, HttpHandler, IoStream, h1, h2}; +use super::{h1, h2, utils, HttpHandler, IoStream}; const HTTP2_PREFACE: [u8; 14] = *b"PRI * HTTP/2.0"; @@ -93,12 +93,12 @@ where let el = self as *mut _; self.node = Some(Node::new(el)); let _ = match self.proto { - Some(HttpProtocol::H1(ref mut h1)) => self.node - .as_ref() - .map(|n| h1.settings().head().insert(n)), - Some(HttpProtocol::H2(ref mut h2)) => self.node - .as_ref() - .map(|n| h2.settings().head().insert(n)), + Some(HttpProtocol::H1(ref mut h1)) => { + self.node.as_ref().map(|n| h1.settings().head().insert(n)) + } + Some(HttpProtocol::H2(ref mut h2)) => { + self.node.as_ref().map(|n| h2.settings().head().insert(n)) + } Some(HttpProtocol::Unknown(ref mut settings, _, _, _)) => { self.node.as_ref().map(|n| settings.head().insert(n)) } @@ -112,7 +112,9 @@ where match result { Ok(Async::Ready(())) | Err(_) => { h1.settings().remove_channel(); - self.node.as_mut().map(|n| n.remove()); + if let Some(n) = self.node.as_mut() { + n.remove() + }; } _ => (), } @@ -123,7 +125,9 @@ where match result { Ok(Async::Ready(())) | Err(_) => { h2.settings().remove_channel(); - self.node.as_mut().map(|n| n.remove()); + if let Some(n) = self.node.as_mut() { + n.remove() + }; } _ => (), } @@ -139,7 +143,9 @@ where Ok(Async::Ready(0)) | Err(_) => { debug!("Ignored premature client disconnection"); settings.remove_channel(); - self.node.as_mut().map(|n| n.remove()); + if let Some(n) = self.node.as_mut() { + n.remove() + }; return Err(()); } _ => (), @@ -162,12 +168,8 @@ where if let Some(HttpProtocol::Unknown(settings, addr, io, buf)) = self.proto.take() { match kind { ProtocolKind::Http1 => { - self.proto = Some(HttpProtocol::H1(h1::Http1::new( - settings, - io, - addr, - buf, - ))); + self.proto = + Some(HttpProtocol::H1(h1::Http1::new(settings, io, addr, buf))); return self.poll(); } ProtocolKind::Http2 => { @@ -204,7 +206,8 @@ impl Node { #[allow(mutable_transmutes)] unsafe { if let Some(ref next2) = self.next { - let n: &mut Node<()> = mem::transmute(next2.as_ref().unwrap()); + let n: &mut Node<()> = + &mut *(next2.as_ref().unwrap() as *const _ as *mut _); n.prev = Some(next as *const _ as *mut _); } let slf: &mut Node = mem::transmute(self); @@ -275,7 +278,9 @@ where T: AsyncRead + AsyncWrite + 'static, { pub fn new(io: T) -> Self { - WrapperStream { io } + WrapperStream { + io, + } } } diff --git a/src/server/encoding.rs b/src/server/encoding.rs index ae69ae07..6e450f71 100644 --- a/src/server/encoding.rs +++ b/src/server/encoding.rs @@ -763,8 +763,7 @@ impl TransferEncoding { return Ok(*remaining == 0); } let len = cmp::min(*remaining, msg.len() as u64); - self.buffer - .extend(msg.take().split_to(len as usize).into()); + self.buffer.extend(msg.take().split_to(len as usize).into()); *remaining -= len as u64; Ok(*remaining == 0) @@ -856,10 +855,8 @@ impl AcceptEncoding { /// Parse a raw Accept-Encoding header value into an ordered list. pub fn parse(raw: &str) -> ContentEncoding { - let mut encodings: Vec<_> = raw.replace(' ', "") - .split(',') - .map(|l| AcceptEncoding::new(l)) - .collect(); + let mut encodings: Vec<_> = + raw.replace(' ', "").split(',').map(|l| AcceptEncoding::new(l)).collect(); encodings.sort(); for enc in encodings { @@ -879,9 +876,7 @@ mod tests { fn test_chunked_te() { let bytes = SharedBytes::default(); let mut enc = TransferEncoding::chunked(bytes.clone()); - assert!(!enc.encode(Binary::from(b"test".as_ref())) - .ok() - .unwrap()); + assert!(!enc.encode(Binary::from(b"test".as_ref())).ok().unwrap()); assert!(enc.encode(Binary::from(b"".as_ref())).ok().unwrap()); assert_eq!( bytes.get_mut().take().freeze(), diff --git a/src/server/h1.rs b/src/server/h1.rs index e411a788..4a197603 100644 --- a/src/server/h1.rs +++ b/src/server/h1.rs @@ -210,8 +210,7 @@ where self.stream.reset(); if ready { - item.flags - .insert(EntryFlags::EOF | EntryFlags::FINISHED); + item.flags.insert(EntryFlags::EOF | EntryFlags::FINISHED); } else { item.flags.insert(EntryFlags::FINISHED); } @@ -253,10 +252,7 @@ where // cleanup finished tasks let max = self.tasks.len() >= MAX_PIPELINED_MESSAGES; while !self.tasks.is_empty() { - if self.tasks[0] - .flags - .contains(EntryFlags::EOF | EntryFlags::FINISHED) - { + if self.tasks[0].flags.contains(EntryFlags::EOF | EntryFlags::FINISHED) { self.tasks.pop_front(); } else { break; @@ -308,7 +304,10 @@ where pub fn parse(&mut self) { 'outer: loop { match self.decoder.decode(&mut self.buf, &self.settings) { - Ok(Some(Message::Message { msg, payload })) => { + Ok(Some(Message::Message { + msg, + payload, + })) => { self.flags.insert(Flags::STARTED); if payload { @@ -421,13 +420,19 @@ mod tests { impl Message { fn message(self) -> SharedHttpInnerMessage { match self { - Message::Message { msg, payload: _ } => msg, + Message::Message { + msg, + payload: _, + } => msg, _ => panic!("error"), } } fn is_payload(&self) -> bool { match *self { - Message::Message { msg: _, payload } => payload, + Message::Message { + msg: _, + payload, + } => payload, _ => panic!("error"), } } @@ -623,10 +628,7 @@ mod tests { assert_eq!(req.version(), Version::HTTP_11); assert_eq!(*req.method(), Method::GET); assert_eq!(req.path(), "/test"); - assert_eq!( - req.headers().get("test").unwrap().as_bytes(), - b"value" - ); + assert_eq!(req.headers().get("test").unwrap().as_bytes(), b"value"); } Ok(_) | Err(_) => unreachable!("Error during parsing http request"), } @@ -848,12 +850,7 @@ mod tests { assert!(!req.keep_alive()); assert!(req.upgrade()); assert_eq!( - reader - .decode(&mut buf, &settings) - .unwrap() - .unwrap() - .chunk() - .as_ref(), + reader.decode(&mut buf, &settings).unwrap().unwrap().chunk().as_ref(), b"some raw data" ); } @@ -910,30 +907,14 @@ mod tests { buf.extend(b"4\r\ndata\r\n4\r\nline\r\n0\r\n\r\n"); assert_eq!( - reader - .decode(&mut buf, &settings) - .unwrap() - .unwrap() - .chunk() - .as_ref(), + reader.decode(&mut buf, &settings).unwrap().unwrap().chunk().as_ref(), b"data" ); assert_eq!( - reader - .decode(&mut buf, &settings) - .unwrap() - .unwrap() - .chunk() - .as_ref(), + reader.decode(&mut buf, &settings).unwrap().unwrap().chunk().as_ref(), b"line" ); - assert!( - reader - .decode(&mut buf, &settings) - .unwrap() - .unwrap() - .eof() - ); + assert!(reader.decode(&mut buf, &settings).unwrap().unwrap().eof()); } #[test] @@ -1014,13 +995,7 @@ mod tests { assert!(reader.decode(&mut buf, &settings).unwrap().is_none()); buf.extend(b"\r\n"); - assert!( - reader - .decode(&mut buf, &settings) - .unwrap() - .unwrap() - .eof() - ); + assert!(reader.decode(&mut buf, &settings).unwrap().unwrap().eof()); } #[test] @@ -1038,17 +1013,9 @@ mod tests { assert!(req.chunked().unwrap()); buf.extend(b"4;test\r\ndata\r\n4\r\nline\r\n0\r\n\r\n"); // test: test\r\n\r\n") - let chunk = reader - .decode(&mut buf, &settings) - .unwrap() - .unwrap() - .chunk(); + let chunk = reader.decode(&mut buf, &settings).unwrap().unwrap().chunk(); assert_eq!(chunk, Bytes::from_static(b"data")); - let chunk = reader - .decode(&mut buf, &settings) - .unwrap() - .unwrap() - .chunk(); + let chunk = reader.decode(&mut buf, &settings).unwrap().unwrap().chunk(); assert_eq!(chunk, Bytes::from_static(b"line")); let msg = reader.decode(&mut buf, &settings).unwrap().unwrap(); assert!(msg.eof()); diff --git a/src/server/h1decoder.rs b/src/server/h1decoder.rs index d610afc6..3895c8c7 100644 --- a/src/server/h1decoder.rs +++ b/src/server/h1decoder.rs @@ -41,7 +41,9 @@ impl From for DecoderError { impl H1Decoder { pub fn new() -> H1Decoder { - H1Decoder { decoder: None } + H1Decoder { + decoder: None, + } } pub fn decode( @@ -59,9 +61,7 @@ impl H1Decoder { } } - match self.parse_message(src, settings) - .map_err(DecoderError::Error)? - { + match self.parse_message(src, settings).map_err(DecoderError::Error)? { Async::Ready((msg, decoder)) => { if let Some(decoder) = decoder { self.decoder = Some(decoder); @@ -103,7 +103,7 @@ impl H1Decoder { let (len, method, path, version, headers_len) = { let b = unsafe { let b: &[u8] = buf; - mem::transmute(b) + &*(b as *const [u8]) }; let mut req = httparse::Request::new(&mut headers); match req.parse(b)? { @@ -415,10 +415,9 @@ impl ChunkedState { match byte!(rdr) { b'\n' if *size > 0 => Ok(Async::Ready(ChunkedState::Body)), b'\n' if *size == 0 => Ok(Async::Ready(ChunkedState::EndCr)), - _ => Err(io::Error::new( - io::ErrorKind::InvalidInput, - "Invalid chunk size LF", - )), + _ => { + Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk size LF")) + } } } @@ -451,37 +450,33 @@ impl ChunkedState { fn read_body_cr(rdr: &mut BytesMut) -> Poll { match byte!(rdr) { b'\r' => Ok(Async::Ready(ChunkedState::BodyLf)), - _ => Err(io::Error::new( - io::ErrorKind::InvalidInput, - "Invalid chunk body CR", - )), + _ => { + Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk body CR")) + } } } fn read_body_lf(rdr: &mut BytesMut) -> Poll { match byte!(rdr) { b'\n' => Ok(Async::Ready(ChunkedState::Size)), - _ => Err(io::Error::new( - io::ErrorKind::InvalidInput, - "Invalid chunk body LF", - )), + _ => { + Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk body LF")) + } } } fn read_end_cr(rdr: &mut BytesMut) -> Poll { match byte!(rdr) { b'\r' => Ok(Async::Ready(ChunkedState::EndLf)), - _ => Err(io::Error::new( - io::ErrorKind::InvalidInput, - "Invalid chunk end CR", - )), + _ => { + Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk end CR")) + } } } fn read_end_lf(rdr: &mut BytesMut) -> Poll { match byte!(rdr) { b'\n' => Ok(Async::Ready(ChunkedState::End)), - _ => Err(io::Error::new( - io::ErrorKind::InvalidInput, - "Invalid chunk end LF", - )), + _ => { + Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid chunk end LF")) + } } } } diff --git a/src/server/h1writer.rs b/src/server/h1writer.rs index 3d94d44c..08d40d09 100644 --- a/src/server/h1writer.rs +++ b/src/server/h1writer.rs @@ -2,8 +2,8 @@ use bytes::BufMut; use futures::{Async, Poll}; +use std::io; use std::rc::Rc; -use std::{io, mem}; use tokio_io::AsyncWrite; use super::encoding::ContentEncoder; @@ -13,10 +13,10 @@ use super::shared::SharedBytes; use super::{Writer, WriterState, MAX_WRITE_BUFFER_SIZE}; use body::{Binary, Body}; use header::ContentEncoding; +use http::header::{HeaderValue, CONNECTION, CONTENT_LENGTH, DATE}; +use http::{Method, Version}; use httprequest::HttpInnerMessage; use httpresponse::HttpResponse; -use http::{Method, Version}; -use http::header::{HeaderValue, CONNECTION, CONTENT_LENGTH, DATE}; const AVERAGE_HEADER_SIZE: usize = 30; // totally scientific @@ -42,7 +42,7 @@ pub(crate) struct H1Writer { impl H1Writer { pub fn new( - stream: T, buf: SharedBytes, settings: Rc> + stream: T, buf: SharedBytes, settings: Rc>, ) -> H1Writer { H1Writer { flags: Flags::empty(), @@ -117,8 +117,7 @@ impl Writer for H1Writer { let version = msg.version().unwrap_or_else(|| req.version); if msg.upgrade() { self.flags.insert(Flags::UPGRADE); - msg.headers_mut() - .insert(CONNECTION, HeaderValue::from_static("upgrade")); + msg.headers_mut().insert(CONNECTION, HeaderValue::from_static("upgrade")); } // keep-alive else if self.flags.contains(Flags::KEEPALIVE) { @@ -127,8 +126,7 @@ impl Writer for H1Writer { .insert(CONNECTION, HeaderValue::from_static("keep-alive")); } } else if version >= Version::HTTP_11 { - msg.headers_mut() - .insert(CONNECTION, HeaderValue::from_static("close")); + msg.headers_mut().insert(CONNECTION, HeaderValue::from_static("close")); } let body = msg.replace_body(Body::Empty); @@ -169,7 +167,7 @@ impl Writer for H1Writer { let mut pos = 0; let mut has_date = false; let mut remaining = buffer.remaining_mut(); - let mut buf: &mut [u8] = unsafe { mem::transmute(buffer.bytes_mut()) }; + let mut buf = unsafe { &mut *(buffer.bytes_mut() as *mut [u8]) }; for (key, value) in msg.headers() { if is_bin && key == CONTENT_LENGTH { is_bin = false; @@ -184,7 +182,7 @@ impl Writer for H1Writer { pos = 0; buffer.reserve(len); remaining = buffer.remaining_mut(); - buf = unsafe { mem::transmute(buffer.bytes_mut()) }; + buf = unsafe { &mut *(buffer.bytes_mut() as *mut _) }; } buf[pos..pos + k.len()].copy_from_slice(k); @@ -272,7 +270,8 @@ impl Writer for H1Writer { #[inline] fn poll_completed(&mut self, shutdown: bool) -> Poll<(), io::Error> { if !self.buffer.is_empty() { - let buf: &[u8] = unsafe { mem::transmute(self.buffer.as_ref()) }; + let buf: &[u8] = + unsafe { &mut *(self.buffer.as_ref() as *const _ as *mut _) }; let written = self.write_data(buf)?; let _ = self.buffer.split_to(written); if self.buffer.len() > self.buffer_capacity { diff --git a/src/server/h2.rs b/src/server/h2.rs index a5ac2cfc..e2013357 100644 --- a/src/server/h2.rs +++ b/src/server/h2.rs @@ -61,7 +61,7 @@ where H: HttpHandler + 'static, { pub fn new( - settings: Rc>, io: T, addr: Option, buf: Bytes + settings: Rc>, io: T, addr: Option, buf: Bytes, ) -> Self { Http2 { flags: Flags::empty(), diff --git a/src/server/h2writer.rs b/src/server/h2writer.rs index 168fd8af..a9dc06fd 100644 --- a/src/server/h2writer.rs +++ b/src/server/h2writer.rs @@ -45,7 +45,7 @@ pub(crate) struct H2Writer { impl H2Writer { pub fn new( - respond: SendResponse, buf: SharedBytes, settings: Rc> + respond: SendResponse, buf: SharedBytes, settings: Rc>, ) -> H2Writer { H2Writer { respond, @@ -107,8 +107,7 @@ impl Writer for H2Writer { ); } Body::Empty => { - msg.headers_mut() - .insert(CONTENT_LENGTH, HeaderValue::from_static("0")); + msg.headers_mut().insert(CONTENT_LENGTH, HeaderValue::from_static("0")); } _ => (), } @@ -120,9 +119,7 @@ impl Writer for H2Writer { resp.headers_mut().insert(key, value.clone()); } - match self.respond - .send_response(resp, self.flags.contains(Flags::EOF)) - { + match self.respond.send_response(resp, self.flags.contains(Flags::EOF)) { Ok(stream) => self.stream = Some(stream), Err(_) => return Err(io::Error::new(io::ErrorKind::Other, "err")), } diff --git a/src/server/helpers.rs b/src/server/helpers.rs index bb8730ec..ae8c2be8 100644 --- a/src/server/helpers.rs +++ b/src/server/helpers.rs @@ -69,7 +69,7 @@ impl SharedHttpInnerMessage { } pub fn new( - msg: Rc, pool: Rc + msg: Rc, pool: Rc, ) -> SharedHttpInnerMessage { SharedHttpInnerMessage(Some(msg), Some(pool)) } @@ -79,7 +79,7 @@ impl SharedHttpInnerMessage { #[cfg_attr(feature = "cargo-clippy", allow(mut_from_ref, inline_always))] pub fn get_mut(&self) -> &mut HttpInnerMessage { let r: &HttpInnerMessage = self.0.as_ref().unwrap().as_ref(); - unsafe { mem::transmute(r) } + unsafe { &mut *(r as *const _ as *mut _) } } #[inline(always)] @@ -96,9 +96,8 @@ const DEC_DIGITS_LUT: &[u8] = b"0001020304050607080910111213141516171819\ 8081828384858687888990919293949596979899"; pub(crate) fn write_status_line(version: Version, mut n: u16, bytes: &mut BytesMut) { - let mut buf: [u8; 13] = [ - b'H', b'T', b'T', b'P', b'/', b'1', b'.', b'1', b' ', b' ', b' ', b' ', b' ' - ]; + let mut buf: [u8; 13] = + [b'H', b'T', b'T', b'P', b'/', b'1', b'.', b'1', b' ', b' ', b' ', b' ', b' ']; match version { Version::HTTP_2 => buf[5] = b'2', Version::HTTP_10 => buf[7] = b'0', @@ -251,63 +250,33 @@ mod tests { let mut bytes = BytesMut::new(); bytes.reserve(50); write_content_length(0, &mut bytes); - assert_eq!( - bytes.take().freeze(), - b"\r\ncontent-length: 0\r\n"[..] - ); + assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 0\r\n"[..]); bytes.reserve(50); write_content_length(9, &mut bytes); - assert_eq!( - bytes.take().freeze(), - b"\r\ncontent-length: 9\r\n"[..] - ); + assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 9\r\n"[..]); bytes.reserve(50); write_content_length(10, &mut bytes); - assert_eq!( - bytes.take().freeze(), - b"\r\ncontent-length: 10\r\n"[..] - ); + assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 10\r\n"[..]); bytes.reserve(50); write_content_length(99, &mut bytes); - assert_eq!( - bytes.take().freeze(), - b"\r\ncontent-length: 99\r\n"[..] - ); + assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 99\r\n"[..]); bytes.reserve(50); write_content_length(100, &mut bytes); - assert_eq!( - bytes.take().freeze(), - b"\r\ncontent-length: 100\r\n"[..] - ); + assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 100\r\n"[..]); bytes.reserve(50); write_content_length(101, &mut bytes); - assert_eq!( - bytes.take().freeze(), - b"\r\ncontent-length: 101\r\n"[..] - ); + assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 101\r\n"[..]); bytes.reserve(50); write_content_length(998, &mut bytes); - assert_eq!( - bytes.take().freeze(), - b"\r\ncontent-length: 998\r\n"[..] - ); + assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 998\r\n"[..]); bytes.reserve(50); write_content_length(1000, &mut bytes); - assert_eq!( - bytes.take().freeze(), - b"\r\ncontent-length: 1000\r\n"[..] - ); + assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 1000\r\n"[..]); bytes.reserve(50); write_content_length(1001, &mut bytes); - assert_eq!( - bytes.take().freeze(), - b"\r\ncontent-length: 1001\r\n"[..] - ); + assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 1001\r\n"[..]); bytes.reserve(50); write_content_length(5909, &mut bytes); - assert_eq!( - bytes.take().freeze(), - b"\r\ncontent-length: 5909\r\n"[..] - ); + assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 5909\r\n"[..]); } } diff --git a/src/server/settings.rs b/src/server/settings.rs index 1b57db1a..291fcf13 100644 --- a/src/server/settings.rs +++ b/src/server/settings.rs @@ -8,10 +8,10 @@ use std::sync::Arc; use std::{fmt, mem, net}; use time; -use super::KeepAlive; use super::channel::Node; use super::helpers; use super::shared::{SharedBytes, SharedBytesPool}; +use super::KeepAlive; use body::Body; use httpresponse::{HttpResponse, HttpResponseBuilder, HttpResponsePool}; @@ -72,7 +72,7 @@ impl Default for ServerSettings { impl ServerSettings { /// Crate server settings instance pub(crate) fn new( - addr: Option, host: &Option, secure: bool + addr: Option, host: &Option, secure: bool, ) -> ServerSettings { let host = if let Some(ref host) = *host { host.clone() @@ -119,7 +119,7 @@ impl ServerSettings { #[inline] pub(crate) fn get_response_builder( - &self, status: StatusCode + &self, status: StatusCode, ) -> HttpResponseBuilder { HttpResponsePool::get_builder(&self.responses, status) } @@ -255,10 +255,7 @@ mod tests { #[test] fn test_date_len() { - assert_eq!( - DATE_VALUE_LENGTH, - "Sun, 06 Nov 1994 08:49:37 GMT".len() - ); + assert_eq!(DATE_VALUE_LENGTH, "Sun, 06 Nov 1994 08:49:37 GMT".len()); } #[test] diff --git a/src/server/shared.rs b/src/server/shared.rs index a3ddc378..2d7e285b 100644 --- a/src/server/shared.rs +++ b/src/server/shared.rs @@ -1,8 +1,8 @@ use bytes::{BufMut, BytesMut}; use std::cell::RefCell; use std::collections::VecDeque; +use std::io; use std::rc::Rc; -use std::{io, mem}; use body::Binary; @@ -61,7 +61,7 @@ impl SharedBytes { #[cfg_attr(feature = "cargo-clippy", allow(mut_from_ref, inline_always))] pub(crate) fn get_mut(&self) -> &mut BytesMut { let r: &BytesMut = self.0.as_ref().unwrap().as_ref(); - unsafe { mem::transmute(r) } + unsafe { &mut *(r as *const _ as *mut _) } } #[inline] diff --git a/src/server/srv.rs b/src/server/srv.rs index 314dc836..276e1e20 100644 --- a/src/server/srv.rs +++ b/src/server/srv.rs @@ -219,10 +219,7 @@ where if let Some(e) = err.take() { Err(e) } else { - Err(io::Error::new( - io::ErrorKind::Other, - "Can not bind to address.", - )) + Err(io::Error::new(io::ErrorKind::Other, "Can not bind to address.")) } } else { Ok(self) @@ -230,7 +227,7 @@ where } fn start_workers( - &mut self, settings: &ServerSettings, handler: &StreamHandlerType + &mut self, settings: &ServerSettings, handler: &StreamHandlerType, ) -> Vec<(usize, mpsc::UnboundedSender>)> { // start workers let mut workers = Vec::new(); @@ -332,9 +329,9 @@ impl HttpServer { ctx.add_stream(rx); self }); - signals.map(|signals| { + if let Some(signals) = signals { signals.do_send(signal::Subscribe(addr.clone().recipient())) - }); + } addr } } @@ -378,10 +375,7 @@ impl HttpServer { /// Start listening for incoming tls connections. pub fn start_tls(mut self, acceptor: TlsAcceptor) -> io::Result> { if self.sockets.is_empty() { - Err(io::Error::new( - io::ErrorKind::Other, - "No socket addresses are bound", - )) + Err(io::Error::new(io::ErrorKind::Other, "No socket addresses are bound")) } else { let (tx, rx) = mpsc::unbounded(); let addrs: Vec<(net::SocketAddr, net::TcpListener)> = @@ -427,13 +421,10 @@ impl HttpServer { /// /// This method sets alpn protocols to "h2" and "http/1.1" pub fn start_ssl( - mut self, mut builder: SslAcceptorBuilder + mut self, mut builder: SslAcceptorBuilder, ) -> io::Result> { if self.sockets.is_empty() { - Err(io::Error::new( - io::ErrorKind::Other, - "No socket addresses are bound", - )) + Err(io::Error::new(io::ErrorKind::Other, "No socket addresses are bound")) } else { // alpn support if !self.no_http2 { @@ -545,8 +536,9 @@ impl HttpServer { })); self }); - signals - .map(|signals| signals.do_send(signal::Subscribe(addr.clone().recipient()))); + if let Some(signals) = signals { + signals.do_send(signal::Subscribe(addr.clone().recipient())) + } addr } } @@ -562,17 +554,35 @@ impl Handler for HttpServer { signal::SignalType::Int => { info!("SIGINT received, exiting"); self.exit = true; - Handler::::handle(self, StopServer { graceful: false }, ctx); + Handler::::handle( + self, + StopServer { + graceful: false, + }, + ctx, + ); } signal::SignalType::Term => { info!("SIGTERM received, stopping"); self.exit = true; - Handler::::handle(self, StopServer { graceful: true }, ctx); + Handler::::handle( + self, + StopServer { + graceful: true, + }, + ctx, + ); } signal::SignalType::Quit => { info!("SIGQUIT received, exiting"); self.exit = true; - Handler::::handle(self, StopServer { graceful: false }, ctx); + Handler::::handle( + self, + StopServer { + graceful: false, + }, + ctx, + ); } _ => (), } @@ -696,7 +706,9 @@ impl Handler for HttpServer { let tx2 = tx.clone(); worker .1 - .send(StopWorker { graceful: dur }) + .send(StopWorker { + graceful: dur, + }) .into_actor(self) .then(move |_, slf, ctx| { slf.workers.pop(); @@ -746,9 +758,8 @@ fn start_accept_thread( // start accept thread #[cfg_attr(feature = "cargo-clippy", allow(cyclomatic_complexity))] - let _ = thread::Builder::new() - .name(format!("Accept on {}", addr)) - .spawn(move || { + let _ = thread::Builder::new().name(format!("Accept on {}", addr)).spawn( + move || { const SRV: mio::Token = mio::Token(0); const CMD: mio::Token = mio::Token(1); @@ -773,12 +784,9 @@ fn start_accept_thread( } // Start listening for incoming commands - if let Err(err) = poll.register( - ®, - CMD, - mio::Ready::readable(), - mio::PollOpt::edge(), - ) { + if let Err(err) = + poll.register(®, CMD, mio::Ready::readable(), mio::PollOpt::edge()) + { panic!("Can not register Registration: {}", err); } @@ -909,13 +917,14 @@ fn start_accept_thread( } } } - }); + }, + ); (readiness, tx) } fn create_tcp_listener( - addr: net::SocketAddr, backlog: i32 + addr: net::SocketAddr, backlog: i32, ) -> io::Result { let builder = match addr { net::SocketAddr::V4(_) => TcpBuilder::new_v4()?, diff --git a/src/server/utils.rs b/src/server/utils.rs index 430fb211..e0e7e7f6 100644 --- a/src/server/utils.rs +++ b/src/server/utils.rs @@ -8,7 +8,7 @@ const LW_BUFFER_SIZE: usize = 4096; const HW_BUFFER_SIZE: usize = 32_768; pub fn read_from_io( - io: &mut T, buf: &mut BytesMut + io: &mut T, buf: &mut BytesMut, ) -> Poll { unsafe { if buf.remaining_mut() < LW_BUFFER_SIZE { diff --git a/src/server/worker.rs b/src/server/worker.rs index a6ec0711..16eb2946 100644 --- a/src/server/worker.rs +++ b/src/server/worker.rs @@ -1,5 +1,5 @@ -use futures::Future; use futures::unsync::oneshot; +use futures::Future; use net2::TcpStreamExt; use std::rc::Rc; use std::{net, time}; @@ -59,7 +59,7 @@ where impl Worker { pub(crate) fn new( - h: Vec, handler: StreamHandlerType, keep_alive: KeepAlive + h: Vec, handler: StreamHandlerType, keep_alive: KeepAlive, ) -> Worker { let tcp_ka = if let KeepAlive::Tcp(val) = keep_alive { Some(time::Duration::new(val as u64, 0)) @@ -77,13 +77,11 @@ impl Worker { fn update_time(&self, ctx: &mut Context) { self.settings.update_date(); - ctx.run_later(time::Duration::new(1, 0), |slf, ctx| { - slf.update_time(ctx) - }); + ctx.run_later(time::Duration::new(1, 0), |slf, ctx| slf.update_time(ctx)); } fn shutdown_timeout( - &self, ctx: &mut Context, tx: oneshot::Sender, dur: time::Duration + &self, ctx: &mut Context, tx: oneshot::Sender, dur: time::Duration, ) { // sleep for 1 second and then check again ctx.run_later(time::Duration::new(1, 0), move |slf, ctx| { @@ -124,8 +122,7 @@ where if self.tcp_ka.is_some() && msg.io.set_keepalive(self.tcp_ka).is_err() { error!("Can not set socket keep-alive option"); } - self.handler - .handle(Rc::clone(&self.settings), &self.hnd, msg); + self.handler.handle(Rc::clone(&self.settings), &self.hnd, msg); } } @@ -165,7 +162,7 @@ pub(crate) enum StreamHandlerType { impl StreamHandlerType { fn handle( - &mut self, h: Rc>, hnd: &Handle, msg: Conn + &mut self, h: Rc>, hnd: &Handle, msg: Conn, ) { match *self { StreamHandlerType::Normal => { @@ -177,60 +174,57 @@ impl StreamHandlerType { } #[cfg(feature = "tls")] StreamHandlerType::Tls(ref acceptor) => { - let Conn { io, peer, http2 } = msg; + let Conn { + io, + peer, + http2, + } = msg; let _ = io.set_nodelay(true); let io = TcpStream::from_stream(io, hnd) .expect("failed to associate TCP stream"); - hnd.spawn( - TlsAcceptorExt::accept_async(acceptor, io).then(move |res| { - match res { - Ok(io) => Arbiter::handle().spawn(HttpChannel::new( - h, - io, - peer, - http2, - )), - Err(err) => { - trace!("Error during handling tls connection: {}", err) - } - }; - future::result(Ok(())) - }), - ); + hnd.spawn(TlsAcceptorExt::accept_async(acceptor, io).then(move |res| { + match res { + Ok(io) => { + Arbiter::handle().spawn(HttpChannel::new(h, io, peer, http2)) + } + Err(err) => { + trace!("Error during handling tls connection: {}", err) + } + }; + future::result(Ok(())) + })); } #[cfg(feature = "alpn")] StreamHandlerType::Alpn(ref acceptor) => { - let Conn { io, peer, .. } = msg; + let Conn { + io, + peer, + .. + } = msg; let _ = io.set_nodelay(true); let io = TcpStream::from_stream(io, hnd) .expect("failed to associate TCP stream"); - hnd.spawn( - SslAcceptorExt::accept_async(acceptor, io).then(move |res| { - match res { - Ok(io) => { - let http2 = if let Some(p) = - io.get_ref().ssl().selected_alpn_protocol() - { - p.len() == 2 && &p == b"h2" - } else { - false - }; - Arbiter::handle().spawn(HttpChannel::new( - h, - io, - peer, - http2, - )); - } - Err(err) => { - trace!("Error during handling tls connection: {}", err) - } - }; - future::result(Ok(())) - }), - ); + hnd.spawn(SslAcceptorExt::accept_async(acceptor, io).then(move |res| { + match res { + Ok(io) => { + let http2 = if let Some(p) = + io.get_ref().ssl().selected_alpn_protocol() + { + p.len() == 2 && &p == b"h2" + } else { + false + }; + Arbiter::handle() + .spawn(HttpChannel::new(h, io, peer, http2)); + } + Err(err) => { + trace!("Error during handling tls connection: {}", err) + } + }; + future::result(Ok(())) + })); } } } diff --git a/src/test.rs b/src/test.rs index c93e721b..d8ae8067 100644 --- a/src/test.rs +++ b/src/test.rs @@ -170,14 +170,22 @@ impl TestServer { if uri.starts_with('/') { format!( "{}://{}{}", - if self.ssl { "https" } else { "http" }, + if self.ssl { + "https" + } else { + "http" + }, self.addr, uri ) } else { format!( "{}://{}/{}", - if self.ssl { "https" } else { "http" }, + if self.ssl { + "https" + } else { + "http" + }, self.addr, uri ) @@ -202,7 +210,7 @@ impl TestServer { /// Connect to websocket server pub fn ws( - &mut self + &mut self, ) -> Result<(ws::ClientReader, ws::ClientWriter), ws::ClientError> { let url = self.url("/"); self.system.run_until_complete( @@ -350,17 +358,14 @@ pub struct TestApp { impl TestApp { fn new(state: S) -> TestApp { let app = App::with_state(state); - TestApp { app: Some(app) } + TestApp { + app: Some(app), + } } /// Register handler for "/" pub fn handler>(&mut self, handler: H) { - self.app = Some( - self.app - .take() - .unwrap() - .resource("/", |r| r.h(handler)), - ); + self.app = Some(self.app.take().unwrap().resource("/", |r| r.h(handler))); } /// Register middleware @@ -594,7 +599,7 @@ impl TestRequest { /// /// This method panics is handler returns actor or async result. pub fn run>( - self, mut h: H + self, mut h: H, ) -> Result>::Result as Responder>::Error> { let req = self.finish(); let resp = h.handle(req.clone()); diff --git a/src/uri.rs b/src/uri.rs index d30fe5cb..f2e16cec 100644 --- a/src/uri.rs +++ b/src/uri.rs @@ -44,7 +44,10 @@ impl Url { pub fn new(uri: Uri) -> Url { let path = DEFAULT_QUOTER.requote(uri.path().as_bytes()); - Url { uri, path } + Url { + uri, + path, + } } pub fn uri(&self) -> &Uri { diff --git a/src/with.rs b/src/with.rs index 07e9efc4..a18139dc 100644 --- a/src/with.rs +++ b/src/with.rs @@ -187,7 +187,7 @@ where S: 'static, { pub fn new( - f: F, cfg1: ExtractorConfig, cfg2: ExtractorConfig + f: F, cfg1: ExtractorConfig, cfg2: ExtractorConfig, ) -> Self { With2 { hnd: Rc::new(UnsafeCell::new(f)), @@ -307,10 +307,8 @@ where Async::Ready(item) => { self.item = Some(item); self.fut1.take(); - self.fut2 = Some(Box::new(T2::from_request( - &self.req, - self.cfg2.as_ref(), - ))); + self.fut2 = + Some(Box::new(T2::from_request(&self.req, self.cfg2.as_ref()))); } Async::NotReady => return Ok(Async::NotReady), } @@ -510,10 +508,8 @@ where Async::Ready(item) => { self.item1 = Some(item); self.fut1.take(); - self.fut2 = Some(Box::new(T2::from_request( - &self.req, - self.cfg2.as_ref(), - ))); + self.fut2 = + Some(Box::new(T2::from_request(&self.req, self.cfg2.as_ref()))); } Async::NotReady => return Ok(Async::NotReady), } @@ -524,10 +520,8 @@ where Async::Ready(item) => { self.item2 = Some(item); self.fut2.take(); - self.fut3 = Some(Box::new(T3::from_request( - &self.req, - self.cfg3.as_ref(), - ))); + self.fut3 = + Some(Box::new(T3::from_request(&self.req, self.cfg3.as_ref()))); } Async::NotReady => return Ok(Async::NotReady), } @@ -539,15 +533,13 @@ where }; let hnd: &mut F = unsafe { &mut *self.hnd.get() }; - let item = match (*hnd)( - self.item1.take().unwrap(), - self.item2.take().unwrap(), - item, - ).respond_to(self.req.drop_state()) - { - Ok(item) => item.into(), - Err(err) => return Err(err.into()), - }; + let item = + match (*hnd)(self.item1.take().unwrap(), self.item2.take().unwrap(), item) + .respond_to(self.req.drop_state()) + { + Ok(item) => item.into(), + Err(err) => return Err(err.into()), + }; match item.into() { ReplyItem::Message(resp) => return Ok(Async::Ready(resp)), diff --git a/src/ws/client.rs b/src/ws/client.rs index 5a8f10e0..174ee4a1 100644 --- a/src/ws/client.rs +++ b/src/ws/client.rs @@ -121,7 +121,7 @@ impl Client { /// Create new websocket connection with custom `ClientConnector` pub fn with_connector>( - uri: S, conn: Addr + uri: S, conn: Addr, ) -> Client { let mut cl = Client { request: ClientRequest::build(), @@ -142,9 +142,8 @@ impl Client { U: IntoIterator + 'static, V: AsRef, { - let mut protos = protos - .into_iter() - .fold(String::new(), |acc, s| acc + s.as_ref() + ","); + let mut protos = + protos.into_iter().fold(String::new(), |acc, s| acc + s.as_ref() + ","); protos.pop(); self.protocols = Some(protos); self @@ -218,8 +217,7 @@ impl Client { self.request.upgrade(); self.request.set_header(header::UPGRADE, "websocket"); self.request.set_header(header::CONNECTION, "upgrade"); - self.request - .set_header(header::SEC_WEBSOCKET_VERSION, "13"); + self.request.set_header(header::SEC_WEBSOCKET_VERSION, "13"); self.request.with_connector(self.conn.clone()); if let Some(protocols) = self.protocols.take() { @@ -394,10 +392,7 @@ impl Future for ClientHandshake { encoded, key ); - return Err(ClientError::InvalidChallengeResponse( - encoded, - key.clone(), - )); + return Err(ClientError::InvalidChallengeResponse(encoded, key.clone())); } } else { trace!("Missing SEC-WEBSOCKET-ACCEPT header"); @@ -416,7 +411,9 @@ impl Future for ClientHandshake { inner: Rc::clone(&inner), max_size: self.max_size, }, - ClientWriter { inner }, + ClientWriter { + inner, + }, ))) } } @@ -536,23 +533,13 @@ impl ClientWriter { /// Send ping frame #[inline] pub fn ping(&mut self, message: &str) { - self.write(Frame::message( - Vec::from(message), - OpCode::Ping, - true, - true, - )); + self.write(Frame::message(Vec::from(message), OpCode::Ping, true, true)); } /// Send pong frame #[inline] pub fn pong(&mut self, message: &str) { - self.write(Frame::message( - Vec::from(message), - OpCode::Pong, - true, - true, - )); + self.write(Frame::message(Vec::from(message), OpCode::Pong, true, true)); } /// Send close frame diff --git a/src/ws/context.rs b/src/ws/context.rs index b3831258..f76532cc 100644 --- a/src/ws/context.rs +++ b/src/ws/context.rs @@ -156,23 +156,13 @@ where /// Send ping frame #[inline] pub fn ping(&mut self, message: &str) { - self.write(Frame::message( - Vec::from(message), - OpCode::Ping, - true, - false, - )); + self.write(Frame::message(Vec::from(message), OpCode::Ping, true, false)); } /// Send pong frame #[inline] pub fn pong(&mut self, message: &str) { - self.write(Frame::message( - Vec::from(message), - OpCode::Pong, - true, - false, - )); + self.write(Frame::message(Vec::from(message), OpCode::Pong, true, false)); } /// Send close frame diff --git a/src/ws/frame.rs b/src/ws/frame.rs index de78b31d..5c4d5e4a 100644 --- a/src/ws/frame.rs +++ b/src/ws/frame.rs @@ -8,9 +8,9 @@ use body::Binary; use error::PayloadError; use payload::PayloadHelper; -use ws::ProtocolError; use ws::mask::apply_mask; use ws::proto::{CloseCode, CloseReason, OpCode}; +use ws::ProtocolError; /// A struct representing a `WebSocket` frame. #[derive(Debug)] @@ -36,7 +36,7 @@ impl Frame { NetworkEndian::write_u16(&mut code_bytes, reason.code.into()); let mut payload = Vec::from(&code_bytes[..]); - if let Some(description) = reason.description{ + if let Some(description) = reason.description { payload.extend(description.as_bytes()); } payload @@ -48,7 +48,7 @@ impl Frame { #[cfg_attr(feature = "cargo-clippy", allow(type_complexity))] fn read_copy_md( - pl: &mut PayloadHelper, server: bool, max_size: usize + pl: &mut PayloadHelper, server: bool, max_size: usize, ) -> Poll)>, ProtocolError> where S: Stream, @@ -122,17 +122,11 @@ impl Frame { None }; - Ok(Async::Ready(Some(( - idx, - finished, - opcode, - length, - mask, - )))) + Ok(Async::Ready(Some((idx, finished, opcode, length, mask)))) } fn read_chunk_md( - chunk: &[u8], server: bool, max_size: usize + chunk: &[u8], server: bool, max_size: usize, ) -> Poll<(usize, bool, OpCode, usize, Option), ProtocolError> { let chunk_len = chunk.len(); @@ -203,7 +197,7 @@ impl Frame { /// Parse the input stream into a frame. pub fn parse( - pl: &mut PayloadHelper, server: bool, max_size: usize + pl: &mut PayloadHelper, server: bool, max_size: usize, ) -> Poll, ProtocolError> where S: Stream, @@ -288,7 +282,10 @@ impl Frame { } else { None }; - Some(CloseReason { code, description }) + Some(CloseReason { + code, + description, + }) } else { None } @@ -296,7 +293,7 @@ impl Frame { /// Generate binary representation pub fn message>( - data: B, code: OpCode, finished: bool, genmask: bool + data: B, code: OpCode, finished: bool, genmask: bool, ) -> Binary { let payload = data.into(); let one: u8 = if finished { diff --git a/src/ws/mask.rs b/src/ws/mask.rs index f78258fa..13246d97 100644 --- a/src/ws/mask.rs +++ b/src/ws/mask.rs @@ -28,7 +28,11 @@ fn apply_mask_fast32(buf: &mut [u8], mask_u32: u32) { // Possible first unaligned block. let head = min(len, (8 - (ptr as usize & 0x7)) & 0x3); let mask_u32 = if head > 0 { - let n = if head > 4 { head - 4 } else { head }; + let n = if head > 4 { + head - 4 + } else { + head + }; let mask_u32 = if n > 0 { unsafe { diff --git a/src/ws/mod.rs b/src/ws/mod.rs index 93fd431c..42cd3589 100644 --- a/src/ws/mod.rs +++ b/src/ws/mod.rs @@ -133,24 +133,24 @@ pub enum HandshakeError { impl ResponseError for HandshakeError { fn error_response(&self) -> HttpResponse { match *self { - HandshakeError::GetMethodRequired => HttpResponse::MethodNotAllowed() - .header(header::ALLOW, "GET") - .finish(), + HandshakeError::GetMethodRequired => { + HttpResponse::MethodNotAllowed().header(header::ALLOW, "GET").finish() + } HandshakeError::NoWebsocketUpgrade => HttpResponse::BadRequest() .reason("No WebSocket UPGRADE header found") .finish(), - HandshakeError::NoConnectionUpgrade => HttpResponse::BadRequest() - .reason("No CONNECTION upgrade") - .finish(), + HandshakeError::NoConnectionUpgrade => { + HttpResponse::BadRequest().reason("No CONNECTION upgrade").finish() + } HandshakeError::NoVersionHeader => HttpResponse::BadRequest() .reason("Websocket version header is required") .finish(), - HandshakeError::UnsupportedVersion => HttpResponse::BadRequest() - .reason("Unsupported version") - .finish(), - HandshakeError::BadWebsocketKey => HttpResponse::BadRequest() - .reason("Handshake error") - .finish(), + HandshakeError::UnsupportedVersion => { + HttpResponse::BadRequest().reason("Unsupported version").finish() + } + HandshakeError::BadWebsocketKey => { + HttpResponse::BadRequest().reason("Handshake error").finish() + } } } } @@ -189,7 +189,7 @@ where // /// the returned response headers contain the first protocol in this list // /// which the server also knows. pub fn handshake( - req: &HttpRequest + req: &HttpRequest, ) -> Result { // WebSocket accepts only GET if *req.method() != Method::GET { @@ -216,9 +216,7 @@ pub fn handshake( } // check supported version - if !req.headers() - .contains_key(header::SEC_WEBSOCKET_VERSION) - { + if !req.headers().contains_key(header::SEC_WEBSOCKET_VERSION) { return Err(HandshakeError::NoVersionHeader); } let supported_ver = { @@ -355,10 +353,7 @@ mod tests { HeaderMap::new(), None, ); - assert_eq!( - HandshakeError::GetMethodRequired, - handshake(&req).err().unwrap() - ); + assert_eq!(HandshakeError::GetMethodRequired, handshake(&req).err().unwrap()); let req = HttpRequest::new( Method::GET, @@ -367,16 +362,10 @@ mod tests { HeaderMap::new(), None, ); - assert_eq!( - HandshakeError::NoWebsocketUpgrade, - handshake(&req).err().unwrap() - ); + assert_eq!(HandshakeError::NoWebsocketUpgrade, handshake(&req).err().unwrap()); let mut headers = HeaderMap::new(); - headers.insert( - header::UPGRADE, - header::HeaderValue::from_static("test"), - ); + headers.insert(header::UPGRADE, header::HeaderValue::from_static("test")); let req = HttpRequest::new( Method::GET, Uri::from_str("/").unwrap(), @@ -384,16 +373,10 @@ mod tests { headers, None, ); - assert_eq!( - HandshakeError::NoWebsocketUpgrade, - handshake(&req).err().unwrap() - ); + assert_eq!(HandshakeError::NoWebsocketUpgrade, handshake(&req).err().unwrap()); let mut headers = HeaderMap::new(); - headers.insert( - header::UPGRADE, - header::HeaderValue::from_static("websocket"), - ); + headers.insert(header::UPGRADE, header::HeaderValue::from_static("websocket")); let req = HttpRequest::new( Method::GET, Uri::from_str("/").unwrap(), @@ -401,20 +384,11 @@ mod tests { headers, None, ); - assert_eq!( - HandshakeError::NoConnectionUpgrade, - handshake(&req).err().unwrap() - ); + assert_eq!(HandshakeError::NoConnectionUpgrade, handshake(&req).err().unwrap()); let mut headers = HeaderMap::new(); - headers.insert( - header::UPGRADE, - header::HeaderValue::from_static("websocket"), - ); - headers.insert( - header::CONNECTION, - header::HeaderValue::from_static("upgrade"), - ); + headers.insert(header::UPGRADE, header::HeaderValue::from_static("websocket")); + headers.insert(header::CONNECTION, header::HeaderValue::from_static("upgrade")); let req = HttpRequest::new( Method::GET, Uri::from_str("/").unwrap(), @@ -422,20 +396,11 @@ mod tests { headers, None, ); - assert_eq!( - HandshakeError::NoVersionHeader, - handshake(&req).err().unwrap() - ); + assert_eq!(HandshakeError::NoVersionHeader, handshake(&req).err().unwrap()); let mut headers = HeaderMap::new(); - headers.insert( - header::UPGRADE, - header::HeaderValue::from_static("websocket"), - ); - headers.insert( - header::CONNECTION, - header::HeaderValue::from_static("upgrade"), - ); + headers.insert(header::UPGRADE, header::HeaderValue::from_static("websocket")); + headers.insert(header::CONNECTION, header::HeaderValue::from_static("upgrade")); headers.insert( header::SEC_WEBSOCKET_VERSION, header::HeaderValue::from_static("5"), @@ -447,20 +412,11 @@ mod tests { headers, None, ); - assert_eq!( - HandshakeError::UnsupportedVersion, - handshake(&req).err().unwrap() - ); + assert_eq!(HandshakeError::UnsupportedVersion, handshake(&req).err().unwrap()); let mut headers = HeaderMap::new(); - headers.insert( - header::UPGRADE, - header::HeaderValue::from_static("websocket"), - ); - headers.insert( - header::CONNECTION, - header::HeaderValue::from_static("upgrade"), - ); + headers.insert(header::UPGRADE, header::HeaderValue::from_static("websocket")); + headers.insert(header::CONNECTION, header::HeaderValue::from_static("upgrade")); headers.insert( header::SEC_WEBSOCKET_VERSION, header::HeaderValue::from_static("13"), @@ -472,28 +428,17 @@ mod tests { headers, None, ); - assert_eq!( - HandshakeError::BadWebsocketKey, - handshake(&req).err().unwrap() - ); + assert_eq!(HandshakeError::BadWebsocketKey, handshake(&req).err().unwrap()); let mut headers = HeaderMap::new(); - headers.insert( - header::UPGRADE, - header::HeaderValue::from_static("websocket"), - ); - headers.insert( - header::CONNECTION, - header::HeaderValue::from_static("upgrade"), - ); + headers.insert(header::UPGRADE, header::HeaderValue::from_static("websocket")); + headers.insert(header::CONNECTION, header::HeaderValue::from_static("upgrade")); headers.insert( header::SEC_WEBSOCKET_VERSION, header::HeaderValue::from_static("13"), ); - headers.insert( - header::SEC_WEBSOCKET_KEY, - header::HeaderValue::from_static("13"), - ); + headers + .insert(header::SEC_WEBSOCKET_KEY, header::HeaderValue::from_static("13")); let req = HttpRequest::new( Method::GET, Uri::from_str("/").unwrap(), diff --git a/src/ws/proto.rs b/src/ws/proto.rs index 2851fb9e..6e07ca7e 100644 --- a/src/ws/proto.rs +++ b/src/ws/proto.rs @@ -194,11 +194,11 @@ impl From for CloseReason { } } -impl > From<(CloseCode, T)> for CloseReason { +impl> From<(CloseCode, T)> for CloseReason { fn from(info: (CloseCode, T)) -> Self { - CloseReason{ + CloseReason { code: info.0, - description: Some(info.1.into()) + description: Some(info.1.into()), } } } diff --git a/tests/test_client.rs b/tests/test_client.rs index b9154cc4..fc6007b0 100644 --- a/tests/test_client.rs +++ b/tests/test_client.rs @@ -9,8 +9,8 @@ use std::io::Read; use bytes::Bytes; use flate2::read::GzDecoder; -use futures::Future; use futures::stream::once; +use futures::Future; use rand::Rng; use actix_web::*; @@ -72,10 +72,7 @@ fn test_with_query_parameter() { }) }); - let request = srv.get() - .uri(srv.url("/?qp=5").as_str()) - .finish() - .unwrap(); + let request = srv.get().uri(srv.url("/?qp=5").as_str()).finish().unwrap(); let response = srv.execute(request.send()).unwrap(); assert!(response.status().is_success()); @@ -124,10 +121,8 @@ fn test_client_gzip_encoding() { }); // client request - let request = srv.post() - .content_encoding(http::ContentEncoding::Gzip) - .body(STR) - .unwrap(); + let request = + srv.post().content_encoding(http::ContentEncoding::Gzip).body(STR).unwrap(); let response = srv.execute(request.send()).unwrap(); assert!(response.status().is_success()); @@ -167,10 +162,7 @@ fn test_client_gzip_encoding_large() { #[test] fn test_client_gzip_encoding_large_random() { - let data = rand::thread_rng() - .gen_ascii_chars() - .take(100_000) - .collect::(); + let data = rand::thread_rng().gen_ascii_chars().take(100_000).collect::(); let mut srv = test::TestServer::new(|app| { app.handler(|req: HttpRequest| { @@ -228,10 +220,7 @@ fn test_client_brotli_encoding() { #[cfg(feature = "brotli")] #[test] fn test_client_brotli_encoding_large_random() { - let data = rand::thread_rng() - .gen_ascii_chars() - .take(70_000) - .collect::(); + let data = rand::thread_rng().gen_ascii_chars().take(70_000).collect::(); let mut srv = test::TestServer::new(|app| { app.handler(|req: HttpRequest| { @@ -275,10 +264,8 @@ fn test_client_deflate_encoding() { }); // client request - let request = srv.post() - .content_encoding(http::ContentEncoding::Deflate) - .body(STR) - .unwrap(); + let request = + srv.post().content_encoding(http::ContentEncoding::Deflate).body(STR).unwrap(); let response = srv.execute(request.send()).unwrap(); assert!(response.status().is_success()); @@ -290,10 +277,7 @@ fn test_client_deflate_encoding() { #[cfg(feature = "brotli")] #[test] fn test_client_deflate_encoding_large_random() { - let data = rand::thread_rng() - .gen_ascii_chars() - .take(70_000) - .collect::(); + let data = rand::thread_rng().gen_ascii_chars().take(70_000).collect::(); let mut srv = test::TestServer::new(|app| { app.handler(|req: HttpRequest| { @@ -338,9 +322,7 @@ fn test_client_streaming_explicit() { let body = once(Ok(Bytes::from_static(STR.as_ref()))); - let request = srv.get() - .body(Body::Streaming(Box::new(body))) - .unwrap(); + let request = srv.get().body(Body::Streaming(Box::new(body))).unwrap(); let response = srv.execute(request.send()).unwrap(); assert!(response.status().is_success()); @@ -413,11 +395,8 @@ fn test_client_cookie_handling() { }) }); - let request = srv.get() - .cookie(cookie1.clone()) - .cookie(cookie2.clone()) - .finish() - .unwrap(); + let request = + srv.get().cookie(cookie1.clone()).cookie(cookie2.clone()).finish().unwrap(); let response = srv.execute(request.send()).unwrap(); assert!(response.status().is_success()); let c1 = response.cookie("cookie1").expect("Missing cookie1"); diff --git a/tests/test_handlers.rs b/tests/test_handlers.rs index 7a9abe97..65d72724 100644 --- a/tests/test_handlers.rs +++ b/tests/test_handlers.rs @@ -26,10 +26,7 @@ fn test_path_extractor() { }); // client request - let request = srv.get() - .uri(srv.url("/test/index.html")) - .finish() - .unwrap(); + let request = srv.get().uri(srv.url("/test/index.html")).finish().unwrap(); let response = srv.execute(request.send()).unwrap(); assert!(response.status().is_success()); @@ -47,10 +44,7 @@ fn test_query_extractor() { }); // client request - let request = srv.get() - .uri(srv.url("/index.html?username=test")) - .finish() - .unwrap(); + let request = srv.get().uri(srv.url("/index.html?username=test")).finish().unwrap(); let response = srv.execute(request.send()).unwrap(); assert!(response.status().is_success()); @@ -59,10 +53,7 @@ fn test_query_extractor() { assert_eq!(bytes, Bytes::from_static(b"Welcome test!")); // client request - let request = srv.get() - .uri(srv.url("/index.html")) - .finish() - .unwrap(); + let request = srv.get().uri(srv.url("/index.html")).finish().unwrap(); let response = srv.execute(request.send()).unwrap(); assert_eq!(response.status(), StatusCode::BAD_REQUEST); } @@ -78,10 +69,8 @@ fn test_path_and_query_extractor() { }); // client request - let request = srv.get() - .uri(srv.url("/test1/index.html?username=test2")) - .finish() - .unwrap(); + let request = + srv.get().uri(srv.url("/test1/index.html?username=test2")).finish().unwrap(); let response = srv.execute(request.send()).unwrap(); assert!(response.status().is_success()); @@ -90,10 +79,7 @@ fn test_path_and_query_extractor() { assert_eq!(bytes, Bytes::from_static(b"Welcome test1 - test2!")); // client request - let request = srv.get() - .uri(srv.url("/test1/index.html")) - .finish() - .unwrap(); + let request = srv.get().uri(srv.url("/test1/index.html")).finish().unwrap(); let response = srv.execute(request.send()).unwrap(); assert_eq!(response.status(), StatusCode::BAD_REQUEST); } @@ -102,18 +88,15 @@ fn test_path_and_query_extractor() { fn test_path_and_query_extractor2() { let mut srv = test::TestServer::new(|app| { app.resource("/{username}/index.html", |r| { - r.route() - .with3(|_: HttpRequest, p: Path, q: Query| { - format!("Welcome {} - {}!", p.username, q.username) - }) + r.route().with3(|_: HttpRequest, p: Path, q: Query| { + format!("Welcome {} - {}!", p.username, q.username) + }) }); }); // client request - let request = srv.get() - .uri(srv.url("/test1/index.html?username=test2")) - .finish() - .unwrap(); + let request = + srv.get().uri(srv.url("/test1/index.html?username=test2")).finish().unwrap(); let response = srv.execute(request.send()).unwrap(); assert!(response.status().is_success()); @@ -122,10 +105,7 @@ fn test_path_and_query_extractor2() { assert_eq!(bytes, Bytes::from_static(b"Welcome test1 - test2!")); // client request - let request = srv.get() - .uri(srv.url("/test1/index.html")) - .finish() - .unwrap(); + let request = srv.get().uri(srv.url("/test1/index.html")).finish().unwrap(); let response = srv.execute(request.send()).unwrap(); assert_eq!(response.status(), StatusCode::BAD_REQUEST); } @@ -137,10 +117,7 @@ fn test_non_ascii_route() { }); // client request - let request = srv.get() - .uri(srv.url("/中文/index.html")) - .finish() - .unwrap(); + let request = srv.get().uri(srv.url("/中文/index.html")).finish().unwrap(); let response = srv.execute(request.send()).unwrap(); assert!(response.status().is_success()); @@ -158,17 +135,12 @@ fn test_unsafe_path_route() { }); // client request - let request = srv.get() - .uri(srv.url("/test/http%3A%2F%2Fexample.com")) - .finish() - .unwrap(); + let request = + srv.get().uri(srv.url("/test/http%3A%2F%2Fexample.com")).finish().unwrap(); let response = srv.execute(request.send()).unwrap(); assert!(response.status().is_success()); // read response let bytes = srv.execute(response.body()).unwrap(); - assert_eq!( - bytes, - Bytes::from_static(b"success: http:%2F%2Fexample.com") - ); + assert_eq!(bytes, Bytes::from_static(b"success: http:%2F%2Fexample.com")); } diff --git a/tests/test_server.rs b/tests/test_server.rs index cfbff6d8..7bb8a6cd 100644 --- a/tests/test_server.rs +++ b/tests/test_server.rs @@ -14,9 +14,9 @@ extern crate brotli2; #[cfg(feature = "brotli")] use brotli2::write::{BrotliDecoder, BrotliEncoder}; use bytes::{Bytes, BytesMut}; -use flate2::Compression; use flate2::read::GzDecoder; use flate2::write::{DeflateDecoder, DeflateEncoder, GzEncoder}; +use flate2::Compression; use futures::stream::once; use futures::{future, Future, Stream}; use h2::client as h2client; @@ -62,11 +62,9 @@ fn test_start() { thread::spawn(move || { let sys = System::new("test"); let srv = server::new(|| { - vec![ - App::new().resource("/", |r| { - r.method(http::Method::GET).f(|_| HttpResponse::Ok()) - }), - ] + vec![App::new().resource("/", |r| { + r.method(http::Method::GET).f(|_| HttpResponse::Ok()) + })] }); let srv = srv.bind("127.0.0.1:0").unwrap(); @@ -113,11 +111,9 @@ fn test_shutdown() { thread::spawn(move || { let sys = System::new("test"); let srv = server::new(|| { - vec![ - App::new().resource("/", |r| { - r.method(http::Method::GET).f(|_| HttpResponse::Ok()) - }), - ] + vec![App::new().resource("/", |r| { + r.method(http::Method::GET).f(|_| HttpResponse::Ok()) + })] }); let srv = srv.bind("127.0.0.1:0").unwrap(); @@ -135,7 +131,9 @@ fn test_shutdown() { .finish() .unwrap(); let response = sys.run_until_complete(req.send()).unwrap(); - srv_addr.do_send(server::StopServer { graceful: true }); + srv_addr.do_send(server::StopServer { + graceful: true, + }); assert!(response.status().is_success()); } @@ -208,9 +206,7 @@ fn test_body() { fn test_body_gzip() { let mut srv = test::TestServer::new(|app| { app.handler(|_| { - HttpResponse::Ok() - .content_encoding(http::ContentEncoding::Gzip) - .body(STR) + HttpResponse::Ok().content_encoding(http::ContentEncoding::Gzip).body(STR) }) }); @@ -258,10 +254,7 @@ fn test_body_gzip_large() { #[test] fn test_body_gzip_large_random() { - let data = rand::thread_rng() - .gen_ascii_chars() - .take(70_000) - .collect::(); + let data = rand::thread_rng().gen_ascii_chars().take(70_000).collect::(); let srv_data = Arc::new(data.clone()); let mut srv = test::TestServer::new(move |app| { @@ -342,11 +335,7 @@ fn test_body_br_streaming() { #[test] fn test_head_empty() { let mut srv = test::TestServer::new(|app| { - app.handler(|_| { - HttpResponse::Ok() - .content_length(STR.len() as u64) - .finish() - }) + app.handler(|_| HttpResponse::Ok().content_length(STR.len() as u64).finish()) }); let request = srv.head().finish().unwrap(); @@ -354,10 +343,7 @@ fn test_head_empty() { assert!(response.status().is_success()); { - let len = response - .headers() - .get(http::header::CONTENT_LENGTH) - .unwrap(); + let len = response.headers().get(http::header::CONTENT_LENGTH).unwrap(); assert_eq!(format!("{}", STR.len()), len.to_str().unwrap()); } @@ -382,10 +368,7 @@ fn test_head_binary() { assert!(response.status().is_success()); { - let len = response - .headers() - .get(http::header::CONTENT_LENGTH) - .unwrap(); + let len = response.headers().get(http::header::CONTENT_LENGTH).unwrap(); assert_eq!(format!("{}", STR.len()), len.to_str().unwrap()); } @@ -409,10 +392,7 @@ fn test_head_binary2() { assert!(response.status().is_success()); { - let len = response - .headers() - .get(http::header::CONTENT_LENGTH) - .unwrap(); + let len = response.headers().get(http::header::CONTENT_LENGTH).unwrap(); assert_eq!(format!("{}", STR.len()), len.to_str().unwrap()); } } @@ -468,9 +448,7 @@ fn test_body_chunked_explicit() { fn test_body_deflate() { let mut srv = test::TestServer::new(|app| { app.handler(|_| { - HttpResponse::Ok() - .content_encoding(http::ContentEncoding::Deflate) - .body(STR) + HttpResponse::Ok().content_encoding(http::ContentEncoding::Deflate).body(STR) }) }); @@ -494,9 +472,7 @@ fn test_body_deflate() { fn test_body_brotli() { let mut srv = test::TestServer::new(|app| { app.handler(|_| { - HttpResponse::Ok() - .content_encoding(http::ContentEncoding::Br) - .body(STR) + HttpResponse::Ok().content_encoding(http::ContentEncoding::Br).body(STR) }) }); @@ -580,10 +556,7 @@ fn test_gzip_encoding_large() { #[test] fn test_reading_gzip_encoding_large_random() { - let data = rand::thread_rng() - .gen_ascii_chars() - .take(60_000) - .collect::(); + let data = rand::thread_rng().gen_ascii_chars().take(60_000).collect::(); let mut srv = test::TestServer::new(|app| { app.handler(|req: HttpRequest| { @@ -634,10 +607,8 @@ fn test_reading_deflate_encoding() { let enc = e.finish().unwrap(); // client request - let request = srv.post() - .header(http::header::CONTENT_ENCODING, "deflate") - .body(enc) - .unwrap(); + let request = + srv.post().header(http::header::CONTENT_ENCODING, "deflate").body(enc).unwrap(); let response = srv.execute(request.send()).unwrap(); assert!(response.status().is_success()); @@ -666,10 +637,8 @@ fn test_reading_deflate_encoding_large() { let enc = e.finish().unwrap(); // client request - let request = srv.post() - .header(http::header::CONTENT_ENCODING, "deflate") - .body(enc) - .unwrap(); + let request = + srv.post().header(http::header::CONTENT_ENCODING, "deflate").body(enc).unwrap(); let response = srv.execute(request.send()).unwrap(); assert!(response.status().is_success()); @@ -680,10 +649,7 @@ fn test_reading_deflate_encoding_large() { #[test] fn test_reading_deflate_encoding_large_random() { - let data = rand::thread_rng() - .gen_ascii_chars() - .take(160_000) - .collect::(); + let data = rand::thread_rng().gen_ascii_chars().take(160_000).collect::(); let mut srv = test::TestServer::new(|app| { app.handler(|req: HttpRequest| { @@ -702,10 +668,8 @@ fn test_reading_deflate_encoding_large_random() { let enc = e.finish().unwrap(); // client request - let request = srv.post() - .header(http::header::CONTENT_ENCODING, "deflate") - .body(enc) - .unwrap(); + let request = + srv.post().header(http::header::CONTENT_ENCODING, "deflate").body(enc).unwrap(); let response = srv.execute(request.send()).unwrap(); assert!(response.status().is_success()); @@ -735,10 +699,8 @@ fn test_brotli_encoding() { let enc = e.finish().unwrap(); // client request - let request = srv.post() - .header(http::header::CONTENT_ENCODING, "br") - .body(enc) - .unwrap(); + let request = + srv.post().header(http::header::CONTENT_ENCODING, "br").body(enc).unwrap(); let response = srv.execute(request.send()).unwrap(); assert!(response.status().is_success()); @@ -768,10 +730,8 @@ fn test_brotli_encoding_large() { let enc = e.finish().unwrap(); // client request - let request = srv.post() - .header(http::header::CONTENT_ENCODING, "br") - .body(enc) - .unwrap(); + let request = + srv.post().header(http::header::CONTENT_ENCODING, "br").body(enc).unwrap(); let response = srv.execute(request.send()).unwrap(); assert!(response.status().is_success()); @@ -789,30 +749,29 @@ fn test_h2() { let handle = core.handle(); let tcp = TcpStream::connect(&addr, &handle); - let tcp = tcp.then(|res| h2client::handshake(res.unwrap())) - .then(move |res| { - let (mut client, h2) = res.unwrap(); + let tcp = tcp.then(|res| h2client::handshake(res.unwrap())).then(move |res| { + let (mut client, h2) = res.unwrap(); - let request = Request::builder() - .uri(format!("https://{}/", addr).as_str()) - .body(()) - .unwrap(); - let (response, _) = client.send_request(request, false).unwrap(); + let request = Request::builder() + .uri(format!("https://{}/", addr).as_str()) + .body(()) + .unwrap(); + let (response, _) = client.send_request(request, false).unwrap(); - // Spawn a task to run the conn... - handle.spawn(h2.map_err(|e| println!("GOT ERR={:?}", e))); + // Spawn a task to run the conn... + handle.spawn(h2.map_err(|e| println!("GOT ERR={:?}", e))); - response.and_then(|response| { - assert_eq!(response.status(), http::StatusCode::OK); + response.and_then(|response| { + assert_eq!(response.status(), http::StatusCode::OK); - let (_, body) = response.into_parts(); + let (_, body) = response.into_parts(); - body.fold(BytesMut::new(), |mut b, c| -> Result<_, h2::Error> { - b.extend(c); - Ok(b) - }) + body.fold(BytesMut::new(), |mut b, c| -> Result<_, h2::Error> { + b.extend(c); + Ok(b) }) - }); + }) + }); let _res = core.run(tcp); // assert_eq!(res.unwrap(), Bytes::from_static(STR.as_ref())); } @@ -836,28 +795,20 @@ struct MiddlewareTest { impl middleware::Middleware for MiddlewareTest { fn start(&self, _: &mut HttpRequest) -> Result { - self.start.store( - self.start.load(Ordering::Relaxed) + 1, - Ordering::Relaxed, - ); + self.start.store(self.start.load(Ordering::Relaxed) + 1, Ordering::Relaxed); Ok(middleware::Started::Done) } fn response( - &self, _: &mut HttpRequest, resp: HttpResponse + &self, _: &mut HttpRequest, resp: HttpResponse, ) -> Result { - self.response.store( - self.response.load(Ordering::Relaxed) + 1, - Ordering::Relaxed, - ); + self.response + .store(self.response.load(Ordering::Relaxed) + 1, Ordering::Relaxed); Ok(middleware::Response::Done(resp)) } fn finish(&self, _: &mut HttpRequest, _: &HttpResponse) -> middleware::Finished { - self.finish.store( - self.finish.load(Ordering::Relaxed) + 1, - Ordering::Relaxed, - ); + self.finish.store(self.finish.load(Ordering::Relaxed) + 1, Ordering::Relaxed); middleware::Finished::Done } } diff --git a/tests/test_ws.rs b/tests/test_ws.rs index 1283b2e8..563f8f12 100644 --- a/tests/test_ws.rs +++ b/tests/test_ws.rs @@ -44,12 +44,7 @@ fn test_simple() { writer.binary(b"text".as_ref()); let (item, reader) = srv.execute(reader.into_future()).unwrap(); - assert_eq!( - item, - Some(ws::Message::Binary( - Bytes::from_static(b"text").into() - )) - ); + assert_eq!(item, Some(ws::Message::Binary(Bytes::from_static(b"text").into()))); writer.ping("ping"); let (item, reader) = srv.execute(reader.into_future()).unwrap(); @@ -75,7 +70,8 @@ fn test_close_description() { let mut srv = test::TestServer::new(|app| app.handler(|req| ws::start(req, Ws))); let (reader, mut writer) = srv.ws().unwrap(); - let close_reason:ws::CloseReason = (ws::CloseCode::Normal, "close description").into(); + let close_reason: ws::CloseReason = + (ws::CloseCode::Normal, "close description").into(); writer.close(Some(close_reason.clone())); let (item, _) = srv.execute(reader.into_future()).unwrap(); assert_eq!(item, Some(ws::Message::Close(Some(close_reason)))); @@ -83,10 +79,7 @@ fn test_close_description() { #[test] fn test_large_text() { - let data = rand::thread_rng() - .gen_ascii_chars() - .take(65_536) - .collect::(); + let data = rand::thread_rng().gen_ascii_chars().take(65_536).collect::(); let mut srv = test::TestServer::new(|app| app.handler(|req| ws::start(req, Ws))); let (mut reader, mut writer) = srv.ws().unwrap(); @@ -101,10 +94,7 @@ fn test_large_text() { #[test] fn test_large_bin() { - let data = rand::thread_rng() - .gen_ascii_chars() - .take(65_536) - .collect::(); + let data = rand::thread_rng().gen_ascii_chars().take(65_536).collect::(); let mut srv = test::TestServer::new(|app| app.handler(|req| ws::start(req, Ws))); let (mut reader, mut writer) = srv.ws().unwrap(); @@ -113,10 +103,7 @@ fn test_large_bin() { writer.binary(data.clone()); let (item, r) = srv.execute(reader.into_future()).unwrap(); reader = r; - assert_eq!( - item, - Some(ws::Message::Binary(Binary::from(data.clone()))) - ); + assert_eq!(item, Some(ws::Message::Binary(Binary::from(data.clone())))); } } @@ -220,26 +207,20 @@ fn test_ws_server_ssl() { // load ssl keys let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap(); - builder - .set_private_key_file("tests/key.pem", SslFiletype::PEM) - .unwrap(); - builder - .set_certificate_chain_file("tests/cert.pem") - .unwrap(); + builder.set_private_key_file("tests/key.pem", SslFiletype::PEM).unwrap(); + builder.set_certificate_chain_file("tests/cert.pem").unwrap(); - let mut srv = test::TestServer::build() - .ssl(builder.build()) - .start(|app| { - app.handler(|req| { - ws::start( - req, - Ws2 { - count: 0, - bin: false, - }, - ) - }) - }); + let mut srv = test::TestServer::build().ssl(builder.build()).start(|app| { + app.handler(|req| { + ws::start( + req, + Ws2 { + count: 0, + bin: false, + }, + ) + }) + }); let (mut reader, _writer) = srv.ws().unwrap(); let data = Some(ws::Message::Text("0".repeat(65_536))); diff --git a/tools/wsload/src/wsclient.rs b/tools/wsload/src/wsclient.rs index 6c431f2d..0fc36ac9 100644 --- a/tools/wsload/src/wsclient.rs +++ b/tools/wsload/src/wsclient.rs @@ -14,8 +14,8 @@ extern crate url; use futures::Future; use rand::{thread_rng, Rng}; -use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::Arc; use std::time::Duration; use actix::prelude::*; @@ -61,12 +61,8 @@ fn main() { let sample_rate = parse_u64_default(matches.value_of("sample-rate"), 1) as usize; let perf_counters = Arc::new(PerfCounters::new()); - let payload = Arc::new( - thread_rng() - .gen_ascii_chars() - .take(payload_size) - .collect::(), - ); + let payload = + Arc::new(thread_rng().gen_ascii_chars().take(payload_size).collect::()); let sys = actix::System::new("ws-client"); @@ -82,43 +78,40 @@ fn main() { let perf = perf_counters.clone(); let addr = Arbiter::new(format!("test {}", t)); - addr.do_send(actix::msgs::Execute::new( - move || -> Result<(), ()> { - for _ in 0..concurrency { - let pl2 = pl.clone(); - let perf2 = perf.clone(); - let ws2 = ws.clone(); + addr.do_send(actix::msgs::Execute::new(move || -> Result<(), ()> { + for _ in 0..concurrency { + let pl2 = pl.clone(); + let perf2 = perf.clone(); + let ws2 = ws.clone(); - Arbiter::handle().spawn( - ws::Client::new(&ws) - .write_buffer_capacity(0) - .connect() - .map_err(|e| { - println!("Error: {}", e); - //Arbiter::system().do_send(actix::msgs::SystemExit(0)); - () - }) - .map(move |(reader, writer)| { - let addr: Addr = - ChatClient::create(move |ctx| { - ChatClient::add_stream(reader, ctx); - ChatClient { - url: ws2, - conn: writer, - payload: pl2, - bin: bin, - ts: time::precise_time_ns(), - perf_counters: perf2, - sent: 0, - max_payload_size: max_payload_size, - } - }); - }), - ); - } - Ok(()) - }, - )); + Arbiter::handle().spawn( + ws::Client::new(&ws) + .write_buffer_capacity(0) + .connect() + .map_err(|e| { + println!("Error: {}", e); + //Arbiter::system().do_send(actix::msgs::SystemExit(0)); + () + }) + .map(move |(reader, writer)| { + let addr: Addr = ChatClient::create(move |ctx| { + ChatClient::add_stream(reader, ctx); + ChatClient { + url: ws2, + conn: writer, + payload: pl2, + bin: bin, + ts: time::precise_time_ns(), + perf_counters: perf2, + sent: 0, + max_payload_size: max_payload_size, + } + }); + }), + ); + } + Ok(()) + })); } let res = sys.run(); @@ -126,10 +119,7 @@ fn main() { fn parse_u64_default(input: Option<&str>, default: u64) -> u64 { input - .map(|v| { - v.parse() - .expect(&format!("not a valid number: {}", v)) - }) + .map(|v| v.parse().expect(&format!("not a valid number: {}", v))) .unwrap_or(default) } @@ -149,15 +139,13 @@ impl Actor for Perf { impl Perf { fn sample_rate(&self, ctx: &mut Context) { - ctx.run_later( - Duration::new(self.sample_rate_secs as u64, 0), - |act, ctx| { - let req_count = act.counters.pull_request_count(); - if req_count != 0 { - let conns = act.counters.pull_connections_count(); - let latency = act.counters.pull_latency_ns(); - let latency_max = act.counters.pull_latency_max_ns(); - println!( + ctx.run_later(Duration::new(self.sample_rate_secs as u64, 0), |act, ctx| { + let req_count = act.counters.pull_request_count(); + if req_count != 0 { + let conns = act.counters.pull_connections_count(); + let latency = act.counters.pull_latency_ns(); + let latency_max = act.counters.pull_latency_max_ns(); + println!( "rate: {}, conns: {}, throughput: {:?} kb, latency: {}, latency max: {}", req_count / act.sample_rate_secs, conns / act.sample_rate_secs, @@ -166,11 +154,10 @@ impl Perf { time::Duration::nanoseconds((latency / req_count as u64) as i64), time::Duration::nanoseconds(latency_max as i64) ); - } + } - act.sample_rate(ctx); - }, - ); + act.sample_rate(ctx); + }); } } @@ -314,8 +301,7 @@ impl PerfCounters { loop { let current = self.lat_max.load(Ordering::SeqCst); if current >= nanos - || self.lat_max - .compare_and_swap(current, nanos, Ordering::SeqCst) + || self.lat_max.compare_and_swap(current, nanos, Ordering::SeqCst) == current { break;