Comments (22)
Support has landed! See the EventStream
and Event
docs and the new chat example.
from rocket.
@SergioBenitez There are a number of differences between Server Send Events (SSE) and WebSockets (WS) -- definitely worth reading up on. They both have value for their specific use-cases. SSE has some great features, and WS has some problem that only become apparent once you investigate them. For example, WS don't currently work with AWS ELBs unless the ELB is in PROXY-mode, which removes a lot of the benefit of an ELB! Also, the security model for WS is different than standard HTTP, which complicates securely implementing WS. WS need an UPGRADE on the HTTP protocol to work, whereas SSE does not. There are a number of other advantages to SSE (easy to implement, browsers automatically reconnect if they become disconnected, ... more ... more), and are good for when you don't have to have the bi-directional capabilities or super-low-latency of WS. I would definitely vote +1 for SSE support in Rocket (which, I'm still loving!)
from rocket.
Bringing this back to 0.5, thanks to @jebrosen's nearly complete implementation!
from rocket.
Pushing this up to 0.5
.
from rocket.
I believe Rocket should be able to handle Server Sent Events. It's likely that the implementation would reside in contrib
, but core
should make such an implementation as simple as possible. That being said, the current synchronous architecture isn't amenable to SSE. As a result, I'm slating this for a later milestone. Nonetheless, I am committed to seeing this in Rocket.
from rocket.
+1 on the native support for web sockets within Rocket
from rocket.
why would someone use server-sent events instead of web sockets
Because if you only need unidirectional (server to browser) notifications, why set up the more complex WebSocket protocol? Okay, I know WS is not actually complex, but still. SSE just feels lighter.
from rocket.
Ok, I managed to patch version 0.10.13 of hyper to force flush sockets.
I know i said i would stop posting here, but this may help more people than me.
This enables to do streaming "properly", so SSE and that kind of stuff.
Latest Hyper versions does use flush, but rocket.rs can't build with latest hyper due to various changes.
Basically, for hyper 0.10.13, edit src/server/response.rs
and you need to have :
217 impl<'a> Write for Response<'a, Streaming> {
218 #[inline]
219 fn write(&mut self, msg: &[u8]) -> io::Result<usize> {
220 debug!("write {:?} bytes", msg.len());
221 let r = self.body.write(msg);
222 self.body.flush();
223 r
224 }
This will properlly flush the socket and make it possible to send only a few bytes.
The sample codes i pasted above will then work perfectly well.
from rocket.
In my opinion it would be great to have an example that shows how to currently implement a simple SSE or websocket solution using the current API (I guess using Stream in some way).
from rocket.
I think my MR #1365 would satisfy this request for Rocket 0.4.x.
Having read the discussion, I wanted to respond to a few points:
"will block" has the serious consequence that the maximum number of clients with open SSE channels is bounded by the number of worker threads
Yes. Depending on the application, it will be necessary to significantly increase the number of worker threads (and hope the system doesn't overload or get DOS'd). Also there is a browser limitation, see https://developer.mozilla.org/en-US/docs/Web/API/EventSource for which traditional workaround is to make the SSE requests to a wildcard domain with a randomly-chosen leafname, or similar (the client maximum connections limit being per domain, not per IP address).
Ok, I managed to patch version 0.10.13 of hyper to force flush sockets.
I don't think that change is necessary (everything works for me with hyper 0.10.16) or desirable. If rocket can be persuaded to complete a chunk, and issue a flush call, hyper seems to do the right things.
In my opinion it would be great to have an example that shows how to currently implement a simple SSE
I have code that could easily become such a thing if my MR #1365 is accepted. If there is interest I could produce a suitable git branch.
from rocket.
Unless otherwise stated, everything is streaming in Rocket by default, not just Stream
. If you'd like, you can implement server sent events via Responder. You'd need to create a new Read
type that does the appropriate thing. Of course, that Responder
will block while sending events, a side effect of Rocket being synchronous. This will eventually stop being the case.
On a more fundamental level: why would someone use server-sent events instead of web sockets? I think seeing some kind of native support for web sockets would be nice, and it would be even nicer if that supplanted the need for server-sent events.
from rocket.
This would be great. I tried to make my own implementation using a Responder but my rust knowledge is not there yet. I would love to see an example of how to do SSE in Rocket.
from rocket.
I'm, sadly, going to push this to 0.6 to clear the way for 0.5. It's likely we can have a solution as a point release in the 0.5 series, however.
from rocket.
@lpgeiger You're mixing documentation/examples, and perhaps code, from master
and 0.4
. Neither master
nor v0.4
include built-in support for SSE. v0.4
recently gained the ability to implement SSE externally, and we added an sse
example to the repository doing just this. master
has had support for external implementation of SSE since it became async
, but we do not have an example on how to implement support externally; @jebrosen has as example, however.
In general, "nice" SSE support is blocked on a write-based API for responses. We can emulate such an API in Rocket with a performance cost, but it sub-optimal. Ideally, an underlying HTTP library would support such an API, but that is not the case today.
BTW, (and you may be aware of this) when I try the same example code, except using published
rocket
androcket-contrib
as the dependencies leads to a this error:
This example works in both v0.4
and master
, and is tested by the CI on every commit. I suspect you're mixing versions in your Cargo.toml
, however. Ensure that your rocket
and rocket_contrib
versions point at the same version.
from rocket.
Hello, i am having (almost) the same need.
As i am a complete beginner with rust (im trying to see how hard it would be to port an existing project from C to Rust), but i still have been able to come up with this code :
https://gist.github.com/gfriloux/5f82c702e445fdc4b447586bb6721dbd
What it does is simply read on a unix pipe.
If i only return a File structure from the pending
function, rocket.rs will only read the pipe once and return this result to the HTTP client (so it wont be a "stream" or a chunked answer).
So i create a PipeLoop structure, implement Responder
and Read
for it, and each read call will be blocking.
This allows any other app to write into the pipe as it has things to write, and rocket.rs to be aware of it.
Still, there is a thing that doesnt work properlly : rocket.rs will bufferise on its side.
It seems to wait for around 16KB of data to start sending the first bytes.
For example, if my pipe is /tmp/testfifo
, i have to do this :
# echo "toto" >/tmp/testfifo
# perl -E 'say "=" x 8000' >/tmp/testfifo
# perl -E 'say "=" x 8000' >/tmp/testfifo
Only to receive "toto" on the client side.
This is where i begin to not know what to do.
I am reading rocket's source code, trying to find an answer, but if you know the last bits needed to get it working, it would be awesome.
I'd like to come up with a workaround before v0.8.0 (having a long running thread isn't a problem in my case).
from rocket.
Using chunked_body()
(with a size of 5 bytes for example) will trigger a lot of read()
calls into my PipeLoop structure, but it won't send anything until i pile thousands of chars.
This makes me believe (i am not yet able to determine it) that hyper will bufferize on its side.
from rocket.
Using Stream
instead of writing my own Responder
makes the code more simple, but gives the same result.
Here is a code example : https://gist.github.com/gfriloux/c8846afed6d2bfceffd13fc5375bced3
from rocket.
I dont know where its blocking (my low rust knowledge doesnt help) but i assume it should not wait to have the buffer filled to send data.
Data should be sent either immediately or after a very short window.
This would unblock this issue the time you implement SSE inside rocket.rs.
Comparing to C functions, write()
or send()
won't block data until a fixed amount of data is given.
You can send 1 byte without any problem, it won't delay it indefinitly, waiting for more data.
from rocket.
Ok, after spending some days on other stuff, im back at this.
The problem isnt in rocket.rs itself.
setting logs at debug level, i can see that hyper writes the data, but the HTTP client doesnt get it :
--> /root/.cargo/registry/src/github.com-1ecc6299db9ec823/hyper-0.10.13/src/server/response.rs:220
write 10 bytes
chunked write, size = 10
You need to write a bunch of data for it to be received by the HTTP client (it wont even send the HTTP headers, in some cases).
As i had doubts about curl, i directly went with telnet, and the same problem occurs.
My first hint is that hyper is missing a few flushes.
So i will stop reporting here this behavior.
from rocket.
The problem with an example of SSE in the current API is related to this point:
Of course, that Responder will block while sending events, a side effect of Rocket being synchronous
"will block" has the serious consequence that the maximum number of clients with open SSE channels is bounded by the number of worker threads, at which point the server will "hang" until those clients disconnect. If I'm reading #33 (comment) correctly, then hyper also needs modifications for SSE to work correctly.
#1065 will make doing this not-dangerous - open Response
channels "waiting" on the server to push data will no longer prevent new incoming requests from being processed. And #1066 will make SSE easier to implement by eliminating the need to implement some kind of custom Read
type.
from rocket.
newb here. I see this is a long running thread, so unsure if this is the right place for these comments. I've run the sse demo in /examples
. Looks powerful! Happy to contribute to get this to production.
As of Mar/2021 how do the proposal above change the behavior or API in the demo?
BTW, (and you may be aware of this) when I try the same example code, except using published rocket
and rocket-contrib
as the dependencies leads to a this error:
error[E0277]: the trait bound `Vec<Route>: std::convert::From<StaticFiles>` is not satisfied
--> src/main.rs:58:10
|
58 | .mount("/", StaticFiles::from("static"))
| ^^^^^ the trait `std::convert::From<StaticFiles>` is not implemented for `Vec<Route>`
from rocket.
Reading up on this very thing, http2 can basically do websockets with fetch api and sse.
from rocket.
Related Issues (20)
- how to return error as a Json from FromParam HOT 3
- Responder enums not serializing like expected HOT 1
- FileServer can serve pre-gzipped content if it exists on the filesystem HOT 1
- Cookies aren't read by get methods but it exists in the browser HOT 2
- HTTP3/QUIC support HOT 15
- Add HTMLStream HOT 5
- cookie removal and Microsoft Edge HOT 7
- Inject script to auto-reload browser when Rocket restarts
- Rocket App Hangs HOT 5
- DefaultListener::bindable() isnβt usable HOT 8
- Allow routes that match any method HOT 4
- Hyper and Rocket disagreeing on validity of URL HOT 3
- Allow from form macro to work on structs with range HOT 4
- Clippy Lint w/ FromForm derive HOT 7
- Possible Incompleteness HOT 1
- Possible Incompleteness HOT 1
- doc: change `&ContentType` with `&Accept` in the list of implementations of `FromRequest` HOT 1
- [Feature]: Enhanced State Mutation for Effortless Handling of Shared Resources HOT 5
- Guide navigation causes relative links inside articles to 404 HOT 1
- Redirection to a route which takes a vector parameter results in an error HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from rocket.