Fix data buffer indexing bug. Add from_request example.

This commit is contained in:
Sergio Benitez 2016-11-21 00:45:44 -08:00
parent 15fe6ec8d0
commit a2e99985b0
2 changed files with 83 additions and 18 deletions

View File

@ -138,6 +138,9 @@ impl Data {
io::copy(&mut self.open(), &mut File::create(path)?)
}
// 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`.
#[doc(hidden)]
pub fn new(mut buf: Vec<u8>,
pos: usize,
@ -151,28 +154,38 @@ impl Data {
buf.resize(PEEK_BYTES, 0);
}
// We want to fill the buffer with as many bytes as possible. We also
// want to record if we reach the EOF while filling the buffer. The
// buffer already has `cap` bytes. We read up to buf.len() - 1 bytes,
// and then we try reading 1 more to see if we've reached the EOF.
trace!("Init buffer cap: {}", cap);
let buf_len = buf.len();
let eof = match stream.read(&mut buf[cap..(buf_len - 1)]) {
Ok(n) if n == 0 => true,
Ok(n) => {
trace!("Filled peek buf with {} bytes.", n);
cap += n;
match stream.read(&mut buf[cap..(cap + 1)]) {
Ok(n) => {
cap += n;
n == 0
}
Err(e) => {
error_!("Failed to check stream EOF status: {:?}", e);
false
let eof = if cap < buf_len {
// We have room to read into the buffer. Let's do it.
match stream.read(&mut buf[cap..(buf_len - 1)]) {
Ok(0) => true,
Ok(n) => {
trace!("Filled peek buf with {} bytes.", n);
cap += n;
match stream.read(&mut buf[cap..(cap + 1)]) {
Ok(n) => {
cap += n;
n == 0
}
Err(e) => {
error_!("Failed to check stream EOF status: {:?}", e);
false
}
}
}
Err(e) => {
error_!("Failed to read into peek buffer: {:?}", e);
false
}
}
Err(e) => {
error_!("Failed to read into peek buffer: {:?}", e);
false
}
} else {
// There's no more room in the buffer. Assume there are still bytes.
false
};
trace!("Peek buffer size: {}, remaining: {}", buf_len, buf_len - cap);

View File

@ -19,7 +19,7 @@ impl<S, E> IntoOutcome<S, (StatusCode, E), ()> for Result<S, E> {
/// Trait used to derive an object from incoming request metadata.
///
/// An arbitrary number of types that implement this trait can appears as
/// An arbitrary number of types that implement this trait can appear as
/// parameters in a route handler, as illustrated below:
///
/// ```rust,ignore
@ -62,6 +62,58 @@ impl<S, E> IntoOutcome<S, (StatusCode, E), ()> for Result<S, E> {
/// If the `Outcome` is `Forward`, the request will be forwarded to the next
/// matching request. Note that users can request an `Option<S>` to catch
/// `Forward`s.
///
/// # Example
///
/// Imagine you're running an authenticated API service that requires that some
/// requests be sent along with a valid API key in a header field. You want to
/// ensure that the handlers corresponding to these requests don't get called
/// unless there is an API key in the request and the key is valid. The
/// following example implements this using an `APIKey` type and a `FromRequest`
/// implementation for that type in the `senstive` handler:
///
/// ```rust
/// # #![feature(plugin)]
/// # #![plugin(rocket_codegen)]
/// # extern crate rocket;
/// #
/// use rocket::Outcome;
/// use rocket::http::StatusCode;
/// use rocket::request::{self, Request, FromRequest};
///
/// struct APIKey(String);
///
/// /// Returns true if `key` is a valid API key string.
/// fn is_valid(key: &str) -> bool {
/// key == "valid_api_key"
/// }
///
/// impl<'r> FromRequest<'r> for APIKey {
/// type Error = ();
/// fn from_request(request: &'r Request) -> request::Outcome<APIKey, ()> {
/// if let Some(keys) = request.headers().get_raw("x-api-key") {
/// if keys.len() != 1 {
/// return Outcome::Failure((StatusCode::BadRequest, ()));
/// }
///
/// if let Ok(key) = String::from_utf8(keys[0].clone()) {
/// if is_valid(&key) {
/// return Outcome::Success(APIKey(key));
/// }
/// }
/// }
///
/// Outcome::Forward(())
/// }
/// }
///
/// #[get("/sensitive")]
/// fn sensitive(key: APIKey) -> &'static str {
/// "Sensitive data."
/// }
///
/// # fn main() { }
/// ```
pub trait FromRequest<'r>: Sized {
/// The associated error to be returned when derivation fails.
type Error: Debug;