2021-04-28 09:01:35 +00:00
|
|
|
use std::{io, time::Duration};
|
2019-09-22 22:48:08 +00:00
|
|
|
use std::task::{Poll, Context};
|
2021-04-28 09:01:35 +00:00
|
|
|
use std::pin::Pin;
|
2016-12-15 08:47:31 +00:00
|
|
|
|
2021-07-09 06:58:25 +00:00
|
|
|
use bytes::{Bytes, BytesMut};
|
UTF-8 routes. Forms revamp. Temp files. Capped.
So. Many. Changes.
This is an insane commit: simultaneously one of the best (because of all
the wonderful improvements!) and one of the worst (because it is just
massive) in the project's history.
Routing:
* All UTF-8 characters are accepted everywhere in route paths. (#998)
* `path` is now `uri` in `route` attribute: `#[route(GET, path = "..")]`
becomes `#[route(GET, uri = "..")]`.
Forms Revamp
* All form related types now reside in a new `form` module.
* Multipart forms are supported. (resolves #106)
* Collections are supported in forms and queries. (resolves #205)
* Nested structures in forms and queries are supported. (resolves #313)
* Form fields can be ad-hoc validated with `#[field(validate = expr)]`.
* `FromFormValue` is now `FromFormField`, blanket implements `FromForm`.
* Form field values are always percent-decoded apriori.
Temporary Files
* A new `TempFile` data and form guard allows streaming data directly to a
file which can then be persisted.
* A new `temp_dir` config parameter specifies where to store `TempFile`.
* The limits `file` and `file/$ext`, where `$ext` is the file extension,
determines the data limit for a `TempFile`.
Capped
* A new `Capped` type is used to indicate when data has been truncated due to
incoming data limits. It allows checking whether data is complete or
truncated.
* `DataStream` methods return `Capped` types.
* `DataStream` API has been revamped to account for `Capped` types.
* Several `Capped<T>` types implement `FromData`, `FromForm`.
* HTTP 413 (Payload Too Large) errors are now returned when data limits are
exceeded. (resolves #972)
Hierarchical Limits
* Data limits are now hierarchical, delimited with `/`. A limit of `a/b/c`
falls back to `a/b` then `a`.
Core
* `&RawStr` no longer implements `FromParam`.
* `&str` implements `FromParam`, `FromData`, `FromForm`.
* `FromTransformedData` was removed.
* `FromData` gained a lifetime for use with request-local data.
* The default error HTML is more compact.
* `&Config` is a request guard.
* The `DataStream` interface was entirely revamped.
* `State` is only exported via `rocket::State`.
* A `request::local_cache!()` macro was added for storing values in
request-local cache without consideration for type uniqueness by using a
locally generated anonymous type.
* `Request::get_param()` is now `Request::param()`.
* `Request::get_segments()` is now `Request::segments()`, takes a range.
* `Request::get_query_value()` is now `Request::query_value()`, can parse any
`FromForm` including sequences.
* `std::io::Error` implements `Responder` like `Debug<std::io::Error>`.
* `(Status, R)` where `R: Responder` implements `Responder` by overriding the
`Status` of `R`.
* The name of a route is printed first during route matching.
* `FlashMessage` now only has one lifetime generic.
HTTP
* `RawStr` implements `serde::{Serialize, Deserialize}`.
* `RawStr` implements _many_ more methods, in particular, those related to the
`Pattern` API.
* `RawStr::from_str()` is now `RawStr::new()`.
* `RawStr::url_decode()` and `RawStr::url_decode_lossy()` only allocate as
necessary, return `Cow`.
* `Status` implements `Default` with `Status::Ok`.
* `Status` implements `PartialEq`, `Eq`, `Hash`, `PartialOrd`, `Ord`.
* Authority and origin part of `Absolute` can be modified with new
`Absolute::{with,set}_authority()`, `Absolute::{with,set}_origin()` methods.
* `Origin::segments()` was removed in favor of methods split into query and
path parts and into raw and decoded versions.
* The `Segments` iterator is smarter, returns decoded `&str` items.
* `Segments::into_path_buf()` is now `Segments::to_path_buf()`.
* A new `QuerySegments` is the analogous query segment iterator.
* Once set, `expires` on private cookies is not overwritten. (resolves #1506)
* `Origin::path()` and `Origin::query()` return `&RawStr`, not `&str`.
Codegen
* Preserve more spans in `uri!` macro.
* Preserve spans `FromForm` field types.
* All dynamic parameters in a query string must typecheck as `FromForm`.
* `FromFormValue` derive removed; `FromFormField` added.
* The `form` `FromForm` and `FromFormField` field attribute is now named
`field`. `#[form(field = ..)]` is now `#[field(name = ..)]`.
Contrib
* `Json` implements `FromForm`.
* `MsgPack` implements `FromForm`.
* The `json!` macro is exported as `rocket_contrib::json::json!`.
* Added clarifying docs to `StaticFiles`.
Examples
* `form_validation` and `form_kitchen_sink` removed in favor of `forms`.
* The `hello_world` example uses unicode in paths.
* The `json` example only allocates as necessary.
Internal
* Codegen uses new `exports` module with the following conventions:
- Locals starts with `__` and are lowercased.
- Rocket modules start with `_` and are lowercased.
- `std` types start with `_` and are titlecased.
- Rocket types are titlecased.
* A `header` module was added to `http`, contains header types.
* `SAFETY` is used as doc-string keyword for `unsafe` related comments.
* The `Uri` parser no longer recognizes Rocket route URIs.
2020-10-30 03:50:06 +00:00
|
|
|
use pin_project_lite::pin_project;
|
2021-04-28 09:01:35 +00:00
|
|
|
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
|
|
|
use tokio::time::{sleep, Sleep};
|
|
|
|
|
|
|
|
use futures::stream::Stream;
|
2021-06-01 18:46:17 +00:00
|
|
|
use futures::future::{self, Future, FutureExt};
|
2019-06-30 16:45:17 +00:00
|
|
|
|
2021-04-14 00:45:09 +00:00
|
|
|
pin_project! {
|
|
|
|
pub struct ReaderStream<R> {
|
|
|
|
#[pin]
|
|
|
|
reader: Option<R>,
|
|
|
|
buf: BytesMut,
|
|
|
|
cap: usize,
|
|
|
|
}
|
2019-06-30 16:45:17 +00:00
|
|
|
}
|
|
|
|
|
2021-04-14 00:45:09 +00:00
|
|
|
impl<R: AsyncRead> Stream for ReaderStream<R> {
|
|
|
|
type Item = std::io::Result<Bytes>;
|
2019-06-30 16:45:17 +00:00
|
|
|
|
2021-04-14 00:45:09 +00:00
|
|
|
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
|
|
|
use tokio_util::io::poll_read_buf;
|
2019-06-30 16:45:17 +00:00
|
|
|
|
2021-04-14 00:45:09 +00:00
|
|
|
let mut this = self.as_mut().project();
|
2019-06-30 16:45:17 +00:00
|
|
|
|
2021-04-14 00:45:09 +00:00
|
|
|
let reader = match this.reader.as_pin_mut() {
|
|
|
|
Some(r) => r,
|
|
|
|
None => return Poll::Ready(None),
|
|
|
|
};
|
|
|
|
|
|
|
|
if this.buf.capacity() == 0 {
|
|
|
|
this.buf.reserve(*this.cap);
|
|
|
|
}
|
|
|
|
|
|
|
|
match poll_read_buf(reader, cx, &mut this.buf) {
|
2019-06-30 16:45:17 +00:00
|
|
|
Poll::Pending => Poll::Pending,
|
2021-04-14 00:45:09 +00:00
|
|
|
Poll::Ready(Err(err)) => {
|
|
|
|
self.project().reader.set(None);
|
|
|
|
Poll::Ready(Some(Err(err)))
|
|
|
|
}
|
|
|
|
Poll::Ready(Ok(0)) => {
|
|
|
|
self.project().reader.set(None);
|
|
|
|
Poll::Ready(None)
|
|
|
|
}
|
|
|
|
Poll::Ready(Ok(_)) => {
|
|
|
|
let chunk = this.buf.split();
|
|
|
|
Poll::Ready(Some(Ok(chunk.freeze())))
|
2016-12-15 08:47:31 +00:00
|
|
|
}
|
|
|
|
}
|
2019-06-30 16:45:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-30 11:17:38 +00:00
|
|
|
pub trait AsyncReadExt: AsyncRead + Sized {
|
2021-04-14 00:45:09 +00:00
|
|
|
fn into_bytes_stream(self, cap: usize) -> ReaderStream<Self> {
|
|
|
|
ReaderStream { reader: Some(self), cap, buf: BytesMut::with_capacity(cap) }
|
2019-06-30 16:45:17 +00:00
|
|
|
}
|
2016-12-15 08:47:31 +00:00
|
|
|
}
|
|
|
|
|
2019-06-30 16:45:17 +00:00
|
|
|
impl<T: AsyncRead> AsyncReadExt for T { }
|
2019-09-22 22:48:08 +00:00
|
|
|
|
UTF-8 routes. Forms revamp. Temp files. Capped.
So. Many. Changes.
This is an insane commit: simultaneously one of the best (because of all
the wonderful improvements!) and one of the worst (because it is just
massive) in the project's history.
Routing:
* All UTF-8 characters are accepted everywhere in route paths. (#998)
* `path` is now `uri` in `route` attribute: `#[route(GET, path = "..")]`
becomes `#[route(GET, uri = "..")]`.
Forms Revamp
* All form related types now reside in a new `form` module.
* Multipart forms are supported. (resolves #106)
* Collections are supported in forms and queries. (resolves #205)
* Nested structures in forms and queries are supported. (resolves #313)
* Form fields can be ad-hoc validated with `#[field(validate = expr)]`.
* `FromFormValue` is now `FromFormField`, blanket implements `FromForm`.
* Form field values are always percent-decoded apriori.
Temporary Files
* A new `TempFile` data and form guard allows streaming data directly to a
file which can then be persisted.
* A new `temp_dir` config parameter specifies where to store `TempFile`.
* The limits `file` and `file/$ext`, where `$ext` is the file extension,
determines the data limit for a `TempFile`.
Capped
* A new `Capped` type is used to indicate when data has been truncated due to
incoming data limits. It allows checking whether data is complete or
truncated.
* `DataStream` methods return `Capped` types.
* `DataStream` API has been revamped to account for `Capped` types.
* Several `Capped<T>` types implement `FromData`, `FromForm`.
* HTTP 413 (Payload Too Large) errors are now returned when data limits are
exceeded. (resolves #972)
Hierarchical Limits
* Data limits are now hierarchical, delimited with `/`. A limit of `a/b/c`
falls back to `a/b` then `a`.
Core
* `&RawStr` no longer implements `FromParam`.
* `&str` implements `FromParam`, `FromData`, `FromForm`.
* `FromTransformedData` was removed.
* `FromData` gained a lifetime for use with request-local data.
* The default error HTML is more compact.
* `&Config` is a request guard.
* The `DataStream` interface was entirely revamped.
* `State` is only exported via `rocket::State`.
* A `request::local_cache!()` macro was added for storing values in
request-local cache without consideration for type uniqueness by using a
locally generated anonymous type.
* `Request::get_param()` is now `Request::param()`.
* `Request::get_segments()` is now `Request::segments()`, takes a range.
* `Request::get_query_value()` is now `Request::query_value()`, can parse any
`FromForm` including sequences.
* `std::io::Error` implements `Responder` like `Debug<std::io::Error>`.
* `(Status, R)` where `R: Responder` implements `Responder` by overriding the
`Status` of `R`.
* The name of a route is printed first during route matching.
* `FlashMessage` now only has one lifetime generic.
HTTP
* `RawStr` implements `serde::{Serialize, Deserialize}`.
* `RawStr` implements _many_ more methods, in particular, those related to the
`Pattern` API.
* `RawStr::from_str()` is now `RawStr::new()`.
* `RawStr::url_decode()` and `RawStr::url_decode_lossy()` only allocate as
necessary, return `Cow`.
* `Status` implements `Default` with `Status::Ok`.
* `Status` implements `PartialEq`, `Eq`, `Hash`, `PartialOrd`, `Ord`.
* Authority and origin part of `Absolute` can be modified with new
`Absolute::{with,set}_authority()`, `Absolute::{with,set}_origin()` methods.
* `Origin::segments()` was removed in favor of methods split into query and
path parts and into raw and decoded versions.
* The `Segments` iterator is smarter, returns decoded `&str` items.
* `Segments::into_path_buf()` is now `Segments::to_path_buf()`.
* A new `QuerySegments` is the analogous query segment iterator.
* Once set, `expires` on private cookies is not overwritten. (resolves #1506)
* `Origin::path()` and `Origin::query()` return `&RawStr`, not `&str`.
Codegen
* Preserve more spans in `uri!` macro.
* Preserve spans `FromForm` field types.
* All dynamic parameters in a query string must typecheck as `FromForm`.
* `FromFormValue` derive removed; `FromFormField` added.
* The `form` `FromForm` and `FromFormField` field attribute is now named
`field`. `#[form(field = ..)]` is now `#[field(name = ..)]`.
Contrib
* `Json` implements `FromForm`.
* `MsgPack` implements `FromForm`.
* The `json!` macro is exported as `rocket_contrib::json::json!`.
* Added clarifying docs to `StaticFiles`.
Examples
* `form_validation` and `form_kitchen_sink` removed in favor of `forms`.
* The `hello_world` example uses unicode in paths.
* The `json` example only allocates as necessary.
Internal
* Codegen uses new `exports` module with the following conventions:
- Locals starts with `__` and are lowercased.
- Rocket modules start with `_` and are lowercased.
- `std` types start with `_` and are titlecased.
- Rocket types are titlecased.
* A `header` module was added to `http`, contains header types.
* `SAFETY` is used as doc-string keyword for `unsafe` related comments.
* The `Uri` parser no longer recognizes Rocket route URIs.
2020-10-30 03:50:06 +00:00
|
|
|
pub trait PollExt<T, E> {
|
|
|
|
fn map_err_ext<U, F>(self, f: F) -> Poll<Option<Result<T, U>>>
|
|
|
|
where F: FnOnce(E) -> U;
|
2019-09-22 22:48:08 +00:00
|
|
|
}
|
|
|
|
|
UTF-8 routes. Forms revamp. Temp files. Capped.
So. Many. Changes.
This is an insane commit: simultaneously one of the best (because of all
the wonderful improvements!) and one of the worst (because it is just
massive) in the project's history.
Routing:
* All UTF-8 characters are accepted everywhere in route paths. (#998)
* `path` is now `uri` in `route` attribute: `#[route(GET, path = "..")]`
becomes `#[route(GET, uri = "..")]`.
Forms Revamp
* All form related types now reside in a new `form` module.
* Multipart forms are supported. (resolves #106)
* Collections are supported in forms and queries. (resolves #205)
* Nested structures in forms and queries are supported. (resolves #313)
* Form fields can be ad-hoc validated with `#[field(validate = expr)]`.
* `FromFormValue` is now `FromFormField`, blanket implements `FromForm`.
* Form field values are always percent-decoded apriori.
Temporary Files
* A new `TempFile` data and form guard allows streaming data directly to a
file which can then be persisted.
* A new `temp_dir` config parameter specifies where to store `TempFile`.
* The limits `file` and `file/$ext`, where `$ext` is the file extension,
determines the data limit for a `TempFile`.
Capped
* A new `Capped` type is used to indicate when data has been truncated due to
incoming data limits. It allows checking whether data is complete or
truncated.
* `DataStream` methods return `Capped` types.
* `DataStream` API has been revamped to account for `Capped` types.
* Several `Capped<T>` types implement `FromData`, `FromForm`.
* HTTP 413 (Payload Too Large) errors are now returned when data limits are
exceeded. (resolves #972)
Hierarchical Limits
* Data limits are now hierarchical, delimited with `/`. A limit of `a/b/c`
falls back to `a/b` then `a`.
Core
* `&RawStr` no longer implements `FromParam`.
* `&str` implements `FromParam`, `FromData`, `FromForm`.
* `FromTransformedData` was removed.
* `FromData` gained a lifetime for use with request-local data.
* The default error HTML is more compact.
* `&Config` is a request guard.
* The `DataStream` interface was entirely revamped.
* `State` is only exported via `rocket::State`.
* A `request::local_cache!()` macro was added for storing values in
request-local cache without consideration for type uniqueness by using a
locally generated anonymous type.
* `Request::get_param()` is now `Request::param()`.
* `Request::get_segments()` is now `Request::segments()`, takes a range.
* `Request::get_query_value()` is now `Request::query_value()`, can parse any
`FromForm` including sequences.
* `std::io::Error` implements `Responder` like `Debug<std::io::Error>`.
* `(Status, R)` where `R: Responder` implements `Responder` by overriding the
`Status` of `R`.
* The name of a route is printed first during route matching.
* `FlashMessage` now only has one lifetime generic.
HTTP
* `RawStr` implements `serde::{Serialize, Deserialize}`.
* `RawStr` implements _many_ more methods, in particular, those related to the
`Pattern` API.
* `RawStr::from_str()` is now `RawStr::new()`.
* `RawStr::url_decode()` and `RawStr::url_decode_lossy()` only allocate as
necessary, return `Cow`.
* `Status` implements `Default` with `Status::Ok`.
* `Status` implements `PartialEq`, `Eq`, `Hash`, `PartialOrd`, `Ord`.
* Authority and origin part of `Absolute` can be modified with new
`Absolute::{with,set}_authority()`, `Absolute::{with,set}_origin()` methods.
* `Origin::segments()` was removed in favor of methods split into query and
path parts and into raw and decoded versions.
* The `Segments` iterator is smarter, returns decoded `&str` items.
* `Segments::into_path_buf()` is now `Segments::to_path_buf()`.
* A new `QuerySegments` is the analogous query segment iterator.
* Once set, `expires` on private cookies is not overwritten. (resolves #1506)
* `Origin::path()` and `Origin::query()` return `&RawStr`, not `&str`.
Codegen
* Preserve more spans in `uri!` macro.
* Preserve spans `FromForm` field types.
* All dynamic parameters in a query string must typecheck as `FromForm`.
* `FromFormValue` derive removed; `FromFormField` added.
* The `form` `FromForm` and `FromFormField` field attribute is now named
`field`. `#[form(field = ..)]` is now `#[field(name = ..)]`.
Contrib
* `Json` implements `FromForm`.
* `MsgPack` implements `FromForm`.
* The `json!` macro is exported as `rocket_contrib::json::json!`.
* Added clarifying docs to `StaticFiles`.
Examples
* `form_validation` and `form_kitchen_sink` removed in favor of `forms`.
* The `hello_world` example uses unicode in paths.
* The `json` example only allocates as necessary.
Internal
* Codegen uses new `exports` module with the following conventions:
- Locals starts with `__` and are lowercased.
- Rocket modules start with `_` and are lowercased.
- `std` types start with `_` and are titlecased.
- Rocket types are titlecased.
* A `header` module was added to `http`, contains header types.
* `SAFETY` is used as doc-string keyword for `unsafe` related comments.
* The `Uri` parser no longer recognizes Rocket route URIs.
2020-10-30 03:50:06 +00:00
|
|
|
impl<T, E> PollExt<T, E> for Poll<Option<Result<T, E>>> {
|
|
|
|
/// Changes the error value of this `Poll` with the closure provided.
|
|
|
|
fn map_err_ext<U, F>(self, f: F) -> Poll<Option<Result<T, U>>>
|
|
|
|
where F: FnOnce(E) -> U
|
|
|
|
{
|
|
|
|
match self {
|
|
|
|
Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(t))),
|
|
|
|
Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(f(e)))),
|
|
|
|
Poll::Ready(None) => Poll::Ready(None),
|
|
|
|
Poll::Pending => Poll::Pending,
|
|
|
|
}
|
|
|
|
}
|
2019-09-22 22:48:08 +00:00
|
|
|
}
|
|
|
|
|
UTF-8 routes. Forms revamp. Temp files. Capped.
So. Many. Changes.
This is an insane commit: simultaneously one of the best (because of all
the wonderful improvements!) and one of the worst (because it is just
massive) in the project's history.
Routing:
* All UTF-8 characters are accepted everywhere in route paths. (#998)
* `path` is now `uri` in `route` attribute: `#[route(GET, path = "..")]`
becomes `#[route(GET, uri = "..")]`.
Forms Revamp
* All form related types now reside in a new `form` module.
* Multipart forms are supported. (resolves #106)
* Collections are supported in forms and queries. (resolves #205)
* Nested structures in forms and queries are supported. (resolves #313)
* Form fields can be ad-hoc validated with `#[field(validate = expr)]`.
* `FromFormValue` is now `FromFormField`, blanket implements `FromForm`.
* Form field values are always percent-decoded apriori.
Temporary Files
* A new `TempFile` data and form guard allows streaming data directly to a
file which can then be persisted.
* A new `temp_dir` config parameter specifies where to store `TempFile`.
* The limits `file` and `file/$ext`, where `$ext` is the file extension,
determines the data limit for a `TempFile`.
Capped
* A new `Capped` type is used to indicate when data has been truncated due to
incoming data limits. It allows checking whether data is complete or
truncated.
* `DataStream` methods return `Capped` types.
* `DataStream` API has been revamped to account for `Capped` types.
* Several `Capped<T>` types implement `FromData`, `FromForm`.
* HTTP 413 (Payload Too Large) errors are now returned when data limits are
exceeded. (resolves #972)
Hierarchical Limits
* Data limits are now hierarchical, delimited with `/`. A limit of `a/b/c`
falls back to `a/b` then `a`.
Core
* `&RawStr` no longer implements `FromParam`.
* `&str` implements `FromParam`, `FromData`, `FromForm`.
* `FromTransformedData` was removed.
* `FromData` gained a lifetime for use with request-local data.
* The default error HTML is more compact.
* `&Config` is a request guard.
* The `DataStream` interface was entirely revamped.
* `State` is only exported via `rocket::State`.
* A `request::local_cache!()` macro was added for storing values in
request-local cache without consideration for type uniqueness by using a
locally generated anonymous type.
* `Request::get_param()` is now `Request::param()`.
* `Request::get_segments()` is now `Request::segments()`, takes a range.
* `Request::get_query_value()` is now `Request::query_value()`, can parse any
`FromForm` including sequences.
* `std::io::Error` implements `Responder` like `Debug<std::io::Error>`.
* `(Status, R)` where `R: Responder` implements `Responder` by overriding the
`Status` of `R`.
* The name of a route is printed first during route matching.
* `FlashMessage` now only has one lifetime generic.
HTTP
* `RawStr` implements `serde::{Serialize, Deserialize}`.
* `RawStr` implements _many_ more methods, in particular, those related to the
`Pattern` API.
* `RawStr::from_str()` is now `RawStr::new()`.
* `RawStr::url_decode()` and `RawStr::url_decode_lossy()` only allocate as
necessary, return `Cow`.
* `Status` implements `Default` with `Status::Ok`.
* `Status` implements `PartialEq`, `Eq`, `Hash`, `PartialOrd`, `Ord`.
* Authority and origin part of `Absolute` can be modified with new
`Absolute::{with,set}_authority()`, `Absolute::{with,set}_origin()` methods.
* `Origin::segments()` was removed in favor of methods split into query and
path parts and into raw and decoded versions.
* The `Segments` iterator is smarter, returns decoded `&str` items.
* `Segments::into_path_buf()` is now `Segments::to_path_buf()`.
* A new `QuerySegments` is the analogous query segment iterator.
* Once set, `expires` on private cookies is not overwritten. (resolves #1506)
* `Origin::path()` and `Origin::query()` return `&RawStr`, not `&str`.
Codegen
* Preserve more spans in `uri!` macro.
* Preserve spans `FromForm` field types.
* All dynamic parameters in a query string must typecheck as `FromForm`.
* `FromFormValue` derive removed; `FromFormField` added.
* The `form` `FromForm` and `FromFormField` field attribute is now named
`field`. `#[form(field = ..)]` is now `#[field(name = ..)]`.
Contrib
* `Json` implements `FromForm`.
* `MsgPack` implements `FromForm`.
* The `json!` macro is exported as `rocket_contrib::json::json!`.
* Added clarifying docs to `StaticFiles`.
Examples
* `form_validation` and `form_kitchen_sink` removed in favor of `forms`.
* The `hello_world` example uses unicode in paths.
* The `json` example only allocates as necessary.
Internal
* Codegen uses new `exports` module with the following conventions:
- Locals starts with `__` and are lowercased.
- Rocket modules start with `_` and are lowercased.
- `std` types start with `_` and are titlecased.
- Rocket types are titlecased.
* A `header` module was added to `http`, contains header types.
* `SAFETY` is used as doc-string keyword for `unsafe` related comments.
* The `Uri` parser no longer recognizes Rocket route URIs.
2020-10-30 03:50:06 +00:00
|
|
|
pin_project! {
|
|
|
|
/// Stream for the [`chain`](super::AsyncReadExt::chain) method.
|
|
|
|
#[must_use = "streams do nothing unless polled"]
|
|
|
|
pub struct Chain<T, U> {
|
|
|
|
#[pin]
|
|
|
|
first: T,
|
|
|
|
#[pin]
|
|
|
|
second: U,
|
|
|
|
done_first: bool,
|
2019-12-15 19:10:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
UTF-8 routes. Forms revamp. Temp files. Capped.
So. Many. Changes.
This is an insane commit: simultaneously one of the best (because of all
the wonderful improvements!) and one of the worst (because it is just
massive) in the project's history.
Routing:
* All UTF-8 characters are accepted everywhere in route paths. (#998)
* `path` is now `uri` in `route` attribute: `#[route(GET, path = "..")]`
becomes `#[route(GET, uri = "..")]`.
Forms Revamp
* All form related types now reside in a new `form` module.
* Multipart forms are supported. (resolves #106)
* Collections are supported in forms and queries. (resolves #205)
* Nested structures in forms and queries are supported. (resolves #313)
* Form fields can be ad-hoc validated with `#[field(validate = expr)]`.
* `FromFormValue` is now `FromFormField`, blanket implements `FromForm`.
* Form field values are always percent-decoded apriori.
Temporary Files
* A new `TempFile` data and form guard allows streaming data directly to a
file which can then be persisted.
* A new `temp_dir` config parameter specifies where to store `TempFile`.
* The limits `file` and `file/$ext`, where `$ext` is the file extension,
determines the data limit for a `TempFile`.
Capped
* A new `Capped` type is used to indicate when data has been truncated due to
incoming data limits. It allows checking whether data is complete or
truncated.
* `DataStream` methods return `Capped` types.
* `DataStream` API has been revamped to account for `Capped` types.
* Several `Capped<T>` types implement `FromData`, `FromForm`.
* HTTP 413 (Payload Too Large) errors are now returned when data limits are
exceeded. (resolves #972)
Hierarchical Limits
* Data limits are now hierarchical, delimited with `/`. A limit of `a/b/c`
falls back to `a/b` then `a`.
Core
* `&RawStr` no longer implements `FromParam`.
* `&str` implements `FromParam`, `FromData`, `FromForm`.
* `FromTransformedData` was removed.
* `FromData` gained a lifetime for use with request-local data.
* The default error HTML is more compact.
* `&Config` is a request guard.
* The `DataStream` interface was entirely revamped.
* `State` is only exported via `rocket::State`.
* A `request::local_cache!()` macro was added for storing values in
request-local cache without consideration for type uniqueness by using a
locally generated anonymous type.
* `Request::get_param()` is now `Request::param()`.
* `Request::get_segments()` is now `Request::segments()`, takes a range.
* `Request::get_query_value()` is now `Request::query_value()`, can parse any
`FromForm` including sequences.
* `std::io::Error` implements `Responder` like `Debug<std::io::Error>`.
* `(Status, R)` where `R: Responder` implements `Responder` by overriding the
`Status` of `R`.
* The name of a route is printed first during route matching.
* `FlashMessage` now only has one lifetime generic.
HTTP
* `RawStr` implements `serde::{Serialize, Deserialize}`.
* `RawStr` implements _many_ more methods, in particular, those related to the
`Pattern` API.
* `RawStr::from_str()` is now `RawStr::new()`.
* `RawStr::url_decode()` and `RawStr::url_decode_lossy()` only allocate as
necessary, return `Cow`.
* `Status` implements `Default` with `Status::Ok`.
* `Status` implements `PartialEq`, `Eq`, `Hash`, `PartialOrd`, `Ord`.
* Authority and origin part of `Absolute` can be modified with new
`Absolute::{with,set}_authority()`, `Absolute::{with,set}_origin()` methods.
* `Origin::segments()` was removed in favor of methods split into query and
path parts and into raw and decoded versions.
* The `Segments` iterator is smarter, returns decoded `&str` items.
* `Segments::into_path_buf()` is now `Segments::to_path_buf()`.
* A new `QuerySegments` is the analogous query segment iterator.
* Once set, `expires` on private cookies is not overwritten. (resolves #1506)
* `Origin::path()` and `Origin::query()` return `&RawStr`, not `&str`.
Codegen
* Preserve more spans in `uri!` macro.
* Preserve spans `FromForm` field types.
* All dynamic parameters in a query string must typecheck as `FromForm`.
* `FromFormValue` derive removed; `FromFormField` added.
* The `form` `FromForm` and `FromFormField` field attribute is now named
`field`. `#[form(field = ..)]` is now `#[field(name = ..)]`.
Contrib
* `Json` implements `FromForm`.
* `MsgPack` implements `FromForm`.
* The `json!` macro is exported as `rocket_contrib::json::json!`.
* Added clarifying docs to `StaticFiles`.
Examples
* `form_validation` and `form_kitchen_sink` removed in favor of `forms`.
* The `hello_world` example uses unicode in paths.
* The `json` example only allocates as necessary.
Internal
* Codegen uses new `exports` module with the following conventions:
- Locals starts with `__` and are lowercased.
- Rocket modules start with `_` and are lowercased.
- `std` types start with `_` and are titlecased.
- Rocket types are titlecased.
* A `header` module was added to `http`, contains header types.
* `SAFETY` is used as doc-string keyword for `unsafe` related comments.
* The `Uri` parser no longer recognizes Rocket route URIs.
2020-10-30 03:50:06 +00:00
|
|
|
impl<T: AsyncRead, U: AsyncRead> Chain<T, U> {
|
|
|
|
pub(crate) fn new(first: T, second: U) -> Self {
|
|
|
|
Self { first, second, done_first: false }
|
2019-09-22 22:48:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
UTF-8 routes. Forms revamp. Temp files. Capped.
So. Many. Changes.
This is an insane commit: simultaneously one of the best (because of all
the wonderful improvements!) and one of the worst (because it is just
massive) in the project's history.
Routing:
* All UTF-8 characters are accepted everywhere in route paths. (#998)
* `path` is now `uri` in `route` attribute: `#[route(GET, path = "..")]`
becomes `#[route(GET, uri = "..")]`.
Forms Revamp
* All form related types now reside in a new `form` module.
* Multipart forms are supported. (resolves #106)
* Collections are supported in forms and queries. (resolves #205)
* Nested structures in forms and queries are supported. (resolves #313)
* Form fields can be ad-hoc validated with `#[field(validate = expr)]`.
* `FromFormValue` is now `FromFormField`, blanket implements `FromForm`.
* Form field values are always percent-decoded apriori.
Temporary Files
* A new `TempFile` data and form guard allows streaming data directly to a
file which can then be persisted.
* A new `temp_dir` config parameter specifies where to store `TempFile`.
* The limits `file` and `file/$ext`, where `$ext` is the file extension,
determines the data limit for a `TempFile`.
Capped
* A new `Capped` type is used to indicate when data has been truncated due to
incoming data limits. It allows checking whether data is complete or
truncated.
* `DataStream` methods return `Capped` types.
* `DataStream` API has been revamped to account for `Capped` types.
* Several `Capped<T>` types implement `FromData`, `FromForm`.
* HTTP 413 (Payload Too Large) errors are now returned when data limits are
exceeded. (resolves #972)
Hierarchical Limits
* Data limits are now hierarchical, delimited with `/`. A limit of `a/b/c`
falls back to `a/b` then `a`.
Core
* `&RawStr` no longer implements `FromParam`.
* `&str` implements `FromParam`, `FromData`, `FromForm`.
* `FromTransformedData` was removed.
* `FromData` gained a lifetime for use with request-local data.
* The default error HTML is more compact.
* `&Config` is a request guard.
* The `DataStream` interface was entirely revamped.
* `State` is only exported via `rocket::State`.
* A `request::local_cache!()` macro was added for storing values in
request-local cache without consideration for type uniqueness by using a
locally generated anonymous type.
* `Request::get_param()` is now `Request::param()`.
* `Request::get_segments()` is now `Request::segments()`, takes a range.
* `Request::get_query_value()` is now `Request::query_value()`, can parse any
`FromForm` including sequences.
* `std::io::Error` implements `Responder` like `Debug<std::io::Error>`.
* `(Status, R)` where `R: Responder` implements `Responder` by overriding the
`Status` of `R`.
* The name of a route is printed first during route matching.
* `FlashMessage` now only has one lifetime generic.
HTTP
* `RawStr` implements `serde::{Serialize, Deserialize}`.
* `RawStr` implements _many_ more methods, in particular, those related to the
`Pattern` API.
* `RawStr::from_str()` is now `RawStr::new()`.
* `RawStr::url_decode()` and `RawStr::url_decode_lossy()` only allocate as
necessary, return `Cow`.
* `Status` implements `Default` with `Status::Ok`.
* `Status` implements `PartialEq`, `Eq`, `Hash`, `PartialOrd`, `Ord`.
* Authority and origin part of `Absolute` can be modified with new
`Absolute::{with,set}_authority()`, `Absolute::{with,set}_origin()` methods.
* `Origin::segments()` was removed in favor of methods split into query and
path parts and into raw and decoded versions.
* The `Segments` iterator is smarter, returns decoded `&str` items.
* `Segments::into_path_buf()` is now `Segments::to_path_buf()`.
* A new `QuerySegments` is the analogous query segment iterator.
* Once set, `expires` on private cookies is not overwritten. (resolves #1506)
* `Origin::path()` and `Origin::query()` return `&RawStr`, not `&str`.
Codegen
* Preserve more spans in `uri!` macro.
* Preserve spans `FromForm` field types.
* All dynamic parameters in a query string must typecheck as `FromForm`.
* `FromFormValue` derive removed; `FromFormField` added.
* The `form` `FromForm` and `FromFormField` field attribute is now named
`field`. `#[form(field = ..)]` is now `#[field(name = ..)]`.
Contrib
* `Json` implements `FromForm`.
* `MsgPack` implements `FromForm`.
* The `json!` macro is exported as `rocket_contrib::json::json!`.
* Added clarifying docs to `StaticFiles`.
Examples
* `form_validation` and `form_kitchen_sink` removed in favor of `forms`.
* The `hello_world` example uses unicode in paths.
* The `json` example only allocates as necessary.
Internal
* Codegen uses new `exports` module with the following conventions:
- Locals starts with `__` and are lowercased.
- Rocket modules start with `_` and are lowercased.
- `std` types start with `_` and are titlecased.
- Rocket types are titlecased.
* A `header` module was added to `http`, contains header types.
* `SAFETY` is used as doc-string keyword for `unsafe` related comments.
* The `Uri` parser no longer recognizes Rocket route URIs.
2020-10-30 03:50:06 +00:00
|
|
|
impl<T: AsyncRead, U: AsyncRead> Chain<T, U> {
|
|
|
|
/// Gets references to the underlying readers in this `Chain`.
|
|
|
|
pub fn get_ref(&self) -> (&T, &U) {
|
|
|
|
(&self.first, &self.second)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: AsyncRead, U: AsyncRead> AsyncRead for Chain<T, U> {
|
2020-07-30 11:17:38 +00:00
|
|
|
fn poll_read(
|
UTF-8 routes. Forms revamp. Temp files. Capped.
So. Many. Changes.
This is an insane commit: simultaneously one of the best (because of all
the wonderful improvements!) and one of the worst (because it is just
massive) in the project's history.
Routing:
* All UTF-8 characters are accepted everywhere in route paths. (#998)
* `path` is now `uri` in `route` attribute: `#[route(GET, path = "..")]`
becomes `#[route(GET, uri = "..")]`.
Forms Revamp
* All form related types now reside in a new `form` module.
* Multipart forms are supported. (resolves #106)
* Collections are supported in forms and queries. (resolves #205)
* Nested structures in forms and queries are supported. (resolves #313)
* Form fields can be ad-hoc validated with `#[field(validate = expr)]`.
* `FromFormValue` is now `FromFormField`, blanket implements `FromForm`.
* Form field values are always percent-decoded apriori.
Temporary Files
* A new `TempFile` data and form guard allows streaming data directly to a
file which can then be persisted.
* A new `temp_dir` config parameter specifies where to store `TempFile`.
* The limits `file` and `file/$ext`, where `$ext` is the file extension,
determines the data limit for a `TempFile`.
Capped
* A new `Capped` type is used to indicate when data has been truncated due to
incoming data limits. It allows checking whether data is complete or
truncated.
* `DataStream` methods return `Capped` types.
* `DataStream` API has been revamped to account for `Capped` types.
* Several `Capped<T>` types implement `FromData`, `FromForm`.
* HTTP 413 (Payload Too Large) errors are now returned when data limits are
exceeded. (resolves #972)
Hierarchical Limits
* Data limits are now hierarchical, delimited with `/`. A limit of `a/b/c`
falls back to `a/b` then `a`.
Core
* `&RawStr` no longer implements `FromParam`.
* `&str` implements `FromParam`, `FromData`, `FromForm`.
* `FromTransformedData` was removed.
* `FromData` gained a lifetime for use with request-local data.
* The default error HTML is more compact.
* `&Config` is a request guard.
* The `DataStream` interface was entirely revamped.
* `State` is only exported via `rocket::State`.
* A `request::local_cache!()` macro was added for storing values in
request-local cache without consideration for type uniqueness by using a
locally generated anonymous type.
* `Request::get_param()` is now `Request::param()`.
* `Request::get_segments()` is now `Request::segments()`, takes a range.
* `Request::get_query_value()` is now `Request::query_value()`, can parse any
`FromForm` including sequences.
* `std::io::Error` implements `Responder` like `Debug<std::io::Error>`.
* `(Status, R)` where `R: Responder` implements `Responder` by overriding the
`Status` of `R`.
* The name of a route is printed first during route matching.
* `FlashMessage` now only has one lifetime generic.
HTTP
* `RawStr` implements `serde::{Serialize, Deserialize}`.
* `RawStr` implements _many_ more methods, in particular, those related to the
`Pattern` API.
* `RawStr::from_str()` is now `RawStr::new()`.
* `RawStr::url_decode()` and `RawStr::url_decode_lossy()` only allocate as
necessary, return `Cow`.
* `Status` implements `Default` with `Status::Ok`.
* `Status` implements `PartialEq`, `Eq`, `Hash`, `PartialOrd`, `Ord`.
* Authority and origin part of `Absolute` can be modified with new
`Absolute::{with,set}_authority()`, `Absolute::{with,set}_origin()` methods.
* `Origin::segments()` was removed in favor of methods split into query and
path parts and into raw and decoded versions.
* The `Segments` iterator is smarter, returns decoded `&str` items.
* `Segments::into_path_buf()` is now `Segments::to_path_buf()`.
* A new `QuerySegments` is the analogous query segment iterator.
* Once set, `expires` on private cookies is not overwritten. (resolves #1506)
* `Origin::path()` and `Origin::query()` return `&RawStr`, not `&str`.
Codegen
* Preserve more spans in `uri!` macro.
* Preserve spans `FromForm` field types.
* All dynamic parameters in a query string must typecheck as `FromForm`.
* `FromFormValue` derive removed; `FromFormField` added.
* The `form` `FromForm` and `FromFormField` field attribute is now named
`field`. `#[form(field = ..)]` is now `#[field(name = ..)]`.
Contrib
* `Json` implements `FromForm`.
* `MsgPack` implements `FromForm`.
* The `json!` macro is exported as `rocket_contrib::json::json!`.
* Added clarifying docs to `StaticFiles`.
Examples
* `form_validation` and `form_kitchen_sink` removed in favor of `forms`.
* The `hello_world` example uses unicode in paths.
* The `json` example only allocates as necessary.
Internal
* Codegen uses new `exports` module with the following conventions:
- Locals starts with `__` and are lowercased.
- Rocket modules start with `_` and are lowercased.
- `std` types start with `_` and are titlecased.
- Rocket types are titlecased.
* A `header` module was added to `http`, contains header types.
* `SAFETY` is used as doc-string keyword for `unsafe` related comments.
* The `Uri` parser no longer recognizes Rocket route URIs.
2020-10-30 03:50:06 +00:00
|
|
|
self: Pin<&mut Self>,
|
2020-07-30 11:17:38 +00:00
|
|
|
cx: &mut Context<'_>,
|
2020-12-24 01:02:40 +00:00
|
|
|
buf: &mut ReadBuf<'_>,
|
|
|
|
) -> Poll<io::Result<()>> {
|
UTF-8 routes. Forms revamp. Temp files. Capped.
So. Many. Changes.
This is an insane commit: simultaneously one of the best (because of all
the wonderful improvements!) and one of the worst (because it is just
massive) in the project's history.
Routing:
* All UTF-8 characters are accepted everywhere in route paths. (#998)
* `path` is now `uri` in `route` attribute: `#[route(GET, path = "..")]`
becomes `#[route(GET, uri = "..")]`.
Forms Revamp
* All form related types now reside in a new `form` module.
* Multipart forms are supported. (resolves #106)
* Collections are supported in forms and queries. (resolves #205)
* Nested structures in forms and queries are supported. (resolves #313)
* Form fields can be ad-hoc validated with `#[field(validate = expr)]`.
* `FromFormValue` is now `FromFormField`, blanket implements `FromForm`.
* Form field values are always percent-decoded apriori.
Temporary Files
* A new `TempFile` data and form guard allows streaming data directly to a
file which can then be persisted.
* A new `temp_dir` config parameter specifies where to store `TempFile`.
* The limits `file` and `file/$ext`, where `$ext` is the file extension,
determines the data limit for a `TempFile`.
Capped
* A new `Capped` type is used to indicate when data has been truncated due to
incoming data limits. It allows checking whether data is complete or
truncated.
* `DataStream` methods return `Capped` types.
* `DataStream` API has been revamped to account for `Capped` types.
* Several `Capped<T>` types implement `FromData`, `FromForm`.
* HTTP 413 (Payload Too Large) errors are now returned when data limits are
exceeded. (resolves #972)
Hierarchical Limits
* Data limits are now hierarchical, delimited with `/`. A limit of `a/b/c`
falls back to `a/b` then `a`.
Core
* `&RawStr` no longer implements `FromParam`.
* `&str` implements `FromParam`, `FromData`, `FromForm`.
* `FromTransformedData` was removed.
* `FromData` gained a lifetime for use with request-local data.
* The default error HTML is more compact.
* `&Config` is a request guard.
* The `DataStream` interface was entirely revamped.
* `State` is only exported via `rocket::State`.
* A `request::local_cache!()` macro was added for storing values in
request-local cache without consideration for type uniqueness by using a
locally generated anonymous type.
* `Request::get_param()` is now `Request::param()`.
* `Request::get_segments()` is now `Request::segments()`, takes a range.
* `Request::get_query_value()` is now `Request::query_value()`, can parse any
`FromForm` including sequences.
* `std::io::Error` implements `Responder` like `Debug<std::io::Error>`.
* `(Status, R)` where `R: Responder` implements `Responder` by overriding the
`Status` of `R`.
* The name of a route is printed first during route matching.
* `FlashMessage` now only has one lifetime generic.
HTTP
* `RawStr` implements `serde::{Serialize, Deserialize}`.
* `RawStr` implements _many_ more methods, in particular, those related to the
`Pattern` API.
* `RawStr::from_str()` is now `RawStr::new()`.
* `RawStr::url_decode()` and `RawStr::url_decode_lossy()` only allocate as
necessary, return `Cow`.
* `Status` implements `Default` with `Status::Ok`.
* `Status` implements `PartialEq`, `Eq`, `Hash`, `PartialOrd`, `Ord`.
* Authority and origin part of `Absolute` can be modified with new
`Absolute::{with,set}_authority()`, `Absolute::{with,set}_origin()` methods.
* `Origin::segments()` was removed in favor of methods split into query and
path parts and into raw and decoded versions.
* The `Segments` iterator is smarter, returns decoded `&str` items.
* `Segments::into_path_buf()` is now `Segments::to_path_buf()`.
* A new `QuerySegments` is the analogous query segment iterator.
* Once set, `expires` on private cookies is not overwritten. (resolves #1506)
* `Origin::path()` and `Origin::query()` return `&RawStr`, not `&str`.
Codegen
* Preserve more spans in `uri!` macro.
* Preserve spans `FromForm` field types.
* All dynamic parameters in a query string must typecheck as `FromForm`.
* `FromFormValue` derive removed; `FromFormField` added.
* The `form` `FromForm` and `FromFormField` field attribute is now named
`field`. `#[form(field = ..)]` is now `#[field(name = ..)]`.
Contrib
* `Json` implements `FromForm`.
* `MsgPack` implements `FromForm`.
* The `json!` macro is exported as `rocket_contrib::json::json!`.
* Added clarifying docs to `StaticFiles`.
Examples
* `form_validation` and `form_kitchen_sink` removed in favor of `forms`.
* The `hello_world` example uses unicode in paths.
* The `json` example only allocates as necessary.
Internal
* Codegen uses new `exports` module with the following conventions:
- Locals starts with `__` and are lowercased.
- Rocket modules start with `_` and are lowercased.
- `std` types start with `_` and are titlecased.
- Rocket types are titlecased.
* A `header` module was added to `http`, contains header types.
* `SAFETY` is used as doc-string keyword for `unsafe` related comments.
* The `Uri` parser no longer recognizes Rocket route URIs.
2020-10-30 03:50:06 +00:00
|
|
|
let me = self.project();
|
|
|
|
|
|
|
|
if !*me.done_first {
|
|
|
|
let init_rem = buf.remaining();
|
2021-04-28 09:01:35 +00:00
|
|
|
futures::ready!(me.first.poll_read(cx, buf))?;
|
UTF-8 routes. Forms revamp. Temp files. Capped.
So. Many. Changes.
This is an insane commit: simultaneously one of the best (because of all
the wonderful improvements!) and one of the worst (because it is just
massive) in the project's history.
Routing:
* All UTF-8 characters are accepted everywhere in route paths. (#998)
* `path` is now `uri` in `route` attribute: `#[route(GET, path = "..")]`
becomes `#[route(GET, uri = "..")]`.
Forms Revamp
* All form related types now reside in a new `form` module.
* Multipart forms are supported. (resolves #106)
* Collections are supported in forms and queries. (resolves #205)
* Nested structures in forms and queries are supported. (resolves #313)
* Form fields can be ad-hoc validated with `#[field(validate = expr)]`.
* `FromFormValue` is now `FromFormField`, blanket implements `FromForm`.
* Form field values are always percent-decoded apriori.
Temporary Files
* A new `TempFile` data and form guard allows streaming data directly to a
file which can then be persisted.
* A new `temp_dir` config parameter specifies where to store `TempFile`.
* The limits `file` and `file/$ext`, where `$ext` is the file extension,
determines the data limit for a `TempFile`.
Capped
* A new `Capped` type is used to indicate when data has been truncated due to
incoming data limits. It allows checking whether data is complete or
truncated.
* `DataStream` methods return `Capped` types.
* `DataStream` API has been revamped to account for `Capped` types.
* Several `Capped<T>` types implement `FromData`, `FromForm`.
* HTTP 413 (Payload Too Large) errors are now returned when data limits are
exceeded. (resolves #972)
Hierarchical Limits
* Data limits are now hierarchical, delimited with `/`. A limit of `a/b/c`
falls back to `a/b` then `a`.
Core
* `&RawStr` no longer implements `FromParam`.
* `&str` implements `FromParam`, `FromData`, `FromForm`.
* `FromTransformedData` was removed.
* `FromData` gained a lifetime for use with request-local data.
* The default error HTML is more compact.
* `&Config` is a request guard.
* The `DataStream` interface was entirely revamped.
* `State` is only exported via `rocket::State`.
* A `request::local_cache!()` macro was added for storing values in
request-local cache without consideration for type uniqueness by using a
locally generated anonymous type.
* `Request::get_param()` is now `Request::param()`.
* `Request::get_segments()` is now `Request::segments()`, takes a range.
* `Request::get_query_value()` is now `Request::query_value()`, can parse any
`FromForm` including sequences.
* `std::io::Error` implements `Responder` like `Debug<std::io::Error>`.
* `(Status, R)` where `R: Responder` implements `Responder` by overriding the
`Status` of `R`.
* The name of a route is printed first during route matching.
* `FlashMessage` now only has one lifetime generic.
HTTP
* `RawStr` implements `serde::{Serialize, Deserialize}`.
* `RawStr` implements _many_ more methods, in particular, those related to the
`Pattern` API.
* `RawStr::from_str()` is now `RawStr::new()`.
* `RawStr::url_decode()` and `RawStr::url_decode_lossy()` only allocate as
necessary, return `Cow`.
* `Status` implements `Default` with `Status::Ok`.
* `Status` implements `PartialEq`, `Eq`, `Hash`, `PartialOrd`, `Ord`.
* Authority and origin part of `Absolute` can be modified with new
`Absolute::{with,set}_authority()`, `Absolute::{with,set}_origin()` methods.
* `Origin::segments()` was removed in favor of methods split into query and
path parts and into raw and decoded versions.
* The `Segments` iterator is smarter, returns decoded `&str` items.
* `Segments::into_path_buf()` is now `Segments::to_path_buf()`.
* A new `QuerySegments` is the analogous query segment iterator.
* Once set, `expires` on private cookies is not overwritten. (resolves #1506)
* `Origin::path()` and `Origin::query()` return `&RawStr`, not `&str`.
Codegen
* Preserve more spans in `uri!` macro.
* Preserve spans `FromForm` field types.
* All dynamic parameters in a query string must typecheck as `FromForm`.
* `FromFormValue` derive removed; `FromFormField` added.
* The `form` `FromForm` and `FromFormField` field attribute is now named
`field`. `#[form(field = ..)]` is now `#[field(name = ..)]`.
Contrib
* `Json` implements `FromForm`.
* `MsgPack` implements `FromForm`.
* The `json!` macro is exported as `rocket_contrib::json::json!`.
* Added clarifying docs to `StaticFiles`.
Examples
* `form_validation` and `form_kitchen_sink` removed in favor of `forms`.
* The `hello_world` example uses unicode in paths.
* The `json` example only allocates as necessary.
Internal
* Codegen uses new `exports` module with the following conventions:
- Locals starts with `__` and are lowercased.
- Rocket modules start with `_` and are lowercased.
- `std` types start with `_` and are titlecased.
- Rocket types are titlecased.
* A `header` module was added to `http`, contains header types.
* `SAFETY` is used as doc-string keyword for `unsafe` related comments.
* The `Uri` parser no longer recognizes Rocket route URIs.
2020-10-30 03:50:06 +00:00
|
|
|
if buf.remaining() == init_rem {
|
|
|
|
*me.done_first = true;
|
|
|
|
} else {
|
|
|
|
return Poll::Ready(Ok(()));
|
2019-09-22 22:48:08 +00:00
|
|
|
}
|
|
|
|
}
|
UTF-8 routes. Forms revamp. Temp files. Capped.
So. Many. Changes.
This is an insane commit: simultaneously one of the best (because of all
the wonderful improvements!) and one of the worst (because it is just
massive) in the project's history.
Routing:
* All UTF-8 characters are accepted everywhere in route paths. (#998)
* `path` is now `uri` in `route` attribute: `#[route(GET, path = "..")]`
becomes `#[route(GET, uri = "..")]`.
Forms Revamp
* All form related types now reside in a new `form` module.
* Multipart forms are supported. (resolves #106)
* Collections are supported in forms and queries. (resolves #205)
* Nested structures in forms and queries are supported. (resolves #313)
* Form fields can be ad-hoc validated with `#[field(validate = expr)]`.
* `FromFormValue` is now `FromFormField`, blanket implements `FromForm`.
* Form field values are always percent-decoded apriori.
Temporary Files
* A new `TempFile` data and form guard allows streaming data directly to a
file which can then be persisted.
* A new `temp_dir` config parameter specifies where to store `TempFile`.
* The limits `file` and `file/$ext`, where `$ext` is the file extension,
determines the data limit for a `TempFile`.
Capped
* A new `Capped` type is used to indicate when data has been truncated due to
incoming data limits. It allows checking whether data is complete or
truncated.
* `DataStream` methods return `Capped` types.
* `DataStream` API has been revamped to account for `Capped` types.
* Several `Capped<T>` types implement `FromData`, `FromForm`.
* HTTP 413 (Payload Too Large) errors are now returned when data limits are
exceeded. (resolves #972)
Hierarchical Limits
* Data limits are now hierarchical, delimited with `/`. A limit of `a/b/c`
falls back to `a/b` then `a`.
Core
* `&RawStr` no longer implements `FromParam`.
* `&str` implements `FromParam`, `FromData`, `FromForm`.
* `FromTransformedData` was removed.
* `FromData` gained a lifetime for use with request-local data.
* The default error HTML is more compact.
* `&Config` is a request guard.
* The `DataStream` interface was entirely revamped.
* `State` is only exported via `rocket::State`.
* A `request::local_cache!()` macro was added for storing values in
request-local cache without consideration for type uniqueness by using a
locally generated anonymous type.
* `Request::get_param()` is now `Request::param()`.
* `Request::get_segments()` is now `Request::segments()`, takes a range.
* `Request::get_query_value()` is now `Request::query_value()`, can parse any
`FromForm` including sequences.
* `std::io::Error` implements `Responder` like `Debug<std::io::Error>`.
* `(Status, R)` where `R: Responder` implements `Responder` by overriding the
`Status` of `R`.
* The name of a route is printed first during route matching.
* `FlashMessage` now only has one lifetime generic.
HTTP
* `RawStr` implements `serde::{Serialize, Deserialize}`.
* `RawStr` implements _many_ more methods, in particular, those related to the
`Pattern` API.
* `RawStr::from_str()` is now `RawStr::new()`.
* `RawStr::url_decode()` and `RawStr::url_decode_lossy()` only allocate as
necessary, return `Cow`.
* `Status` implements `Default` with `Status::Ok`.
* `Status` implements `PartialEq`, `Eq`, `Hash`, `PartialOrd`, `Ord`.
* Authority and origin part of `Absolute` can be modified with new
`Absolute::{with,set}_authority()`, `Absolute::{with,set}_origin()` methods.
* `Origin::segments()` was removed in favor of methods split into query and
path parts and into raw and decoded versions.
* The `Segments` iterator is smarter, returns decoded `&str` items.
* `Segments::into_path_buf()` is now `Segments::to_path_buf()`.
* A new `QuerySegments` is the analogous query segment iterator.
* Once set, `expires` on private cookies is not overwritten. (resolves #1506)
* `Origin::path()` and `Origin::query()` return `&RawStr`, not `&str`.
Codegen
* Preserve more spans in `uri!` macro.
* Preserve spans `FromForm` field types.
* All dynamic parameters in a query string must typecheck as `FromForm`.
* `FromFormValue` derive removed; `FromFormField` added.
* The `form` `FromForm` and `FromFormField` field attribute is now named
`field`. `#[form(field = ..)]` is now `#[field(name = ..)]`.
Contrib
* `Json` implements `FromForm`.
* `MsgPack` implements `FromForm`.
* The `json!` macro is exported as `rocket_contrib::json::json!`.
* Added clarifying docs to `StaticFiles`.
Examples
* `form_validation` and `form_kitchen_sink` removed in favor of `forms`.
* The `hello_world` example uses unicode in paths.
* The `json` example only allocates as necessary.
Internal
* Codegen uses new `exports` module with the following conventions:
- Locals starts with `__` and are lowercased.
- Rocket modules start with `_` and are lowercased.
- `std` types start with `_` and are titlecased.
- Rocket types are titlecased.
* A `header` module was added to `http`, contains header types.
* `SAFETY` is used as doc-string keyword for `unsafe` related comments.
* The `Uri` parser no longer recognizes Rocket route URIs.
2020-10-30 03:50:06 +00:00
|
|
|
me.second.poll_read(cx, buf)
|
2019-09-22 22:48:08 +00:00
|
|
|
}
|
|
|
|
}
|
2021-04-28 09:01:35 +00:00
|
|
|
|
2021-04-30 02:19:07 +00:00
|
|
|
enum State {
|
|
|
|
/// I/O has not been cancelled. Proceed as normal.
|
|
|
|
Active,
|
|
|
|
/// I/O has been cancelled. See if we can finish before the timer expires.
|
|
|
|
Grace(Pin<Box<Sleep>>),
|
|
|
|
/// Grace period elapsed. Shutdown the connection, waiting for the timer
|
|
|
|
/// until we force close.
|
|
|
|
Mercy(Pin<Box<Sleep>>),
|
|
|
|
/// We failed to shutdown and are force-closing the connection.
|
|
|
|
Terminated,
|
2021-06-07 22:59:40 +00:00
|
|
|
/// We successfully shutdown the connection.
|
2021-04-30 02:19:07 +00:00
|
|
|
Inactive,
|
|
|
|
}
|
|
|
|
|
2021-04-28 09:01:35 +00:00
|
|
|
pin_project! {
|
|
|
|
/// I/O that can be cancelled when a future `F` resolves.
|
|
|
|
#[must_use = "futures do nothing unless polled"]
|
|
|
|
pub struct CancellableIo<F, I> {
|
|
|
|
#[pin]
|
|
|
|
io: I,
|
|
|
|
#[pin]
|
2021-06-01 18:46:17 +00:00
|
|
|
trigger: future::Fuse<F>,
|
2021-04-30 02:19:07 +00:00
|
|
|
state: State,
|
2021-04-28 09:01:35 +00:00
|
|
|
grace: Duration,
|
2021-04-30 02:19:07 +00:00
|
|
|
mercy: Duration,
|
2021-04-28 09:01:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-30 02:19:07 +00:00
|
|
|
impl<F: Future, I: AsyncWrite> CancellableIo<F, I> {
|
|
|
|
pub fn new(trigger: F, io: I, grace: Duration, mercy: Duration) -> Self {
|
2021-04-28 09:01:35 +00:00
|
|
|
CancellableIo {
|
2021-04-30 02:19:07 +00:00
|
|
|
io, grace, mercy,
|
2021-04-28 09:01:35 +00:00
|
|
|
trigger: trigger.fuse(),
|
2021-04-30 02:19:07 +00:00
|
|
|
state: State::Active
|
2021-04-28 09:01:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-30 02:19:07 +00:00
|
|
|
/// Returns `Ok(true)` if connection processing should continue.
|
|
|
|
fn poll_trigger_then<T>(
|
2021-04-28 09:01:35 +00:00
|
|
|
self: Pin<&mut Self>,
|
2021-04-30 02:19:07 +00:00
|
|
|
cx: &mut Context<'_>,
|
|
|
|
io: impl FnOnce(Pin<&mut I>, &mut Context<'_>) -> Poll<io::Result<T>>,
|
|
|
|
) -> Poll<io::Result<T>> {
|
|
|
|
let mut me = self.project();
|
|
|
|
|
|
|
|
// CORRECTNESS: _EVERY_ branch must reset `state`! If `state` is
|
|
|
|
// unchanged in a branch, that branch _must_ `break`! No `return`!
|
|
|
|
let mut state = std::mem::replace(me.state, State::Active);
|
|
|
|
let result = loop {
|
|
|
|
match state {
|
|
|
|
State::Active => {
|
|
|
|
if me.trigger.as_mut().poll(cx).is_ready() {
|
|
|
|
state = State::Grace(Box::pin(sleep(*me.grace)));
|
|
|
|
} else {
|
|
|
|
state = State::Active;
|
|
|
|
break io(me.io, cx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
State::Grace(mut sleep) => {
|
|
|
|
if sleep.as_mut().poll(cx).is_ready() {
|
|
|
|
if let Some(deadline) = sleep.deadline().checked_add(*me.mercy) {
|
|
|
|
sleep.as_mut().reset(deadline);
|
|
|
|
state = State::Mercy(sleep);
|
|
|
|
} else {
|
|
|
|
state = State::Terminated;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
state = State::Grace(sleep);
|
|
|
|
break io(me.io, cx);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
State::Mercy(mut sleep) => {
|
|
|
|
if sleep.as_mut().poll(cx).is_ready() {
|
|
|
|
state = State::Terminated;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
match me.io.as_mut().poll_shutdown(cx) {
|
|
|
|
Poll::Ready(Err(e)) => {
|
|
|
|
state = State::Terminated;
|
|
|
|
break Poll::Ready(Err(e));
|
|
|
|
}
|
|
|
|
Poll::Ready(Ok(())) => {
|
|
|
|
state = State::Inactive;
|
|
|
|
break Poll::Ready(Err(gone()));
|
|
|
|
}
|
|
|
|
Poll::Pending => {
|
|
|
|
state = State::Mercy(sleep);
|
|
|
|
break Poll::Pending;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
State::Terminated => {
|
|
|
|
// Just in case, as a last ditch effort. Ignore pending.
|
|
|
|
state = State::Terminated;
|
|
|
|
let _ = me.io.as_mut().poll_shutdown(cx);
|
|
|
|
break Poll::Ready(Err(time_out()));
|
|
|
|
},
|
|
|
|
State::Inactive => {
|
|
|
|
state = State::Inactive;
|
|
|
|
break Poll::Ready(Err(gone()));
|
|
|
|
}
|
2021-04-28 09:01:35 +00:00
|
|
|
}
|
2021-04-30 02:19:07 +00:00
|
|
|
};
|
2021-04-28 09:01:35 +00:00
|
|
|
|
2021-04-30 02:19:07 +00:00
|
|
|
*me.state = state;
|
|
|
|
result
|
2021-04-28 09:01:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-30 02:19:07 +00:00
|
|
|
fn time_out() -> io::Error {
|
|
|
|
io::Error::new(io::ErrorKind::TimedOut, "Shutdown grace timed out")
|
|
|
|
}
|
|
|
|
|
|
|
|
fn gone() -> io::Error {
|
|
|
|
io::Error::new(io::ErrorKind::BrokenPipe, "IO driver has terminated")
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<F: Future, I: AsyncRead + AsyncWrite> AsyncRead for CancellableIo<F, I> {
|
2021-04-28 09:01:35 +00:00
|
|
|
fn poll_read(
|
|
|
|
mut self: Pin<&mut Self>,
|
|
|
|
cx: &mut Context<'_>,
|
|
|
|
buf: &mut ReadBuf<'_>,
|
|
|
|
) -> Poll<io::Result<()>> {
|
2021-04-30 02:19:07 +00:00
|
|
|
self.as_mut().poll_trigger_then(cx, |io, cx| io.poll_read(cx, buf))
|
2021-04-28 09:01:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<F: Future, I: AsyncWrite> AsyncWrite for CancellableIo<F, I> {
|
|
|
|
fn poll_write(
|
|
|
|
mut self: Pin<&mut Self>,
|
|
|
|
cx: &mut Context<'_>,
|
|
|
|
buf: &[u8],
|
2021-04-30 02:19:07 +00:00
|
|
|
) -> Poll<io::Result<usize>> {
|
|
|
|
self.as_mut().poll_trigger_then(cx, |io, cx| io.poll_write(cx, buf))
|
2021-04-28 09:01:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn poll_flush(
|
|
|
|
mut self: Pin<&mut Self>,
|
|
|
|
cx: &mut Context<'_>
|
|
|
|
) -> Poll<io::Result<()>> {
|
2021-04-30 02:19:07 +00:00
|
|
|
self.as_mut().poll_trigger_then(cx, |io, cx| io.poll_flush(cx))
|
2021-04-28 09:01:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn poll_shutdown(
|
|
|
|
mut self: Pin<&mut Self>,
|
|
|
|
cx: &mut Context<'_>
|
2021-04-30 02:19:07 +00:00
|
|
|
) -> Poll<io::Result<()>> {
|
|
|
|
self.as_mut().poll_trigger_then(cx, |io, cx| io.poll_shutdown(cx))
|
2021-04-28 09:01:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn poll_write_vectored(
|
|
|
|
mut self: Pin<&mut Self>,
|
|
|
|
cx: &mut Context<'_>,
|
|
|
|
bufs: &[io::IoSlice<'_>],
|
2021-04-30 02:19:07 +00:00
|
|
|
) -> Poll<io::Result<usize>> {
|
|
|
|
self.as_mut().poll_trigger_then(cx, |io, cx| io.poll_write_vectored(cx, bufs))
|
2021-04-28 09:01:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn is_write_vectored(&self) -> bool {
|
|
|
|
self.io.is_write_vectored()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-09 06:58:25 +00:00
|
|
|
use crate::http::private::{Listener, Connection, RawCertificate};
|
2021-04-28 09:01:35 +00:00
|
|
|
|
|
|
|
impl<F: Future, C: Connection> Connection for CancellableIo<F, C> {
|
2021-07-04 22:37:27 +00:00
|
|
|
fn peer_address(&self) -> Option<std::net::SocketAddr> {
|
|
|
|
self.io.peer_address()
|
2021-04-28 09:01:35 +00:00
|
|
|
}
|
2021-07-09 06:58:25 +00:00
|
|
|
|
2022-02-22 22:01:25 +00:00
|
|
|
fn peer_certificates(&self) -> Option<&[RawCertificate]> {
|
2021-07-09 06:58:25 +00:00
|
|
|
self.io.peer_certificates()
|
|
|
|
}
|
2022-04-28 02:30:17 +00:00
|
|
|
|
|
|
|
fn enable_nodelay(&self) -> io::Result<()> {
|
|
|
|
self.io.enable_nodelay()
|
|
|
|
}
|
2021-04-28 09:01:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pin_project! {
|
|
|
|
pub struct CancellableListener<F, L> {
|
|
|
|
pub trigger: F,
|
|
|
|
#[pin]
|
|
|
|
pub listener: L,
|
|
|
|
pub grace: Duration,
|
2021-04-30 02:19:07 +00:00
|
|
|
pub mercy: Duration,
|
2021-04-28 09:01:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<F, L> CancellableListener<F, L> {
|
2021-04-30 02:19:07 +00:00
|
|
|
pub fn new(trigger: F, listener: L, grace: u64, mercy: u64) -> Self {
|
|
|
|
let (grace, mercy) = (Duration::from_secs(grace), Duration::from_secs(mercy));
|
|
|
|
CancellableListener { trigger, listener, grace, mercy }
|
2021-04-28 09:01:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<L: Listener, F: Future + Clone> Listener for CancellableListener<F, L> {
|
|
|
|
type Connection = CancellableIo<F, L::Connection>;
|
|
|
|
|
|
|
|
fn local_addr(&self) -> Option<std::net::SocketAddr> {
|
|
|
|
self.listener.local_addr()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn poll_accept(
|
|
|
|
mut self: Pin<&mut Self>,
|
|
|
|
cx: &mut Context<'_>
|
|
|
|
) -> Poll<io::Result<Self::Connection>> {
|
|
|
|
self.as_mut().project().listener
|
|
|
|
.poll_accept(cx)
|
|
|
|
.map(|res| res.map(|conn| {
|
2021-04-30 02:19:07 +00:00
|
|
|
CancellableIo::new(self.trigger.clone(), conn, self.grace, self.mercy)
|
2021-04-28 09:01:35 +00:00
|
|
|
}))
|
|
|
|
}
|
|
|
|
}
|
2021-06-01 18:46:17 +00:00
|
|
|
|
|
|
|
pub trait StreamExt: Sized + Stream {
|
|
|
|
fn join<U>(self, other: U) -> Join<Self, U>
|
|
|
|
where U: Stream<Item = Self::Item>;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<S: Stream> StreamExt for S {
|
|
|
|
fn join<U>(self, other: U) -> Join<Self, U>
|
|
|
|
where U: Stream<Item = Self::Item>
|
|
|
|
{
|
|
|
|
Join::new(self, other)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pin_project! {
|
|
|
|
/// Stream returned by the [`join`](super::StreamExt::join) method.
|
|
|
|
pub struct Join<T, U> {
|
|
|
|
#[pin]
|
|
|
|
a: T,
|
|
|
|
#[pin]
|
|
|
|
b: U,
|
|
|
|
// When `true`, poll `a` first, otherwise, `poll` b`.
|
|
|
|
toggle: bool,
|
|
|
|
// Set when either `a` or `b` return `None`.
|
|
|
|
done: bool,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T, U> Join<T, U> {
|
|
|
|
pub(super) fn new(a: T, b: U) -> Join<T, U>
|
|
|
|
where T: Stream, U: Stream,
|
|
|
|
{
|
|
|
|
Join { a, b, toggle: false, done: false, }
|
|
|
|
}
|
|
|
|
|
|
|
|
fn poll_next<A: Stream, B: Stream<Item = A::Item>>(
|
|
|
|
first: Pin<&mut A>,
|
|
|
|
second: Pin<&mut B>,
|
|
|
|
done: &mut bool,
|
|
|
|
cx: &mut Context<'_>,
|
|
|
|
) -> Poll<Option<A::Item>> {
|
|
|
|
match first.poll_next(cx) {
|
|
|
|
Poll::Ready(opt) => { *done = opt.is_none(); Poll::Ready(opt) }
|
|
|
|
Poll::Pending => match second.poll_next(cx) {
|
|
|
|
Poll::Ready(opt) => { *done = opt.is_none(); Poll::Ready(opt) }
|
|
|
|
Poll::Pending => Poll::Pending
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T, U> Stream for Join<T, U>
|
|
|
|
where T: Stream,
|
|
|
|
U: Stream<Item = T::Item>,
|
|
|
|
{
|
|
|
|
type Item = T::Item;
|
|
|
|
|
|
|
|
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<T::Item>> {
|
|
|
|
if self.done {
|
|
|
|
return Poll::Ready(None);
|
|
|
|
}
|
|
|
|
|
|
|
|
let me = self.project();
|
|
|
|
*me.toggle = !*me.toggle;
|
|
|
|
match *me.toggle {
|
|
|
|
true => Self::poll_next(me.a, me.b, me.done, cx),
|
|
|
|
false => Self::poll_next(me.b, me.a, me.done, cx),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
|
|
|
let (left_low, left_high) = self.a.size_hint();
|
|
|
|
let (right_low, right_high) = self.b.size_hint();
|
|
|
|
|
|
|
|
let low = left_low.saturating_add(right_low);
|
|
|
|
let high = match (left_high, right_high) {
|
|
|
|
(Some(h1), Some(h2)) => h1.checked_add(h2),
|
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
|
|
|
|
(low, high)
|
|
|
|
}
|
|
|
|
}
|