From 3970783d06ac34e9e7cbcb50c5d79de43f8594a6 Mon Sep 17 00:00:00 2001 From: Sergio Benitez Date: Thu, 29 Oct 2020 23:36:48 -0700 Subject: [PATCH] Fix SSE example, clean-up SSE related code. Also updates UI tests for latest nightly. --- .../ui-fail/from_form_type_errors.stderr | 4 + .../tests/ui-fail/route-type-errors.stderr | 18 +++ .../tests/ui-fail/typed-uri-bad-type.stderr | 10 ++ core/codegen/tests/ui-fail/uri_display.stderr | 84 +++++++------- core/lib/src/ext.rs | 18 +-- core/lib/src/response/response.rs | 7 +- core/lib/src/response/stream.rs | 33 +++--- examples/sse/Cargo.toml | 1 + examples/sse/src/main.rs | 103 +++++++----------- examples/sse/static/index.html | 22 ++++ 10 files changed, 167 insertions(+), 133 deletions(-) create mode 100644 examples/sse/static/index.html diff --git a/core/codegen/tests/ui-fail/from_form_type_errors.stderr b/core/codegen/tests/ui-fail/from_form_type_errors.stderr index 8cbaf3dd4e..469c8bf21a 100644 --- a/core/codegen/tests/ui-fail/from_form_type_errors.stderr +++ b/core/codegen/tests/ui-fail/from_form_type_errors.stderr @@ -3,9 +3,13 @@ error[E0277]: the trait bound `Unknown: FromFormValue<'_>` is not satisfied | 7 | field: Unknown, | ^^^^^^^^^^^^^^ the trait `FromFormValue<'_>` is not implemented for `Unknown` + | + = note: required by `from_form_value` error[E0277]: the trait bound `Foo: FromFormValue<'_>` is not satisfied --> $DIR/from_form_type_errors.rs:15:5 | 15 | field: Foo, | ^^^^^^^^^^^^^^^^^ the trait `FromFormValue<'_>` is not implemented for `Foo` + | + = note: required by `from_form_value` diff --git a/core/codegen/tests/ui-fail/route-type-errors.stderr b/core/codegen/tests/ui-fail/route-type-errors.stderr index 611273bfa0..5369630bc7 100644 --- a/core/codegen/tests/ui-fail/route-type-errors.stderr +++ b/core/codegen/tests/ui-fail/route-type-errors.stderr @@ -3,24 +3,32 @@ error[E0277]: the trait bound `Q: FromParam<'_>` is not satisfied | 8 | fn f0(foo: Q) {} //~ ERROR FromParam | ^^^^^^ the trait `FromParam<'_>` is not implemented for `Q` + | + = note: required by `from_param` error[E0277]: the trait bound `Q: FromSegments<'_>` is not satisfied --> $DIR/route-type-errors.rs:11:7 | 11 | fn f1(foo: Q) {} //~ ERROR FromSegments | ^^^^^^ the trait `FromSegments<'_>` is not implemented for `Q` + | + = note: required by `from_segments` error[E0277]: the trait bound `Q: FromFormValue<'_>` is not satisfied --> $DIR/route-type-errors.rs:14:7 | 14 | fn f2(foo: Q) {} //~ ERROR FromFormValue | ^^^^^^ the trait `FromFormValue<'_>` is not implemented for `Q` + | + = note: required by `from_form_value` error[E0277]: the trait bound `Q: FromQuery<'_>` is not satisfied --> $DIR/route-type-errors.rs:17:7 | 17 | fn f3(foo: Q) {} //~ ERROR FromQuery | ^^^^^^ the trait `FromQuery<'_>` is not implemented for `Q` + | + = note: required by `from_query` error[E0277]: the trait bound `Q: FromDataSimple` is not satisfied --> $DIR/route-type-errors.rs:20:7 @@ -35,27 +43,37 @@ error[E0277]: the trait bound `Q: FromRequest<'_, '_>` is not satisfied | 23 | fn f5(a: Q, foo: Q) {} | ^^^^ the trait `FromRequest<'_, '_>` is not implemented for `Q` + | + = note: required by `from_request` error[E0277]: the trait bound `Q: FromParam<'_>` is not satisfied --> $DIR/route-type-errors.rs:23:13 | 23 | fn f5(a: Q, foo: Q) {} | ^^^^^^ the trait `FromParam<'_>` is not implemented for `Q` + | + = note: required by `from_param` error[E0277]: the trait bound `Q: FromRequest<'_, '_>` is not satisfied --> $DIR/route-type-errors.rs:28:7 | 28 | fn f6(a: Q, foo: Q, good: usize, bar: Q) {} | ^^^^ the trait `FromRequest<'_, '_>` is not implemented for `Q` + | + = note: required by `from_request` error[E0277]: the trait bound `Q: FromParam<'_>` is not satisfied --> $DIR/route-type-errors.rs:28:13 | 28 | fn f6(a: Q, foo: Q, good: usize, bar: Q) {} | ^^^^^^ the trait `FromParam<'_>` is not implemented for `Q` + | + = note: required by `from_param` error[E0277]: the trait bound `Q: FromParam<'_>` is not satisfied --> $DIR/route-type-errors.rs:28:34 | 28 | fn f6(a: Q, foo: Q, good: usize, bar: Q) {} | ^^^^^^ the trait `FromParam<'_>` is not implemented for `Q` + | + = note: required by `from_param` diff --git a/core/codegen/tests/ui-fail/typed-uri-bad-type.stderr b/core/codegen/tests/ui-fail/typed-uri-bad-type.stderr index f624a9f130..5d3496e0a9 100644 --- a/core/codegen/tests/ui-fail/typed-uri-bad-type.stderr +++ b/core/codegen/tests/ui-fail/typed-uri-bad-type.stderr @@ -39,6 +39,8 @@ error[E0277]: the trait bound `S: FromUriParam` is n | 59 | uri!(not_uri_display: 10, S); | ^ the trait `FromUriParam` is not implemented for `S` + | + = note: required by `from_uri_param` error[E0277]: the trait bound `i32: FromUriParam>` is not satisfied --> $DIR/typed-uri-bad-type.rs:65:26 @@ -51,6 +53,7 @@ error[E0277]: the trait bound `i32: FromUriParam> > = note: required because of the requirements on the impl of `FromUriParam>` for `Option` + = note: required by `from_uri_param` error[E0277]: the trait bound `std::string::String: FromUriParam>` is not satisfied --> $DIR/typed-uri-bad-type.rs:65:43 @@ -65,6 +68,7 @@ error[E0277]: the trait bound `std::string::String: FromUriParam> and 2 others = note: required because of the requirements on the impl of `FromUriParam>` for `std::result::Result` + = note: required by `from_uri_param` error[E0277]: the trait bound `isize: FromUriParam` is not satisfied --> $DIR/typed-uri-bad-type.rs:69:20 @@ -95,12 +99,16 @@ error[E0277]: the trait bound `S: FromUriParam` is | 75 | uri!(other_q: 100, S); | ^ the trait `FromUriParam` is not implemented for `S` + | + = note: required by `from_uri_param` error[E0277]: the trait bound `S: FromUriParam` is not satisfied --> $DIR/typed-uri-bad-type.rs:78:26 | 78 | uri!(other_q: rest = S, id = 100); | ^ the trait `FromUriParam` is not implemented for `S` + | + = note: required by `from_uri_param` error[E0277]: the trait bound `S: Ignorable` is not satisfied --> $DIR/typed-uri-bad-type.rs:42:29 @@ -139,3 +147,5 @@ error[E0277]: the trait bound `S: FromUriParam` is | 83 | uri!(other_q: rest = S, id = _); | ^ the trait `FromUriParam` is not implemented for `S` + | + = note: required by `from_uri_param` diff --git a/core/codegen/tests/ui-fail/uri_display.stderr b/core/codegen/tests/ui-fail/uri_display.stderr index 5b1b4ae72c..6e5f27c80b 100644 --- a/core/codegen/tests/ui-fail/uri_display.stderr +++ b/core/codegen/tests/ui-fail/uri_display.stderr @@ -140,7 +140,7 @@ error[E0277]: the trait bound `Foo1: UriDisplay` is no ::: $WORKSPACE/core/http/src/uri/from_uri_param.rs | | type Target: UriDisplay

