Open chicoxyzzy opened 7 years ago
The main reason to not allow this is that this feature can somewhat easily be written on top of fetch()
. I'm not sure we need put more effort into the "legacy" XMLHttpRequest
, WebSocket
, and EventSource
networking APIs.
Hmm... I have not seen any SSE alternatives based on Fetch yet. Do you know any implementations?
No, sorry. It's also still a little early since only Chrome supports https://streams.spec.whatwg.org/ for now. But you can build any kind of abstraction on top of that. You would also no longer be limited by the SSE format and such.
How should we cancel a Fetch stream? Cancelable Promises proposal is withdrawn.
Closing this since I don't think we'll be able to find sufficient interest to extend this API.
@annevk What would indicate a sufficient interest?
SSE is IMO a really nice standard for implementing simple web-based queue-consumers with out of the box at least once consumption semantic and I think it has very real use-cases. But as stated above it obviously lacks the following capabilities:
Last-Event-ID
-Header that can be used to step into an already partially consumed stream (e.g. to resume from a certain position after a page reload).There are also quite a lot active server-side implementations of SSE out there.
It's use-cases really come to shine with event-based/ reactive backends. Something that is, compared to REST, not necessarily the thing yet, but (given all the reactive/async/streaming movement going on in the backend world) seems to be relevant enough (probably needs references).
It would of course be possible to build something similar with fetch - but it would not follow any standard and assumptions like "hey this client library and that server library supports SSE - so we can probably wire them together" will no longer hold. And beside this spec there is no such thing as standard GET
for event streams.
So, I'd second to keep the EventSource/SSE standard alive and move it forward to support custom headers.
I'm not sure, but over the past decade I've heard this request from three people or so, which is not really enough. Also, you can continue to use server-sent events and the server-side implementations thereof, you would just need to implement the client-side bits using fetch()
if you want to transmit more headers.
Make it four. :) We recently chose SSE over Web Sockets for a reactive app because it's much simpler to program against and the built-in reliability is nice. Having to work around the lack of custom headers support by putting the authorization token in the query string is probably the one thing really missing from the standard. Why should we pause use of a perfectly good technology and wait until replacements come out?
I have a working implementation, forked from Yaffle's polyfill.
https://github.com/Yaffle/EventSource/compare/master...kmayer:kmayer-2
Given the (renewed) interest in this I'll reopen. We'll still need implementer interest.
Great!
Could someone with edit permission correct EvenSource -> EventSource in the title?
I think this is easy to implement on Chromium and wouldn't introduce so much complexity. Wanna hear other vendors' interest.
I work on the team that maintains EventSource for Chrome. EventSource is not being actively developed. We feel resources are better spent in filling the gaps in the more generally-useful facilities provided by fetch().
To give some idea of scale, fetch() body streaming is already used on ten times as many pages as EventSource in Chrome.
I acknowledge that the resumption facilities provided by EventSource are very convenient. However, you can already achieve the same things, with more control, in browsers that support fetch() streaming. I expect that every everfresh browser will support fetch() streaming before any browser supports setting headers for EventSource.
To be clear, I don't oppose improvements to EventSource. @danielwegener's arguments in https://github.com/whatwg/html/issues/2177#issuecomment-278254601 are very persuasive. However, my team cannot justify spending any resources on it.
In summary: possible? yes. Likely to happen? no.
I'll +1 on wanting to set the Last-Event-ID
header in the initial request. The query string can be used as a pretty simple workaround but it's unfortunate to not be able to use an existing mechanism for the initial request.
I was looking into using fetch to consume the event-stream but it seems like I would have to reimplement the parsing and automatic reconnects which is a lot more work than I'm willing to go for.
So if I understand correctly what is being said here it that SSE and WS are old technologies that should no longer be supported and authorization is not important to use it from a browser, even though every other client library does support Authorization headers... And while there is no real cross browser support for fetch or any protocol that would enable developers to use like WS or SSE, the only option is to send what would normally go thru a header as a query string.
@ricea would it really take more than a 2 week sprint to add this to chrome? Honestly?!
Exactly. I love the promise (pun intended) of fetch and streams, but doing right by the existing standards adds customer value now for a set of use cases that are becoming increasingly important while the implementers' roadmaps can continue to (slowly) converge on stream-composable fetch-based solutions.
2 years later, not a single browser has full support for fetch() streaming
and we still can't set headers on EventSource
:man_shrugging:
@julienmachon actually fetch streaming is supported in these browsers:
It's still would be great to use headers in SSE though.
@chicoxyzzy according to this https://caniuse.com/#feat=streams we only have partial support for fetch streaming but maybe it's enough for reading serve-sent event (although Firefox under a flag is a bit of a bummer)
If you have some fetch streaming examples playing nicely with SSE, I'd love to see them! :grimacing:
@julienmachon all of browsers support ReadableStreams in streaming response body so it should be enough for most cases.
Unfortunately I don't have any examples with fetch streaming right now, I use WebSockets mostly.
Hi there I'm also stumped with SSE not supporting headers after all this while, if anyone does have an example for using the fetch streaming alternative that has been suggested it'd be awesome if they drop a gist link
For setting authorization headers yaffle polyfill seems to be pretty good. It works on IE as well https://github.com/Yaffle/EventSource I have tested in chrome, fire and IE
You could pass in header and also control the heart beats
//See to that EventSource is tagged to Polyfill version and must for chrome and firefox else it would fall back to native eventsource which does not support headers
var EventSource = EventSourcePolyfill;
const versionEventSource = new EventSource('http://localhost:8080/versions',{
headers: {
'Authorization': 'my jwt token'
},
heartbeatTimeout: 300000 //5 minutes else 45 seconds by default, it initiates another request
});
Only cons is that in chrome EventStream windows we cannot see the messages as it is not it's native EventSource. Otherwise it is all good.
@maziey93 @julienmachon the Yaffle/EventSource library actually uses fetch streams internally (and falls back on xhr) - so you could just think of that library as a working implementation of using fetch streams to consume server sent events. (...an implementation that also happens to conform to the EventSource spec).
https://github.com/Yaffle/EventSource/blob/master/src/eventsource.js
@ricea
EventSource is not being actively developed. We feel resources are better spent in filling the gaps in the more generally-useful facilities provided by fetch().
Are these really conflicting interests for browser vendors, when it's likely (?) that native implementations are using Fetch internally also? Or could quite easily use fetch streams - as in the polyfill above?
EventSource could perhaps accept a Request object (optionally) in place of the URL string (i.e. the same parameters as Fetch currently accepts): https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters
(could then pass custom headers etc.. via the Request object)
@ejdaly thanks for clarifying about Yaffle/EventSource. I do love the idea of being able to pass a Request object, in fact it'd be a no brainer if native implementations use fetch internally.
It would also be great if there was an officially supported polyfill or package that basically replaced the browser eventsource, implementing fetch internally. Would satisfy both parties.
If the polyfill mentioned above is great, maybe validate it and put it as a suggested polyfill to use instead of the default browser eventsource.
With new Chromium-based Edge browser release we will have SSE support in all major browsers
Is the recommended approach, if using browser Eventsource, to pass authentication tokens via cookies or the url? Those two seem like the only options.
You can still protect your site from csrf by having your sse events trigger no state changes - just fetches of data, or prevent your site from being loaded by a different domain.
Am I the only one not understanding the reasoning behind this? I mean, I understand there‘s fetch streaming but you still need to implement reading the standardized SSE response yourself in JavaScript. It‘s slower and there are no native debugging tools contrary to EventSource
. So we have a standard but should implement the browser side ourselves because of not being able to set headers? Although EventSource
is 95% there, native, stable and fast? I‘m slightly confused :)
@Toflar I really do understand your frustrations, I’ve had to abandon my use case for SSE because although the polyfill for EventSource works it feels obtrusive unlike the native implementation. This issue has been tagged needs implementer interest
I think that’s what we should focus on if we want to land header support for EventSource
@Toflar I have tried to implement an EventSource-like consumer with Fetch. Actually the API (ReadableStream and TextDecoder) is still native. They have just split it into individual components.
The only issue is with browser support. Firefox still needs users to manually enable support for ReadableStream for Fetch.
I'm confused that EventSource
api is considered legacy... almost 4 years ago?! So if we can't get header support, can the streaming fetch at least show up in the network tab nicely?
I went through quite a few posts in an attempt to figuring out if the auth token be sent in the EventSource() call. Although there are polyfill alternatives that allow adding headers while others mentioned sending auth token over ssl.
Instead of using polyfill EventSource() or sending the auth token in the query params over ssl, send a eventSource identifier (eventSrcUUID) over ssl in the params of EventSource url as follows :-
On user authentication, eventSrcUUID is generated along with the sseEmitter on the server and place in a sseEmitterMap. The sseEmitter is also placed alongside user session data and the eventSrcUUID is sent to the client along with user auth info.
Client retrieves the eventSrcUUID from the response and invokes the EventSource() call with the eventSrcUUID in the param. On the server, the sseEmitterMap is referenced to retrieve the the eventSrc object and the entry is removed from the sseEmitterMap to disallow further invocations. The sseEmitter object saved in session data is used to send event notifications to client.
I read through the above discussions. If EventSource is HTTP, I couldn't imagine a HTTP request without the ability to add headers. It's quite natural to think of headers when we speak HTTP.
@Toflar I really do understand your frustrations, I’ve had to abandon my use case for SSE because although the polyfill for EventSource works it feels obtrusive unlike the native implementation. This issue has been tagged
needs implementer interest
I think that’s what we should focus on if we want to land header support for EventSource
@eokoneyo How do I express my interest for it? Is this the place or is there some other place for expressing our interest?
I just want to get one thing straight here: I'm not "frustrated" :) I was confused because being able to send meta data (aka headers) along with HTTP requests seems like the most normal thing to do for me. But I've been in the (OSS) developer community for far too long to be frustrated with things. It's just never been implemented by anyone so if I need it, it's also my duty to implement/fix things. Simple :) But I'd be interested in the meaning of "needs implementer interest" as well.
From what I understood OAuth 2.1 will forbid the usage of bearer tokens in query params. In OAuth 2 it is "somewhat" allowed:
SHOULD NOT be used unless it is impossible to transport the access token in the "Authorization" request header field or the HTTP request entity-body rfc6750#section-2.3
(which sounds like a case for SSE) but draft-ietf-oauth-security-topics-15#section-4.3.2 seems to aim to forbid it. As a result, SSE can likely not be used with OAuth2.1 bearer token authorization because it is impossible to transport the bearer access token (I think this counts as "frustrated" :) ).
One point which has not been addressed in this long thread is how a OAuth token passed in the Authorization header would be refreshed when it expires (and how/when does the EventSource detect it has expired)?
I don't think there's any need to specify that at this level; you could either have the server send a message that cause the client to proactively re-establish the connection with a refreshed token, or you could have the server close the connection and have the client reestablish it with the latest token if the old one expired. https://stackoverflow.com/questions/24564030/is-an-eventsource-sse-supposed-to-try-to-reconnect-indefinitely
Is it really necessary to terminate the connection when the token expires? The request is authorized by the server upon receiving and this (already authorized) connection is then kept permanently open while transferring the response (in chunks).
Comparing to non-streamed HTTP requests: Given that you use a token with 30s expiry time and the client issues a POST request When the server grants authorization but takes 60s to generate the response Do you expect the server to respond with unauthorized?
I just noticed the existence of SSE and found out it is what I'm looking for to notify the client without introduce WebSocket into my server. Then this issue broke my heart due to I'm using OIDC.
any update?
Well, one year later @ultimaweapon.
I stumble over the same problem with OIDC. It would be a simple solution, if developers could set the header by themselves.
I found a possible workaround on stackoverflow: https://stackoverflow.com/questions/28176933/http-authorization-header-in-eventsource-server-sent-events
Maybe, WebTransport will be an appropriate candidate to build our use case. See https://w3c.github.io/webtransport
I'd like to share this polyfill that uses fetch streaming instead of XHR polling: https://github.com/Azure/fetch-event-source
We can easily set headers with this polyfill.
Thank you @rodorgas for the solution.
It seems to me like this should be considered a known security vulnerability, since it forces developers to put auth tokens in the URL and URLs (even in HTTPS) are vulnerable. Even without an attack like that, URLs are often stored in log files, meaning auth tokens would be stored there too.
I think the solution here is to either add a custom header feature or just fully deprecate and eventually remove EventSource
altogether. From a security standpoint, leaving it unchanged seems like a worse approach.
(Feel free to correct me if I'm misunderstanding anything here.)
it forces developers to put auth tokens in the URL and [URLs (even in HTTPS) are vulnerable] (https://www.securityweek.com/hackers-can-intercept-https-urls-proxy-attacks/).
While I'm inclined to agree that putting auth tokens in URLs is distasteful on several levels, I'm compelled to note that that particular issue was patched[1] a month before the article was even written seven years ago.
[1] https://bugs.chromium.org/p/chromium/issues/detail?id=593759#c72
I find SSE to be a very standard, nice and simple way to send events to the browser. Then I found it doesn't support set header. I was surprised by that.
I share the felling of @ultimaweapon. When I discovered EventSource and realized that it works over HTTP, the first thing that came to mind was the ability to set headers, as it feels like a natural expectation. However, this issue has been open for approximately seven years, so I assume it won't be implemented anytime soon, which is quite disappointing.
It's 2023, and it's really frustrating that SSE still doesn't support custom headers. With all the tech updates we've seen, it's surprising this hasn't been fixed. Developers have been asking for it for years. You'd think they'd have listened by now, but nope, we're still waiting.
The seemingly prevailing attitude that "this new API can do all these things if you take time to implement them, so these older APIs we created (to do 99% of the implementation) can go pound sand" is disheartening, and does nothing to promote trust or interest in using any API new or old. I could implement on this new API, but what's that down the road? The next shiny thing is just over the horizon? It may take 5+ years to be usable, and have a totally different interface, but we're all going to mark the current API legacy and divert all resources to the new stuff? Does the WHATWG need to start an LTS requirement for their API proposals so at least we have some idea how to gauge the utility of adopting an API if it's just going to be staleware in x months / years?
If Fetch is the way, can't the EventSource API be rebased onto Fetch, making it continue to be useful and relevant? Just a thought.
Hello everyone! Just my 2 cents for this, I have an api, that is an SSE. It just spits data over local network and I just want people who have my bearer token to use it only, or else it is just open to anyone. I understand it isn't the most important thing, but adding some support of headers to the object would be so much better then making a websocket, and having to deal with the whole workflow with that.
Seems like there is no way to add Authorization header or any other headers for EventSource. Is there any reason it shouldn't be possible?