
Security News
Feross on Risky Business Weekly Podcast: npm’s Ongoing Supply Chain Attacks
Socket CEO Feross Aboukhadijeh joins Risky Business Weekly to unpack recent npm phishing attacks, their limited impact, and the risks if attackers get smarter.
launchdarkly-eventsource
Advanced tools
Fork of eventsource package - W3C compliant EventSource client for Node.js and browser (polyfill)
The launchdarkly-eventsource npm package is a client for consuming server-sent events (SSE) from LaunchDarkly. It allows you to listen to real-time updates from LaunchDarkly's feature flag service, making it useful for applications that need to react to changes in feature flags without polling.
Connecting to an Event Stream
This feature allows you to connect to an event stream using a specified URL. The code sample demonstrates how to open a connection and handle open and error events.
const { EventSource } = require('launchdarkly-eventsource');
const url = 'https://example.com/events';
const es = new EventSource(url);
es.onopen = () => {
console.log('Connection to event stream opened.');
};
es.onerror = (err) => {
console.error('Error in event stream:', err);
};
Listening to Specific Events
This feature allows you to listen to specific events from the event stream. The code sample shows how to listen for 'message' and 'custom-event' events and handle them accordingly.
es.addEventListener('message', (event) => {
console.log('New message event:', event.data);
});
es.addEventListener('custom-event', (event) => {
console.log('Custom event received:', event.data);
});
Closing the Event Stream
This feature allows you to close the event stream connection. The code sample demonstrates how to close the connection and log a message.
es.close();
console.log('Event stream closed.');
The eventsource package is a polyfill for the EventSource API, which is used for receiving server-sent events. It provides similar functionality to launchdarkly-eventsource but is more general-purpose and not specific to LaunchDarkly.
The sse-channel package is a simple server-sent events channel for Node.js. It allows you to create an SSE server and send events to clients. While it provides similar real-time event capabilities, it is focused on server-side implementation rather than client-side consumption like launchdarkly-eventsource.
The server-sent-events package is a lightweight library for handling server-sent events in Node.js. It offers similar functionality for consuming SSE but is not tailored specifically for LaunchDarkly's feature flag service.
This library is a pure JavaScript implementation of the EventSource client. The API aims to be W3C compatible.
You can use it with Node.js, or as a browser polyfill for
browsers that don't have native EventSource
support. However, the current implementation is inefficient in a browser due to the use of Node API shims, and is not recommended for use as a polyfill; a future release will improve this.
This is a fork of the original EventSource project by Aslak Hellesøy, with additions to support the requirements of the LaunchDarkly SDKs. Note that as described in the changelog, the API is not backward-compatible with the original package, although it can be used with minimal changes.
npm install launchdarkly-eventsource
npm install
node ./example/sse-server.js
node ./example/sse-client.js # Node.js client
open http://localhost:8080 # Browser client - both native and polyfill
curl http://localhost:8080/sse # Enjoy the simplicity of SSE
Just add example/eventsource-polyfill.js
file to your web page:
<script src="/eventsource-polyfill.js"></script>
Now you will have two global constructors:
window.EventSourcePolyfill
window.EventSource // Unchanged if browser has defined it. Otherwise, same as window.EventSourcePolyfill
If you're using webpack or browserify
you can of course build your own. (The example/eventsource-polyfill.js
is built with webpack).
All configurable extended behaviors use the optional eventSourceInitDict
argument to the EventSource
constructor. For instance:
var eventSourceInitDict = { initialRetryDelayMillis: 1000, maxRetryDelayMillis: 30000 };
var es = new EventSource(url, eventSourceInitDict);
In a browser that is using native EventSource
the extra argument would simply be ignored, so any code that will run in a browser, if it might or might not be using this polyfill, should assume that these options might or might be used.
Like the standard EventSource
, this implementation emits the event open
when a stream has been started and error
when a stream has failed for any reason. All events have a single parameter which is an instance of the Event
class.
The open
event has the following extended behavior: the event object will have a headers
property which is an object representing the HTTP response headers received when opening the stream. For example:
{
'content-type': 'text/event-stream; charset=utf-8',
'transfer-encoding': 'chunked',
'connection': 'close',
'accept-ranges': 'bytes',
'cache-control': 'no-cache, no-store, must-revalidate',
}
The error
event has the following extended behavior: for an HTTP error response, the event object will have a status
property (such as 401
) and optionally a message
property (such as "Unauthorized"
).
es.onerror = function (err) {
if (err) {
if (err.status === 401 || err.status === 403) {
console.log('not authorized');
}
}
};
The following additional events may be emitted:
closed
: The stream has been permanently closed, either due to a non-retryable error or because close()
was called.end
: The server ended the stream. For backward compatibility, this is not reported as an error
, but it is still treated as one in terms of the retry logic.retrying
: After an error, this indicates that EventSource
will try to reconnect after some delay. The event object's delayMillis
property indicates the delay in milliseconds.By default, EventSource
automatically attempts to reconnect if a connection attempt fails or if an existing connection is broken. To prevent a flood of requests, there is always a delay before retrying the connection; the default value for this is 1000 milliseconds.
For backward compatibility, the default behavior is to use the same delay each time. However, it is highly recommended that you enable both exponential backoff (the delay doubles on each successive retry, up to a configurable maximum) and jitter (a random amount is subtracted from each delay), so that if a server outage causes clients to all lose their connections at the same time they will not all retry at the same time. The backoff can also be configured to reset back to the initial delay if the stream has remained active for some amount of time.
var eventSourceInitDict = {
initialRetryDelayMillis: 2000, // sets initial retry delay to 2 seconds
maxBackoffMillis: 30000, // enables backoff, with a maximum of 30 seconds
retryResetIntervalMillis: 60000, // backoff will reset to initial level if stream got an event at least 60 seconds before failing
jitterRatio: 0.5 // each delay will be reduced by a randomized jitter of up to 50%
};
By default, to mimic the behavior of built-in browser EventSource
implementations, EventSource
will retry if a connection cannot be made or if the connection is broken (using whatever retry behavior you have configured, as described above)-- but if it connects and receives an HTTP error status, it will only retry for statuses 500, 502, 503, or 504; otherwise it will just raise an error
event and disconnect, so the application is responsible for starting a new connection.
If you set the option errorFilter
to a function that receives an Error
object and returns true
or false
, then EventSource
will call it for any error-- either an HTTP error or an I/O error. If the function returns true
, it will proceed with retrying the connection; if it returns false
, it will end the connection and raise an error
event. In this example, connections will always be retried unless there is a 401 error:
var eventSourceInitDict = {
errorFilter: function(e) {
return e.status !== 401;
}
};
HTTP redirect responses (301/307) with a valid Location
header are not considered errors, and are always immediately retried with the new URL.
You can define custom HTTP headers for the initial HTTP request. This can be useful for e.g. sending cookies or to specify an initial Last-Event-ID
value.
HTTP headers are defined by assigning a headers
attribute to the optional eventSourceInitDict
argument:
var eventSourceInitDict = { headers: { Cookie: 'test=test' } };
Normally, EventSource will always add the headers Cache-Control: no-cache
(since an SSE stream should always contain live content, not cached content), and Accept: text/event-stream
. This could cause problems if you are making a cross-origin request, since CORS has restrictions on what headers can be sent. To turn off the default headers, so that it will only send the headers you specify, set the skipDefaultHeaders
option to true
:
var eventSourceInitDict = {
headers: { Cookie: 'test=test' },
skipDefaultHeaders: true
};
By default, EventSource makes a GET
request. You can specify a different HTTP verb and/or a request body:
var eventSourceInitDict = { method: 'POST', body: 'n=100' };
TCP connections can sometimes fail without the client detecting an I/O error, in which case EventSource could hang forever waiting for events. Setting a readTimeoutMillis
will cause EventSource to drop and retry the connection if that number of milliseconds ever elapses without receiving any new data from the server. If the server is known to send any "heartbeat" data at regular intervals (such as a :
comment line, which is ignored in SSE) to indicate that the connection is still alive, set the read timeout to some number longer than that interval.
var eventSourceInitDict = { readTimeoutMillis: 30000 };
In Node.js, you can customize the behavior of HTTPS requests by specifying, for instance, additional trusted CA certificates. You may use any of the special TLS options supported by Node's tls.connect()
and tls.createSecureContext()
(depending on what version of Node you are using) by putting them in an object in the https
property of your configuration:
var eventSourceInitDict = {
https: {
rejectUnauthorized: false // causes requests to succeed even if the certificate cannot be validated
}
};
This only works in Node.js, not in a browser.
You can define a proxy
option for the HTTP request to be used. This is typically useful if you are behind a corporate firewall.
var eventSourceInitDict = { proxy: 'http://your.proxy.com' };
In Node.js, you can also set the agent
option to use a tunneling agent.
In cases where the EventSource implementation is determined at runtime (for instance, if you are in a browser that may or may not have native support for EventSource, and you are only loading this polyfill if there is no native support), you may want to know ahead of time whether certain nonstandard features are available or not.
The special property EventSource.supportedOptions
is an object containing a true
value for each property name that is allowed in the constructor parameters. If EventSource.supportedOptions.somePropertyName
is true, then you are using a version of this polyfill that supports the somePropertyName
option. If EventSource.supportedOptions.somePropertyName
is false or undefined, or if EventSource.supportedOptions
does not exist, then you are using either an older version of the polyfill, or some completely different EventSource implementation.
For instance, if you want to use the POST
method-- which built-in EventSource implementations in browsers cannot do-- but you do not know for sure whether the current EventSource is this polyfill or a built-in browser version, you should check first whether that option is supported; otherwise, if it's the browser version, it will simply ignore the method option and do a GET
request instead which probably won't work. So your logic might look like this:
if (EventSource.supportedOptions && EventSource.supportedOptions.method) {
var es = new EventSource(url, { method: 'POST' });
} else {
// do whatever you want to do if you can't do a POST request
}
MIT-licensed. See LICENSE.
FAQs
Fork of eventsource package - W3C compliant EventSource client for Node.js and browser (polyfill)
The npm package launchdarkly-eventsource receives a total of 1,618,165 weekly downloads. As such, launchdarkly-eventsource popularity was classified as popular.
We found that launchdarkly-eventsource demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Socket CEO Feross Aboukhadijeh joins Risky Business Weekly to unpack recent npm phishing attacks, their limited impact, and the risks if attackers get smarter.
Product
Socket’s new Tier 1 Reachability filters out up to 80% of irrelevant CVEs, so security teams can focus on the vulnerabilities that matter.
Research
/Security News
Ongoing npm supply chain attack spreads to DuckDB: multiple packages compromised with the same wallet-drainer malware.