; - | ------------- required by this bound in `FromUriParam` + | ------------- required by this bound in `rocket::http::uri::FromUriParam::Target` | = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) @@ -153,9 +153,9 @@ error[E0277]: the trait bound `Foo1: UriDisplay` is no ::: $WORKSPACE/core/http/src/uri/from_uri_param.rs | | type Target: UriDisplay

; - | ------------- required by this bound in `FromUriParam` + | ------------- required by this bound in `rocket::http::uri::FromUriParam::Target` | - = note: required because of the requirements on the impl of `UriDisplay` for `&Foo1` + = note: required because of the requirements on the impl of `UriDisplay` for `&'__r Foo1` = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Foo1: UriDisplay` is not satisfied @@ -167,9 +167,9 @@ error[E0277]: the trait bound `Foo1: UriDisplay` is no ::: $WORKSPACE/core/http/src/uri/from_uri_param.rs | | type Target: UriDisplay

; - | ------------- required by this bound in `FromUriParam` + | ------------- required by this bound in `rocket::http::uri::FromUriParam::Target` | - = note: required because of the requirements on the impl of `UriDisplay` for `&mut Foo1` + = note: required because of the requirements on the impl of `UriDisplay` for `&'__r mut Foo1` = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Foo2: UriDisplay` is not satisfied @@ -181,7 +181,7 @@ error[E0277]: the trait bound `Foo2: UriDisplay` is no ::: $WORKSPACE/core/http/src/uri/from_uri_param.rs | | type Target: UriDisplay

; - | ------------- required by this bound in `FromUriParam` + | ------------- required by this bound in `rocket::http::uri::FromUriParam::Target` | = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) @@ -194,9 +194,9 @@ error[E0277]: the trait bound `Foo2: UriDisplay` is no ::: $WORKSPACE/core/http/src/uri/from_uri_param.rs | | type Target: UriDisplay

; - | ------------- required by this bound in `FromUriParam` + | ------------- required by this bound in `rocket::http::uri::FromUriParam::Target` | - = note: required because of the requirements on the impl of `UriDisplay` for `&Foo2` + = note: required because of the requirements on the impl of `UriDisplay` for `&'__r Foo2` = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Foo2: UriDisplay` is not satisfied @@ -208,9 +208,9 @@ error[E0277]: the trait bound `Foo2: UriDisplay` is no ::: $WORKSPACE/core/http/src/uri/from_uri_param.rs | | type Target: UriDisplay

; - | ------------- required by this bound in `FromUriParam` + | ------------- required by this bound in `rocket::http::uri::FromUriParam::Target` | - = note: required because of the requirements on the impl of `UriDisplay` for `&mut Foo2` + = note: required because of the requirements on the impl of `UriDisplay` for `&'__r mut Foo2` = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Foo3: UriDisplay` is not satisfied @@ -222,7 +222,7 @@ error[E0277]: the trait bound `Foo3: UriDisplay` is no ::: $WORKSPACE/core/http/src/uri/from_uri_param.rs | | type Target: UriDisplay

; - | ------------- required by this bound in `FromUriParam` + | ------------- required by this bound in `rocket::http::uri::FromUriParam::Target` | = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) @@ -235,9 +235,9 @@ error[E0277]: the trait bound `Foo3: UriDisplay` is no ::: $WORKSPACE/core/http/src/uri/from_uri_param.rs | | type Target: UriDisplay

; - | ------------- required by this bound in `FromUriParam` + | ------------- required by this bound in `rocket::http::uri::FromUriParam::Target` | - = note: required because of the requirements on the impl of `UriDisplay` for `&Foo3` + = note: required because of the requirements on the impl of `UriDisplay` for `&'__r Foo3` = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Foo3: UriDisplay` is not satisfied @@ -249,9 +249,9 @@ error[E0277]: the trait bound `Foo3: UriDisplay` is no ::: $WORKSPACE/core/http/src/uri/from_uri_param.rs | | type Target: UriDisplay

; - | ------------- required by this bound in `FromUriParam` + | ------------- required by this bound in `rocket::http::uri::FromUriParam::Target` | - = note: required because of the requirements on the impl of `UriDisplay` for `&mut Foo3` + = note: required because of the requirements on the impl of `UriDisplay` for `&'__r mut Foo3` = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Foo4: UriDisplay` is not satisfied @@ -263,7 +263,7 @@ error[E0277]: the trait bound `Foo4: UriDisplay` is no ::: $WORKSPACE/core/http/src/uri/from_uri_param.rs | | type Target: UriDisplay

; - | ------------- required by this bound in `FromUriParam` + | ------------- required by this bound in `rocket::http::uri::FromUriParam::Target` | = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) @@ -276,9 +276,9 @@ error[E0277]: the trait bound `Foo4: UriDisplay` is no ::: $WORKSPACE/core/http/src/uri/from_uri_param.rs | | type Target: UriDisplay

; - | ------------- required by this bound in `FromUriParam` + | ------------- required by this bound in `rocket::http::uri::FromUriParam::Target` | - = note: required because of the requirements on the impl of `UriDisplay` for `&Foo4` + = note: required because of the requirements on the impl of `UriDisplay` for `&'__r Foo4` = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Foo4: UriDisplay` is not satisfied @@ -290,9 +290,9 @@ error[E0277]: the trait bound `Foo4: UriDisplay` is no ::: $WORKSPACE/core/http/src/uri/from_uri_param.rs | | type Target: UriDisplay

; - | ------------- required by this bound in `FromUriParam` + | ------------- required by this bound in `rocket::http::uri::FromUriParam::Target` | - = note: required because of the requirements on the impl of `UriDisplay` for `&mut Foo4` + = note: required because of the requirements on the impl of `UriDisplay` for `&'__r mut Foo4` = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Foo5: UriDisplay` is not satisfied @@ -304,7 +304,7 @@ error[E0277]: the trait bound `Foo5: UriDisplay` is no ::: $WORKSPACE/core/http/src/uri/from_uri_param.rs | | type Target: UriDisplay

; - | ------------- required by this bound in `FromUriParam` + | ------------- required by this bound in `rocket::http::uri::FromUriParam::Target` | = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) @@ -317,9 +317,9 @@ error[E0277]: the trait bound `Foo5: UriDisplay` is no ::: $WORKSPACE/core/http/src/uri/from_uri_param.rs | | type Target: UriDisplay

; - | ------------- required by this bound in `FromUriParam` + | ------------- required by this bound in `rocket::http::uri::FromUriParam::Target` | - = note: required because of the requirements on the impl of `UriDisplay` for `&Foo5` + = note: required because of the requirements on the impl of `UriDisplay` for `&'__r Foo5` = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Foo5: UriDisplay` is not satisfied @@ -331,9 +331,9 @@ error[E0277]: the trait bound `Foo5: UriDisplay` is no ::: $WORKSPACE/core/http/src/uri/from_uri_param.rs | | type Target: UriDisplay

; - | ------------- required by this bound in `FromUriParam` + | ------------- required by this bound in `rocket::http::uri::FromUriParam::Target` | - = note: required because of the requirements on the impl of `UriDisplay` for `&mut Foo5` + = note: required because of the requirements on the impl of `UriDisplay` for `&'__r mut Foo5` = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Foo6: UriDisplay` is not satisfied @@ -345,7 +345,7 @@ error[E0277]: the trait bound `Foo6: UriDisplay` is no ::: $WORKSPACE/core/http/src/uri/from_uri_param.rs | | type Target: UriDisplay

; - | ------------- required by this bound in `FromUriParam` + | ------------- required by this bound in `rocket::http::uri::FromUriParam::Target` | = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) @@ -358,9 +358,9 @@ error[E0277]: the trait bound `Foo6: UriDisplay` is no ::: $WORKSPACE/core/http/src/uri/from_uri_param.rs | | type Target: UriDisplay

; - | ------------- required by this bound in `FromUriParam` + | ------------- required by this bound in `rocket::http::uri::FromUriParam::Target` | - = note: required because of the requirements on the impl of `UriDisplay` for `&Foo6` + = note: required because of the requirements on the impl of `UriDisplay` for `&'__r Foo6` = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Foo6: UriDisplay` is not satisfied @@ -372,9 +372,9 @@ error[E0277]: the trait bound `Foo6: UriDisplay` is no ::: $WORKSPACE/core/http/src/uri/from_uri_param.rs | | type Target: UriDisplay

; - | ------------- required by this bound in `FromUriParam` + | ------------- required by this bound in `rocket::http::uri::FromUriParam::Target` | - = note: required because of the requirements on the impl of `UriDisplay` for `&mut Foo6` + = note: required because of the requirements on the impl of `UriDisplay` for `&'__r mut Foo6` = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Foo7: UriDisplay` is not satisfied @@ -386,7 +386,7 @@ error[E0277]: the trait bound `Foo7: UriDisplay` is not ::: $WORKSPACE/core/http/src/uri/from_uri_param.rs | | type Target: UriDisplay

; - | ------------- required by this bound in `FromUriParam` + | ------------- required by this bound in `rocket::http::uri::FromUriParam::Target` | = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) @@ -399,9 +399,9 @@ error[E0277]: the trait bound `Foo7: UriDisplay` is not ::: $WORKSPACE/core/http/src/uri/from_uri_param.rs | | type Target: UriDisplay

; - | ------------- required by this bound in `FromUriParam` + | ------------- required by this bound in `rocket::http::uri::FromUriParam::Target` | - = note: required because of the requirements on the impl of `UriDisplay` for `&Foo7` + = note: required because of the requirements on the impl of `UriDisplay` for `&'__r Foo7` = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Foo8: UriDisplay` is not satisfied @@ -413,7 +413,7 @@ error[E0277]: the trait bound `Foo8: UriDisplay` is not ::: $WORKSPACE/core/http/src/uri/from_uri_param.rs | | type Target: UriDisplay

; - | ------------- required by this bound in `FromUriParam` + | ------------- required by this bound in `rocket::http::uri::FromUriParam::Target` | = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) @@ -426,9 +426,9 @@ error[E0277]: the trait bound `Foo8: UriDisplay` is not ::: $WORKSPACE/core/http/src/uri/from_uri_param.rs | | type Target: UriDisplay

; - | ------------- required by this bound in `FromUriParam` + | ------------- required by this bound in `rocket::http::uri::FromUriParam::Target` | - = note: required because of the requirements on the impl of `UriDisplay` for `&Foo8` + = note: required because of the requirements on the impl of `UriDisplay` for `&'__r Foo8` = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Foo9: UriDisplay` is not satisfied @@ -440,7 +440,7 @@ error[E0277]: the trait bound `Foo9: UriDisplay` is not ::: $WORKSPACE/core/http/src/uri/from_uri_param.rs | | type Target: UriDisplay

; - | ------------- required by this bound in `FromUriParam` + | ------------- required by this bound in `rocket::http::uri::FromUriParam::Target` | = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) @@ -453,9 +453,9 @@ error[E0277]: the trait bound `Foo9: UriDisplay` is not ::: $WORKSPACE/core/http/src/uri/from_uri_param.rs | | type Target: UriDisplay

; - | ------------- required by this bound in `FromUriParam` + | ------------- required by this bound in `rocket::http::uri::FromUriParam::Target` | - = note: required because of the requirements on the impl of `UriDisplay` for `&Foo9` + = note: required because of the requirements on the impl of `UriDisplay` for `&'__r Foo9` = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Foo10: UriDisplay` is not satisfied @@ -467,7 +467,7 @@ error[E0277]: the trait bound `Foo10: UriDisplay` is no ::: $WORKSPACE/core/http/src/uri/from_uri_param.rs | | type Target: UriDisplay

; - | ------------- required by this bound in `FromUriParam` + | ------------- required by this bound in `rocket::http::uri::FromUriParam::Target` | = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) @@ -480,7 +480,7 @@ error[E0277]: the trait bound `Foo10: UriDisplay` is no ::: $WORKSPACE/core/http/src/uri/from_uri_param.rs | | type Target: UriDisplay

; - | ------------- required by this bound in `FromUriParam` + | ------------- required by this bound in `rocket::http::uri::FromUriParam::Target` | - = note: required because of the requirements on the impl of `UriDisplay` for `&Foo10` + = note: required because of the requirements on the impl of `UriDisplay` for `&'__r Foo10` = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/core/lib/src/ext.rs b/core/lib/src/ext.rs index 8124224665..32c9ee26d9 100644 --- a/core/lib/src/ext.rs +++ b/core/lib/src/ext.rs @@ -1,17 +1,18 @@ use std::io; -fn read_max_internal(reader: &mut T, mut buf: &mut [u8], - wouldblock_flush_signalling: bool) - -> io::Result<(usize, bool)> { +fn read_max_internal( + reader: &mut T, + mut buf: &mut [u8], + wouldblock_flush: bool +) -> io::Result<(usize, bool)> { let start_len = buf.len(); let need_flush = loop { if buf.is_empty() { break false } match reader.read(buf) { Ok(0) => { break true } Ok(n) => { let tmp = buf; buf = &mut tmp[n..]; } - Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} - Err(ref e) if (e.kind() == io::ErrorKind::WouldBlock && - wouldblock_flush_signalling) => { break true } + Err(e) if e.kind() == io::ErrorKind::Interrupted => {} + Err(e) if e.kind() == io::ErrorKind::WouldBlock && wouldblock_flush => { break true }, Err(e) => return Err(e), } }; @@ -27,9 +28,8 @@ pub trait ReadExt: io::Read + Sized { /// Tries to fill buf with data. Short reads can occur for EOF or /// flush requests. With SSE enabled, a flush request occurs if /// the underlying reader returns ErrorKind::Wouldblock - fn read_max_wfs(&mut self, buf: &mut [u8]) - -> io::Result<(usize, bool)> { - read_max_internal(self, buf, cfg!(feature="sse")) + fn read_max_wfs(&mut self, buf: &mut [u8]) -> io::Result<(usize, bool)> { + read_max_internal(self, buf, cfg!(feature = "sse")) } } diff --git a/core/lib/src/response/response.rs b/core/lib/src/response/response.rs index 4638983cfc..ee27e84721 100644 --- a/core/lib/src/response/response.rs +++ b/core/lib/src/response/response.rs @@ -1018,10 +1018,9 @@ impl<'r> Response<'r> { /// [DEFAULT_CHUNK_SIZE](::response::DEFAULT_CHUNK_SIZE). Use /// [set_chunked_body](#method.set_chunked_body) for custom chunk sizes. /// - /// Normally, data will be buffered and sent only in complete - /// chunks. If you need timely transmission of available data, - /// rather than buffering, enable the `sse` feature and use the - /// `WouldBlock` technique described in + /// Normally, data will be buffered and sent only in complete chunks. If + /// you need timely transmission of available data, rather than buffering, + /// enable the `sse` feature and use the `WouldBlock` technique described in /// [Stream](::response::Stream). /// /// # Example diff --git a/core/lib/src/response/stream.rs b/core/lib/src/response/stream.rs index e744660622..def290ed9f 100644 --- a/core/lib/src/response/stream.rs +++ b/core/lib/src/response/stream.rs @@ -32,27 +32,26 @@ impl Stream { /// /// # Buffering and blocking /// - /// Normally, data will be buffered and sent only in complete - /// `chunk_size` chunks. + /// Normally, data will be buffered and sent only in complete `chunk_size` + /// chunks. /// - /// With the feature `sse` enabled, the `Read`er may signal that - /// data sent so far should be transmitted in a timely fashion - /// (e.g. it is responding to a Server-Side Events (JavaScript - /// `EventSource`) request. To do this it should return an - /// [io::Error](std::io::Error) of kind `WouldBlock` (which should - /// not normally occur), after returning a collection of data. - /// This will cause a flush of data seen so far, rather than being - /// treated as an error. + /// With the feature `sse` enabled, the `Read`er may signal that data sent + /// so far should be transmitted in a timely fashion (e.g. it is responding + /// to a Server-Side Events (JavaScript `EventSource`) request. To do this + /// it should return an [io::Error](std::io::Error) of kind `WouldBlock` + /// (which should not normally occur), after returning a collection of data. + /// This will cause a flush of data seen so far, rather than being treated + /// as an error. /// - /// Note that long-running responses may easily exhaust Rocket's - /// thread pool, so consider increasing the number of threads. - /// If doing SSE, also note the 'maximum open connections' browser - /// limitation which is described in the - /// [EventSource documentation](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) + /// Note that long-running responses may easily exhaust Rocket's thread + /// pool, so consider increasing the number of threads. If doing SSE, also + /// note the 'maximum open connections' browser limitation which is + /// described in the [EventSource + /// documentation](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) /// on the Mozilla Developer Network. /// - /// Without the `sse` feature, a `WouldBlock` error is treated - /// as an actual error. + /// Without the `sse` feature, a `WouldBlock` error is treated as an actual + /// error. pub fn chunked(reader: T, chunk_size: u64) -> Stream { Stream(reader, chunk_size) } diff --git a/examples/sse/Cargo.toml b/examples/sse/Cargo.toml index 56d93f9b0f..d09d052704 100644 --- a/examples/sse/Cargo.toml +++ b/examples/sse/Cargo.toml @@ -6,3 +6,4 @@ publish = false [dependencies] rocket = { path = "../../core/lib", features = ["sse"] } +rocket_contrib = { path = "../../contrib/lib" } diff --git a/examples/sse/src/main.rs b/examples/sse/src/main.rs index c7bb4ae92b..8fdde7eec7 100644 --- a/examples/sse/src/main.rs +++ b/examples/sse/src/main.rs @@ -1,79 +1,60 @@ #![feature(proc_macro_hygiene, decl_macro)] -#[macro_use] -extern crate rocket; -use rocket::http::ContentType; -use rocket::response::Content; -use rocket::response::Responder; -use std::io::BufReader; -use std::io::Read; -use std::thread::sleep; -use std::time::Duration; - -#[get("/")] -fn index<'r>() -> impl Responder<'r> { - Content( - ContentType::HTML, - r##" - -

Hi!

+#[macro_use] extern crate rocket; +extern crate rocket_contrib; -
nothing yet
+use std::io::{self, BufReader, Read, Write}; +use std::time::Duration; - - -"##, - ) -} +use rocket::http::ContentType; +use rocket::response::{Content, Stream}; +use rocket_contrib::serve::StaticFiles; -#[get("/script.js")] -fn script<'r>() -> impl Responder<'r> { - Content( - ContentType::JavaScript, - r##" -status_node = document.getElementById('spong'); -status_node.innerHTML = 'js-done' +const BUF_SIZE: usize = 4096; -es = new EventSource("updates"); -es.onmessage = function(event) { - status_node.innerHTML = event.data; -} -"##, - ) +struct Counter { + n: usize, + state: State, } -const BUF_SIZE : usize = 4096; - -type TestCounter = BufReader; -#[derive(Debug)] -struct TestCounterInner { - next: usize, -} -impl Read for TestCounterInner { - fn read(&mut self, buf: &mut [u8]) -> std::io::Result { - sleep(Duration::from_millis(500)); - let data = format!("data: {}\n\n", self.next); - self.next += 1; - // `BufReader` won't call us unless its buffer is empty, and - // then buf will be the whole of the buffer, ie of size - // BUF_SIZE (due to the `with_capacity` call). So `data` is - // definitely going to fit. - buf[0..data.len()].copy_from_slice(data.as_bytes()); - Ok(buf.len()) +enum State { Flush, Sleep, Write } + +impl Read for Counter { + fn read(&mut self, mut buf: &mut [u8]) -> io::Result { + // ping/pong between sleep and flush, and implicit sleep -> write + match self.state { + State::Flush => { + self.state = State::Sleep; + Err(io::ErrorKind::WouldBlock)?; + }, + State::Sleep => std::thread::sleep(Duration::from_millis(500)), + State::Write => { /* fall through to `State::Write` */ }, + } + + self.n += 1; + self.state = State::Flush; + + // `BufReader` won't call us unless its buffer is empty, and then buf + // will be the whole of the buffer, ie of size BUF_SIZE (due to the + // `with_capacity` call). So `data` is definitely going to fit. + let data = format!("data: {}\n\n", self.n); + buf.write_all(data.as_bytes())?; + Ok(data.len()) } } +type CounterStream = Stream>; + #[get("/updates")] -fn updates<'x>() -> impl Responder<'x> { - let tc = TestCounterInner { next: 0 }; - let tc = BufReader::with_capacity(BUF_SIZE, tc); - let ch = rocket::response::Stream::from(tc); - let ct = ContentType::parse_flexible("text/event-stream; charset=utf-8").unwrap(); - Content(ct, ch) +fn updates() -> Content { + let reader = BufReader::with_capacity(BUF_SIZE, Counter { n: 0, state: State::Write }); + let ct = ContentType::with_params("text", "event-stream", ("charset", "utf-8")); + Content(ct, Stream::from(reader)) } fn main() { rocket::ignite() - .mount("/", routes![index, script, updates,]) + .mount("/", routes![updates]) + .mount("/", StaticFiles::from("static")) .launch(); } diff --git a/examples/sse/static/index.html b/examples/sse/static/index.html new file mode 100644 index 0000000000..e27592af79 --- /dev/null +++ b/examples/sse/static/index.html @@ -0,0 +1,22 @@ + + + + + + Rocket SSE Example + + +

Streaming...

+
nothing yet
+ + +