mirror of https://github.com/rwf2/Rocket.git
Fix data buffer indexing bug. Add from_request example.
This commit is contained in:
parent
15fe6ec8d0
commit
a2e99985b0
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue