A library to easily intercept, modify, and simulate EventSource server-sent events.
Table of Contents
- Intercept new connections
- Change connection URL
- Intercept incoming events
- Modify events (data, origin, id, etc.)
- Block events
- Simulate incoming events
Install with npm:
npm install --save event-source-hookInstall in a browser:
- download file
browser/eshook.jsorbrowser/eshook.min.js - import it on your web page
Note: these scripts are polyfilled, so it should run on every browser supporting EventSource API.
EventSource before other libraries or code instantiate it.
This applies the patch to the native EventSource constructor.
View code
In Node:
import ESHook from "event-source-hook";
ESHook.enable();In a browser:
// In a browser, the library object is exposed globally.
ESHook.enable();Attach a hook function to listen each new opening connection. You can save EventSource instances for later use if you wish.
View code
const connections = [];
ESHook.createHook = (eventSource) => {
console.log("New connection:", eventSource);
connections.push(eventSource);
};Attach a hook function to change a connection URL just before a new connection is established.
View code
ESHook.urlHook = (url) => {
if (url === "http://a-url") {
url = "http://new-url";
}
return url;
};You can simulate an incoming MessageEvent. It will be handled as if it were an genuine event received from the server.
It is required to specify on which connection you want to simulate the event.
View code
// Connection where the event should be received.
const eventSource = connections[0];
// Event type: can be anything.
const type = "message";
// Event options.
// See: https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent/MessageEvent#options
const options = {
data: { foo: "bar" },
lastEventId: "id",
};
ESHook.simulate(eventSource, type, options);Note: the simulated property is set to true on the MessageEvent object. Thus, it is possible to detect the simulated event like in section 4 just below.
Attach a hook function to listen for incoming MessageEvent just before the native EventSource receives them.
Note: the hook function can be synchronous or asynchronous (see, below examples).
You can modify all event object's properties (such as data, lastEventId) as it is mutable.
View code (synchronous)
Return the (modified) event or null to block the event.
EventSourceHook.eventHook = (type, event, eventSource) => {
// Block incoming events with type `message`.
if (type === "message") {
return null;
}
// Modify incoming events data from URL `https://test`.
if (eventSource.url === "https://test") {
const data = JSON.parse(event.data);
data.foo = "new value";
event.data = JSON.stringify(data);
return event;
}
// Detect simulated events.
if (event.simulated) {
console.log("This event was simulated by the library.");
}
// Leave the other events as they are.
return event;
};View code (asynchronous)
To make the hook function asynchronous, include the optional result callback parameter, and call it to return the (modified) event or null to block the event.
Example with a promise:
EventSourceHook.eventHook = (type, event, eventSource, result) => {
// Block incoming events with type `message`.
if (type === "message") {
result(null);
return;
}
// Modify incoming events data from URL `http://test`.
if (eventSource.url === "https://test") {
fetchData().then((data) => {
event.data = JSON.stringify(data);
result(event);
});
return;
}
// Leave the other events as they are.
result(event);
};Example with async/await:
EventSourceHook.eventHook = async (type, event, eventSource, result) => {
const thing = await something();
if (thing) {
event.data = thing;
result(event);
} else {
result(null);
}
};You can disable hooks by setting null.
View code
ESHook.urlHook = null;
ESHook.createHook = null;
ESHook.eventHook = null;
...View API docs.