mirror of
https://github.com/rwf2/Rocket.git
synced 2025-01-31 22:02:03 +00:00
Remove 'testing' feature. Close stream on network error.
This is a breaking change. The `testing` feature no longer exists. Testing structures can now be accessed without any features enabled. Prior to this change, Rocket would panic when draining from a network stream failed. With this change, Rocket force closes the stream on any error. This change also ensures that the `Fairings` launch output only prints if at least one fairing has been attached.
This commit is contained in:
parent
ac0c78a0cd
commit
1e5a1b8940
@ -6,6 +6,3 @@ workspace = "../../"
|
||||
[dependencies]
|
||||
rocket = { path = "../../lib" }
|
||||
rocket_codegen = { path = "../../codegen" }
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
@ -9,6 +9,3 @@ rocket_codegen = { path = "../../codegen" }
|
||||
serde = "0.9"
|
||||
serde_json = "0.9"
|
||||
serde_derive = "0.9"
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
@ -11,6 +11,3 @@ rocket_codegen = { path = "../../codegen" }
|
||||
path = "../../contrib"
|
||||
default-features = false
|
||||
features = ["handlebars_templates"]
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
@ -6,6 +6,3 @@ workspace = "../../"
|
||||
[dependencies]
|
||||
rocket = { path = "../../lib" }
|
||||
rocket_codegen = { path = "../../codegen" }
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
@ -6,6 +6,3 @@ workspace = "../../"
|
||||
[dependencies]
|
||||
rocket = { path = "../../lib" }
|
||||
rocket_codegen = { path = "../../codegen" }
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
@ -6,6 +6,3 @@ workspace = "../../"
|
||||
[dependencies]
|
||||
rocket = { path = "../../lib" }
|
||||
rocket_codegen = { path = "../../codegen" }
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
@ -6,6 +6,3 @@ workspace = "../../"
|
||||
[dependencies]
|
||||
rocket = { path = "../../lib" }
|
||||
rocket_codegen = { path = "../../codegen" }
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
@ -6,6 +6,3 @@ workspace = "../../"
|
||||
[dependencies]
|
||||
rocket = { path = "../../lib" }
|
||||
rocket_codegen = { path = "../../codegen" }
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
@ -14,6 +14,3 @@ serde_json = "0.9"
|
||||
path = "../../contrib"
|
||||
default-features = false
|
||||
features = ["handlebars_templates"]
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
@ -6,6 +6,3 @@ workspace = "../../"
|
||||
[dependencies]
|
||||
rocket = { path = "../../lib" }
|
||||
rocket_codegen = { path = "../../codegen" }
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
@ -6,6 +6,3 @@ workspace = "../../"
|
||||
[dependencies]
|
||||
rocket = { path = "../../lib" }
|
||||
rocket_codegen = { path = "../../codegen" }
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
@ -6,6 +6,3 @@ workspace = "../../"
|
||||
[dependencies]
|
||||
rocket = { path = "../../lib" }
|
||||
rocket_codegen = { path = "../../codegen" }
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
@ -6,6 +6,3 @@ workspace = "../../"
|
||||
[dependencies]
|
||||
rocket = { path = "../../lib", features = ["tls"] }
|
||||
rocket_codegen = { path = "../../codegen" }
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
@ -6,6 +6,3 @@ workspace = "../../"
|
||||
[dependencies]
|
||||
rocket = { path = "../../lib" }
|
||||
rocket_codegen = { path = "../../codegen" }
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
@ -14,6 +14,3 @@ serde_derive = "0.9"
|
||||
path = "../../contrib"
|
||||
default-features = false
|
||||
features = ["json"]
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
@ -7,6 +7,3 @@ workspace = "../.."
|
||||
crossbeam = "*"
|
||||
rocket = { path = "../../lib" }
|
||||
rocket_codegen = { path = "../../codegen" }
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
@ -5,6 +5,3 @@ workspace = "../../"
|
||||
|
||||
[dependencies]
|
||||
rocket = { path = "../../lib" }
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
@ -13,6 +13,3 @@ serde_derive = "0.9"
|
||||
path = "../../contrib"
|
||||
default-features = false
|
||||
features = ["msgpack"]
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
@ -6,6 +6,3 @@ workspace = "../../"
|
||||
[dependencies]
|
||||
rocket = { path = "../../lib" }
|
||||
rocket_codegen = { path = "../../codegen" }
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
@ -6,6 +6,3 @@ workspace = "../../"
|
||||
[dependencies]
|
||||
rocket = { path = "../../lib" }
|
||||
rocket_codegen = { path = "../../codegen" }
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
@ -7,6 +7,3 @@ workspace = "../../"
|
||||
rocket = { path = "../../lib" }
|
||||
rocket_codegen = { path = "../../codegen" }
|
||||
rand = "0.3"
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
@ -6,6 +6,3 @@ workspace = "../../"
|
||||
[dependencies]
|
||||
rocket = { path = "../../lib" }
|
||||
rocket_codegen = { path = "../../codegen" }
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
@ -7,6 +7,3 @@ workspace = "../../"
|
||||
rocket = { path = "../../lib" }
|
||||
rocket_codegen = { path = "../../codegen" }
|
||||
rusqlite = "0.10"
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
@ -6,6 +6,3 @@ workspace = "../../"
|
||||
[dependencies]
|
||||
rocket = { path = "../../lib" }
|
||||
rocket_codegen = { path = "../../codegen" }
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
@ -11,6 +11,3 @@ rocket_codegen = { path = "../../codegen" }
|
||||
path = "../../contrib"
|
||||
default-features = false
|
||||
features = ["handlebars_templates"]
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
@ -6,6 +6,3 @@ workspace = "../../"
|
||||
[dependencies]
|
||||
rocket = { path = "../../lib" }
|
||||
rocket_codegen = { path = "../../codegen" }
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
@ -6,6 +6,3 @@ workspace = "../../"
|
||||
[dependencies]
|
||||
rocket = { path = "../../lib" }
|
||||
rocket_codegen = { path = "../../codegen" }
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
@ -6,6 +6,3 @@ workspace = "../../"
|
||||
[dependencies]
|
||||
rocket = { path = "../../lib" }
|
||||
rocket_codegen = { path = "../../codegen" }
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
@ -13,6 +13,3 @@ lazy_static = "^0.2"
|
||||
default-features = false
|
||||
path = "../../contrib"
|
||||
features = ["uuid"]
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
@ -15,7 +15,6 @@ build = "build.rs"
|
||||
categories = ["web-programming::http-server"]
|
||||
|
||||
[features]
|
||||
testing = []
|
||||
tls = ["rustls", "hyper-rustls"]
|
||||
|
||||
[dependencies]
|
||||
|
@ -18,7 +18,6 @@ fn rocket() -> rocket::Rocket {
|
||||
.mount("/", routes![get, post])
|
||||
}
|
||||
|
||||
#[cfg(feature = "testing")]
|
||||
mod benches {
|
||||
extern crate test;
|
||||
|
||||
|
@ -31,7 +31,6 @@ fn rocket() -> rocket::Rocket {
|
||||
.mount("/", routes![post, post2, post3])
|
||||
}
|
||||
|
||||
#[cfg(feature = "testing")]
|
||||
mod benches {
|
||||
extern crate test;
|
||||
|
||||
|
@ -34,7 +34,6 @@ fn rocket() -> rocket::Rocket {
|
||||
index_b, index_c, index_dyn_a])
|
||||
}
|
||||
|
||||
#[cfg(feature = "testing")]
|
||||
mod benches {
|
||||
extern crate test;
|
||||
|
||||
|
@ -6,8 +6,9 @@ use std::mem::transmute;
|
||||
|
||||
#[cfg(feature = "tls")] use hyper_rustls::WrappedStream;
|
||||
|
||||
use super::data_stream::{DataStream, StreamReader, kill_stream};
|
||||
use super::net_stream::NetStream;
|
||||
use ext::ReadExt;
|
||||
use super::data_stream::{DataStream, HyperNetStream, StreamReader, kill_stream};
|
||||
|
||||
use http::hyper::h1::HttpReader;
|
||||
use http::hyper::buffer;
|
||||
@ -17,6 +18,9 @@ use http::hyper::net::{HttpStream, NetworkStream};
|
||||
pub type BodyReader<'a, 'b> =
|
||||
self::HttpReader<&'a mut self::buffer::BufReader<&'b mut NetworkStream>>;
|
||||
|
||||
/// The number of bytes to read into the "peek" buffer.
|
||||
const PEEK_BYTES: usize = 4096;
|
||||
|
||||
/// Type representing the data in the body of an incoming request.
|
||||
///
|
||||
/// This type is the only means by which the body of a request can be retrieved.
|
||||
@ -90,19 +94,19 @@ impl Data {
|
||||
let net_stream = h_body.get_ref().get_ref();
|
||||
|
||||
#[cfg(feature = "tls")]
|
||||
fn concrete_stream(stream: &&mut NetworkStream) -> Option<HyperNetStream> {
|
||||
fn concrete_stream(stream: &&mut NetworkStream) -> Option<NetStream> {
|
||||
stream.downcast_ref::<HttpStream>()
|
||||
.map(|s| HyperNetStream::Http(s.clone()))
|
||||
.map(|s| NetStream::Http(s.clone()))
|
||||
.or_else(|| {
|
||||
stream.downcast_ref::<WrappedStream>()
|
||||
.map(|s| HyperNetStream::Https(s.clone()))
|
||||
.map(|s| NetStream::Https(s.clone()))
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "tls"))]
|
||||
fn concrete_stream(stream: &&mut NetworkStream) -> Option<HyperNetStream> {
|
||||
fn concrete_stream(stream: &&mut NetworkStream) -> Option<NetStream> {
|
||||
stream.downcast_ref::<HttpStream>()
|
||||
.map(|s| HyperNetStream::Http(s.clone()))
|
||||
.map(|s| NetStream::Http(s.clone()))
|
||||
}
|
||||
|
||||
// Retrieve the underlying HTTPStream from Hyper.
|
||||
@ -164,15 +168,15 @@ impl Data {
|
||||
}
|
||||
|
||||
// Creates a new data object with an internal buffer `buf`, where the cursor
|
||||
// in the buffer is at `pos` and the buffer has `cap` valid bytes. The
|
||||
// remainder of the data bytes can be read from `stream`.
|
||||
// in the buffer is at `pos` and the buffer has `cap` valid bytes. Thus, the
|
||||
// bytes `vec[pos..cap]` are buffered and unread. The remainder of the data
|
||||
// bytes can be read from `stream`.
|
||||
pub(crate) fn new(mut buf: Vec<u8>,
|
||||
pos: usize,
|
||||
mut cap: usize,
|
||||
mut stream: StreamReader
|
||||
) -> Data {
|
||||
// Make sure the buffer is large enough for the bytes we want to peek.
|
||||
const PEEK_BYTES: usize = 4096;
|
||||
if buf.len() < PEEK_BYTES {
|
||||
trace_!("Resizing peek buffer from {} to {}.", buf.len(), PEEK_BYTES);
|
||||
buf.resize(PEEK_BYTES, 0);
|
||||
@ -203,6 +207,27 @@ impl Data {
|
||||
capacity: cap,
|
||||
}
|
||||
}
|
||||
|
||||
/// This creates a `data` object from a local data source `data`.
|
||||
pub(crate) fn local(mut data: Vec<u8>) -> Data {
|
||||
// Emulate peek buffering.
|
||||
let (buf, rest) = if data.len() <= PEEK_BYTES {
|
||||
(data, vec![])
|
||||
} else {
|
||||
let rest = data.split_off(PEEK_BYTES);
|
||||
(data, rest)
|
||||
};
|
||||
|
||||
let (buf_len, stream_len) = (buf.len(), rest.len() as u64);
|
||||
let stream = NetStream::Local(Cursor::new(rest));
|
||||
Data {
|
||||
buffer: buf,
|
||||
stream: HttpReader::SizedReader(stream, stream_len),
|
||||
is_done: stream_len == 0,
|
||||
position: 0,
|
||||
capacity: buf_len,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Data {
|
||||
|
@ -1,80 +1,14 @@
|
||||
use std::io::{self, BufRead, Read, Cursor, BufReader, Chain, Take};
|
||||
use std::net::{SocketAddr, Shutdown};
|
||||
use std::time::Duration;
|
||||
use std::net::Shutdown;
|
||||
|
||||
#[cfg(feature = "tls")] use hyper_rustls::WrappedStream as RustlsStream;
|
||||
use super::net_stream::NetStream;
|
||||
|
||||
use http::hyper::net::{HttpStream, NetworkStream};
|
||||
use http::hyper::net::NetworkStream;
|
||||
use http::hyper::h1::HttpReader;
|
||||
|
||||
pub type StreamReader = HttpReader<HyperNetStream>;
|
||||
pub type StreamReader = HttpReader<NetStream>;
|
||||
pub type InnerStream = Chain<Take<Cursor<Vec<u8>>>, BufReader<StreamReader>>;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum HyperNetStream {
|
||||
Http(HttpStream),
|
||||
#[cfg(feature = "tls")]
|
||||
Https(RustlsStream)
|
||||
}
|
||||
|
||||
macro_rules! with_inner {
|
||||
($net:expr, |$stream:ident| $body:expr) => ({
|
||||
trace!("{}:{}", file!(), line!());
|
||||
match *$net {
|
||||
HyperNetStream::Http(ref $stream) => $body,
|
||||
#[cfg(feature = "tls")] HyperNetStream::Https(ref $stream) => $body
|
||||
}
|
||||
});
|
||||
($net:expr, |mut $stream:ident| $body:expr) => ({
|
||||
trace!("{}:{}", file!(), line!());
|
||||
match *$net {
|
||||
HyperNetStream::Http(ref mut $stream) => $body,
|
||||
#[cfg(feature = "tls")] HyperNetStream::Https(ref mut $stream) => $body
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
impl io::Read for HyperNetStream {
|
||||
#[inline(always)]
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
with_inner!(self, |mut stream| io::Read::read(stream, buf))
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Write for HyperNetStream {
|
||||
#[inline(always)]
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
with_inner!(self, |mut stream| io::Write::write(stream, buf))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
with_inner!(self, |mut stream| io::Write::flush(stream))
|
||||
}
|
||||
}
|
||||
|
||||
impl NetworkStream for HyperNetStream {
|
||||
#[inline(always)]
|
||||
fn peer_addr(&mut self) -> io::Result<SocketAddr> {
|
||||
with_inner!(self, |mut stream| NetworkStream::peer_addr(stream))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
|
||||
with_inner!(self, |stream| NetworkStream::set_read_timeout(stream, dur))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
|
||||
with_inner!(self, |stream| NetworkStream::set_write_timeout(stream, dur))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn close(&mut self, how: Shutdown) -> io::Result<()> {
|
||||
with_inner!(self, |mut stream| NetworkStream::close(stream, how))
|
||||
}
|
||||
}
|
||||
|
||||
/// Raw data stream of a request body.
|
||||
///
|
||||
/// This stream can only be obtained by calling
|
||||
@ -83,12 +17,12 @@ impl NetworkStream for HyperNetStream {
|
||||
/// Instead, it must be used as an opaque `Read` or `BufRead` structure.
|
||||
pub struct DataStream {
|
||||
stream: InnerStream,
|
||||
network: HyperNetStream,
|
||||
network: NetStream,
|
||||
}
|
||||
|
||||
impl DataStream {
|
||||
#[inline(always)]
|
||||
pub(crate) fn new(stream: InnerStream, network: HyperNetStream) -> DataStream {
|
||||
pub(crate) fn new(stream: InnerStream, network: NetStream) -> DataStream {
|
||||
DataStream { stream, network }
|
||||
}
|
||||
}
|
||||
@ -112,19 +46,18 @@ impl BufRead for DataStream {
|
||||
}
|
||||
}
|
||||
|
||||
// pub fn kill_stream<S: Read>(stream: &mut S, network: &mut HyperNetStream) {
|
||||
pub fn kill_stream<S: Read, N: NetworkStream>(stream: &mut S, network: &mut N) {
|
||||
io::copy(&mut stream.take(1024), &mut io::sink()).expect("kill_stream: sink");
|
||||
|
||||
// If there are any more bytes, kill it.
|
||||
let mut buf = [0];
|
||||
if let Ok(n) = stream.read(&mut buf) {
|
||||
if n > 0 {
|
||||
pub fn kill_stream<S: Read, N: NetworkStream>(stream: &mut S, network: &mut N) {
|
||||
// Take <= 1k from the stream. If there might be more data, force close.
|
||||
const FLUSH_LEN: u64 = 1024;
|
||||
match io::copy(&mut stream.take(FLUSH_LEN), &mut io::sink()) {
|
||||
Ok(FLUSH_LEN) | Err(_) => {
|
||||
warn_!("Data left unread. Force closing network stream.");
|
||||
if let Err(e) = network.close(Shutdown::Both) {
|
||||
error_!("Failed to close network stream: {:?}", e);
|
||||
}
|
||||
}
|
||||
Ok(n) => debug!("flushed {} unread bytes", n)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,25 +1,8 @@
|
||||
//! Types and traits for reading and parsing request body data.
|
||||
|
||||
#[cfg(any(test, feature = "testing"))]
|
||||
#[path = "."]
|
||||
mod items {
|
||||
mod test_data;
|
||||
|
||||
pub use self::test_data::Data;
|
||||
pub use self::test_data::DataStream;
|
||||
}
|
||||
|
||||
#[cfg(not(any(test, feature = "testing")))]
|
||||
#[path = "."]
|
||||
mod items {
|
||||
mod data;
|
||||
mod data_stream;
|
||||
|
||||
pub use self::data::Data;
|
||||
pub use self::data_stream::DataStream;
|
||||
}
|
||||
|
||||
mod data;
|
||||
mod data_stream;
|
||||
mod net_stream;
|
||||
mod from_data;
|
||||
|
||||
pub use self::data::Data;
|
||||
pub use self::data_stream::DataStream;
|
||||
pub use self::from_data::{FromData, Outcome};
|
||||
pub use self::items::{Data, DataStream};
|
||||
|
87
lib/src/data/net_stream.rs
Normal file
87
lib/src/data/net_stream.rs
Normal file
@ -0,0 +1,87 @@
|
||||
use std::io::{self, Cursor};
|
||||
use std::net::{SocketAddr, Shutdown};
|
||||
use std::time::Duration;
|
||||
|
||||
#[cfg(feature = "tls")] use hyper_rustls::WrappedStream as RustlsStream;
|
||||
use http::hyper::net::{HttpStream, NetworkStream};
|
||||
|
||||
use self::NetStream::*;
|
||||
|
||||
// This is a representation of all of the possible network streams we might get.
|
||||
// This really shouldn't be necessary, but, you know, Hyper.
|
||||
#[derive(Clone)]
|
||||
pub enum NetStream {
|
||||
Http(HttpStream),
|
||||
#[cfg(feature = "tls")]
|
||||
Https(RustlsStream),
|
||||
Local(Cursor<Vec<u8>>)
|
||||
}
|
||||
|
||||
impl io::Read for NetStream {
|
||||
#[inline(always)]
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
match *self {
|
||||
Http(ref mut stream) => stream.read(buf),
|
||||
Local(ref mut stream) => stream.read(buf),
|
||||
#[cfg(feature = "tls")] Https(ref mut stream) => stream.read(buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Write for NetStream {
|
||||
#[inline(always)]
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
match *self {
|
||||
Http(ref mut stream) => stream.write(buf),
|
||||
Local(ref mut stream) => stream.write(buf),
|
||||
#[cfg(feature = "tls")] Https(ref mut stream) => stream.write(buf)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
match *self {
|
||||
Http(ref mut stream) => stream.flush(),
|
||||
Local(ref mut stream) => stream.flush(),
|
||||
#[cfg(feature = "tls")] Https(ref mut stream) => stream.flush()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NetworkStream for NetStream {
|
||||
#[inline(always)]
|
||||
fn peer_addr(&mut self) -> io::Result<SocketAddr> {
|
||||
match *self {
|
||||
Http(ref mut stream) => stream.peer_addr(),
|
||||
#[cfg(feature = "tls")] Https(ref mut stream) => stream.peer_addr(),
|
||||
Local(_) => Err(io::Error::from(io::ErrorKind::AddrNotAvailable)),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
|
||||
match *self {
|
||||
Http(ref stream) => stream.set_read_timeout(dur),
|
||||
#[cfg(feature = "tls")] Https(ref stream) => stream.set_read_timeout(dur),
|
||||
Local(_) => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
|
||||
match *self {
|
||||
Http(ref stream) => stream.set_write_timeout(dur),
|
||||
#[cfg(feature = "tls")] Https(ref stream) => stream.set_write_timeout(dur),
|
||||
Local(_) => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn close(&mut self, how: Shutdown) -> io::Result<()> {
|
||||
match *self {
|
||||
Http(ref mut stream) => stream.close(how),
|
||||
#[cfg(feature = "tls")] Https(ref mut stream) => stream.close(how),
|
||||
Local(_) => Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
use std::io::{self, Read, BufRead, Write, Cursor, BufReader};
|
||||
use std::path::Path;
|
||||
use std::fs::File;
|
||||
|
||||
use http::hyper::h1::HttpReader;
|
||||
use http::hyper::net::NetworkStream;
|
||||
use http::hyper::buffer;
|
||||
|
||||
pub type BodyReader<'a, 'b> =
|
||||
self::HttpReader<&'a mut self::buffer::BufReader<&'b mut NetworkStream>>;
|
||||
|
||||
const PEEK_BYTES: usize = 4096;
|
||||
|
||||
pub struct DataStream {
|
||||
stream: BufReader<Cursor<Vec<u8>>>,
|
||||
}
|
||||
|
||||
impl Read for DataStream {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.stream.read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl BufRead for DataStream {
|
||||
fn fill_buf(&mut self) -> io::Result<&[u8]> {
|
||||
self.stream.fill_buf()
|
||||
}
|
||||
|
||||
fn consume(&mut self, amt: usize) {
|
||||
self.stream.consume(amt)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Data {
|
||||
data: Vec<u8>,
|
||||
}
|
||||
|
||||
impl Data {
|
||||
pub fn open(self) -> DataStream {
|
||||
DataStream { stream: BufReader::new(Cursor::new(self.data)) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn peek(&self) -> &[u8] {
|
||||
&self.data[..::std::cmp::min(PEEK_BYTES, self.data.len())]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn peek_complete(&self) -> bool {
|
||||
self.data.len() <= PEEK_BYTES
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn stream_to<W: Write>(self, writer: &mut W) -> io::Result<u64> {
|
||||
io::copy(&mut self.open(), writer)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn stream_to_file<P: AsRef<Path>>(self, path: P) -> io::Result<u64> {
|
||||
io::copy(&mut self.open(), &mut File::create(path)?)
|
||||
}
|
||||
|
||||
pub(crate) fn from_hyp(mut h_body: BodyReader) -> Result<Data, &'static str> {
|
||||
let mut vec = Vec::new();
|
||||
if let Err(_) = io::copy(&mut h_body, &mut vec) {
|
||||
return Err("Reading from body failed.");
|
||||
};
|
||||
|
||||
Ok(Data::new(vec))
|
||||
}
|
||||
|
||||
pub(crate) fn new(data: Vec<u8>) -> Data {
|
||||
Data { data: data }
|
||||
}
|
||||
}
|
@ -173,9 +173,17 @@ impl Fairings {
|
||||
}
|
||||
}
|
||||
|
||||
fn num_attached(&self) -> usize {
|
||||
self.launch.len() + self.request.len() + self.response.len()
|
||||
}
|
||||
|
||||
pub fn pretty_print_counts(&self) {
|
||||
use term_painter::ToStyle;
|
||||
use term_painter::Color::White;
|
||||
use term_painter::Color::{White, Magenta};
|
||||
|
||||
if self.num_attached() > 0 {
|
||||
info!("📡 {}:", Magenta.paint("Fairings"));
|
||||
}
|
||||
|
||||
if !self.launch.is_empty() {
|
||||
info_!("{} launch", White.paint(self.launch.len()));
|
||||
|
@ -117,7 +117,7 @@ extern crate smallvec;
|
||||
#[cfg(test)] #[macro_use] extern crate lazy_static;
|
||||
|
||||
#[doc(hidden)] #[macro_use] pub mod logger;
|
||||
#[cfg(any(test, feature = "testing"))] pub mod testing;
|
||||
pub mod testing;
|
||||
pub mod http;
|
||||
pub mod request;
|
||||
pub mod response;
|
||||
|
@ -645,7 +645,6 @@ impl Rocket {
|
||||
return LaunchError::from(LaunchErrorKind::Collision);
|
||||
}
|
||||
|
||||
info!("📡 {}:", Magenta.paint("Fairings"));
|
||||
self.fairings.pretty_print_counts();
|
||||
|
||||
let full_addr = format!("{}:{}", self.config.address, self.config.port);
|
||||
|
@ -1,33 +1,5 @@
|
||||
//! A tiny module for testing Rocket applications.
|
||||
//!
|
||||
//! # Enabling
|
||||
//!
|
||||
//! The `testing` module is only available when Rocket is compiled with the
|
||||
//! `testing` feature flag. The suggested way to enable the `testing` module is
|
||||
//! through Cargo's `[dev-dependencies]` feature which allows features (and
|
||||
//! other dependencies) to be enabled exclusively when testing/benchmarking your
|
||||
//! application.
|
||||
//!
|
||||
//! To compile Rocket with the `testing` feature for testing/benchmarking, add
|
||||
//! the following to your `Cargo.toml`:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dev-dependencies]
|
||||
//! rocket = { version = "*", features = ["testing"] }
|
||||
//! ```
|
||||
//!
|
||||
//! Then, in your testing module, `use` the testing types. This typically looks
|
||||
//! as follows:
|
||||
//!
|
||||
//! ```rust,ignore
|
||||
//! #[cfg(test)]
|
||||
//! mod test {
|
||||
//! use super::rocket;
|
||||
//! use rocket::testing::MockRequest;
|
||||
//! use rocket::http::Method::*;
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! # Usage
|
||||
//!
|
||||
//! The testing methadology is simple:
|
||||
@ -51,9 +23,10 @@
|
||||
//! builds a request for submitting a login form with three fields:
|
||||
//!
|
||||
//! ```rust
|
||||
//! # use rocket::http::Method::*;
|
||||
//! # use rocket::testing::MockRequest;
|
||||
//! # use rocket::http::ContentType;
|
||||
//! use rocket::http::Method::*;
|
||||
//! use rocket::http::ContentType;
|
||||
//! use rocket::testing::MockRequest;
|
||||
//!
|
||||
//! let (username, password, age) = ("user", "password", 32);
|
||||
//! MockRequest::new(Post, "/login")
|
||||
//! .header(ContentType::Form)
|
||||
@ -119,7 +92,7 @@ impl<'r> MockRequest<'r> {
|
||||
pub fn new<S: AsRef<str>>(method: Method, uri: S) -> Self {
|
||||
MockRequest {
|
||||
request: Request::new(method, uri.as_ref().to_string()),
|
||||
data: Data::new(vec![])
|
||||
data: Data::local(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
@ -222,7 +195,7 @@ impl<'r> MockRequest<'r> {
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn body<S: AsRef<[u8]>>(mut self, body: S) -> Self {
|
||||
self.data = Data::new(body.as_ref().into());
|
||||
self.data = Data::local(body.as_ref().into());
|
||||
self
|
||||
}
|
||||
|
||||
@ -261,7 +234,7 @@ impl<'r> MockRequest<'r> {
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn dispatch_with<'s>(&'s mut self, rocket: &'r Rocket) -> Response<'s> {
|
||||
let data = ::std::mem::replace(&mut self.data, Data::new(vec![]));
|
||||
let data = ::std::mem::replace(&mut self.data, Data::local(vec![]));
|
||||
rocket.dispatch(&mut self.request, data)
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ fn bug(form_data: Form<FormData>) -> &'static str {
|
||||
"OK"
|
||||
}
|
||||
|
||||
#[cfg(feature = "testing")]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use rocket::testing::MockRequest;
|
||||
|
@ -15,7 +15,6 @@ fn bug(form_data: Form<FormData>) -> String {
|
||||
form_data.into_inner().form_data
|
||||
}
|
||||
|
||||
#[cfg(feature = "testing")]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use rocket::testing::MockRequest;
|
||||
|
@ -20,7 +20,6 @@ fn other() -> content::JSON<()> {
|
||||
content::JSON(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "testing")]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
|
@ -15,7 +15,6 @@ fn index(form: Form<Simple>) -> String {
|
||||
form.into_inner().value
|
||||
}
|
||||
|
||||
#[cfg(feature = "testing")]
|
||||
mod tests {
|
||||
use rocket;
|
||||
use rocket::config::{Environment, Config, Limits};
|
||||
|
@ -23,7 +23,6 @@ fn specified_html() -> &'static str {
|
||||
"specified_html"
|
||||
}
|
||||
|
||||
#[cfg(feature = "testing")]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
|
@ -18,7 +18,6 @@ fn second() -> &'static str {
|
||||
"no query"
|
||||
}
|
||||
|
||||
#[cfg(feature = "testing")]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
|
@ -10,7 +10,6 @@ fn not_found() -> Redirect {
|
||||
Redirect::to("/")
|
||||
}
|
||||
|
||||
#[cfg(feature = "testing")]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use rocket::testing::MockRequest;
|
||||
|
@ -10,7 +10,6 @@ fn get_ip(remote: SocketAddr) -> String {
|
||||
remote.to_string()
|
||||
}
|
||||
|
||||
#[cfg(feature = "testing")]
|
||||
mod remote_rewrite_tests {
|
||||
use super::*;
|
||||
use rocket::testing::MockRequest;
|
||||
|
@ -30,7 +30,6 @@ fn dual(user: String, path: Segments) -> String {
|
||||
user + "/is/" + &path.collect::<Vec<_>>().join("/")
|
||||
}
|
||||
|
||||
#[cfg(feature = "testing")]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use rocket::testing::MockRequest;
|
||||
|
Loading…
Reference in New Issue
Block a user