With ajax requests it can be done with this code:
let oldXHROpen = window.XMLHttpRequest.prototype.open;
window.lastXhr = '';
window.XMLHttpRequest.prototype.open = function(method, url, async, user, password) {
this.addEventListener('load', function() {
window.lastXhr = this.responseText;
});
return oldXHROpen.apply(this, arguments);
};
lastXhr
variable will hold the last response.
But how can this be achieved for websockets too?
you would need to make this wrapper as soon as possible
For that answer @brunoff you're correct.. and you can always use your functions before server's by puppet window logic, OR you can hijack the data
from MessageEvent
itself
function listen(fn){
fn=fn||console.log
let property=Object.getOwnPropertyDescriptor
(MessageEvent.prototype,"data")
const data=property.get
function lookAtMessage(){ //to replace get function
let socket=this.currentTarget instanceof WebSocket
if(!socket){return data.call(this)}
let msg=data.call(this)
Object.defineProperty(this,"data",{value:msg}) //anti-loop
fn({data:msg,socket:this.currentTarget,event:this})
return msg
}
property.get=lookAtMessage
Object.defineProperty
(MessageEvent.prototype,"data",property)
}
listen( ({data})=>console.log(data) )
You can try putting in the code and running it in the console on this page and then running their websocket example
To intercept the messages, you will have to spy on the onmessage = fn
and addEventListener("message", fn)
calls.
To be able to modify the onmessage
we have to override the global WebSocket
in the first place. The below is intercepting the incoming messages, but in a similar way you can spy on the send
method to intercept the outgoing messages (the ones sent by the client to the server).
I tested this on a page using Firebase and it works nicely, but you have to initialize it before the other scripts making sure that the websocket library (it can be socket.io, ws, etc) is using the overridden WebSocket
constructor.
data
Eventually you can override the data
before calling the real message listener – this becomes handy if you do not have control over the page functionality and want to inject your own data in the message listener.
const OriginalWebsocket = window.WebSocket
const ProxiedWebSocket = function() {
console.log("Intercepting web socket creation")
const ws = new OriginalWebsocket(...arguments)
const originalAddEventListener = ws.addEventListener
const proxiedAddEventListener = function() {
if (arguments[0] === "message") {
const cb = arguments[1]
arguments[1] = function() {
// Here you can get the actual data from the incoming messages
// Here you can even change the data before calling the real message listener
Object.defineProperty(e, "data", { value: 'your injected data' })
console.log("intercepted", arguments[0].data)
return cb.apply(this, arguments)
}
}
return originalAddEventListener.apply(this, arguments)
}
ws.addEventListener = proxiedAddEventListener
Object.defineProperty(ws, "onmessage", {
set(func) {
return proxiedAddEventListener.apply(this, [
"message",
func,
false
]);
}
});
return ws;
};
window.WebSocket = ProxiedWebSocket;
If you do not need to modify the data, you can follow the second part of the answer.
If you want to listen for messages only, without overriding the data, things are simpler:
const OriginalWebsocket = window.WebSocket
const ProxiedWebSocket = function() {
const ws = new OriginalWebsocket(...arguments)
ws.addEventListener("message", function (e) {
// Only intercept
console.log(e.data)
})
return ws;
};
window.WebSocket = ProxiedWebSocket;
In a very similar way, you can proxy the send
method which is used to send data to the server.
const OriginalWebsocket = window.WebSocket
const ProxiedWebSocket = function() {
const ws = new OriginalWebsocket(...arguments)
const originalSend = ws.send
const proxiedSend = function() {
console.log("Intercepted outgoing ws message", arguments)
// Eventually change the sent data
// arguments[0] = ...
// arguments[1] = ...
return originalSend.apply(this, arguments)
}
ws.send = proxiedSend
return ws;
};
window.WebSocket = ProxiedWebSocket;
Feel free to ask any questions if anything is unclear.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With