Created
January 15, 2019 20:18
-
-
Save benjamingr/0433b52559ad61f6746be786525e97e8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function interceptNetworkRequests(ee) { | |
const open = XMLHttpRequest.prototype.open; | |
const send = XMLHttpRequest.prototype.send; | |
const isRegularXHR = open.toString().indexOf('native code') !== -1; | |
// don't hijack if already hijacked - this will mess up with frameworks like Angular with zones | |
// we work if we load first there which we can. | |
if (isRegularXHR) { | |
XMLHttpRequest.prototype.open = function() { | |
ee.onOpen && ee.onOpen(this, arguments); | |
if (ee.onLoad) { | |
this.addEventListener('load', ee.onLoad.bind(ee)); | |
} | |
if (ee.onError) { | |
this.addEventListener('error', ee.onError.bind(ee)); | |
} | |
return open.apply(this, arguments); | |
}; | |
XMLHttpRequest.prototype.send = function() { | |
ee.onSend && ee.onSend(this, arguments); | |
return send.apply(this, arguments); | |
}; | |
} | |
const fetch = window.fetch || ""; | |
// don't hijack twice, if fetch is built with XHR no need to decorate, if already hijacked | |
// then this is dangerous and we opt out | |
const isFetchNative = fetch.toString().indexOf('native code') !== -1; | |
if(isFetchNative) { | |
window.fetch = function () { | |
ee.onFetch && ee.onFetch(arguments); | |
const p = fetch.apply(this, arguments); | |
p.then(ee.onFetchResponse, ee.onFetchError); | |
return p; | |
}; | |
// at the moment, we don't listen to streams which are likely video | |
const json = Response.prototype.json; | |
const text = Response.prototype.text; | |
const blob = Response.prototype.blob; | |
Response.prototype.json = function () { | |
const p = json.apply(this.arguments); | |
p.then(ee.onFetchLoad && ee.onFetchLoad.bind(ee, "json")); | |
return p; | |
}; | |
Response.prototype.text = function () { | |
const p = text.apply(this.arguments); | |
p.then(ee.onFetchLoad && ee.onFetchLoad.bind(ee, "text")); | |
return p; | |
}; | |
Response.prototype.blob = function () { | |
const p = blob.apply(this.arguments); | |
p.then(ee.onFetchLoad && ee.onFetchLoad.bind(ee, "blob")); | |
return p; | |
}; | |
} | |
return ee; | |
} | |
interceptNetworkRequests({ | |
onFetch: console.log, | |
onFetchResponse: console.log, | |
onFetchLoad: console.log, | |
onOpen: console.log, | |
onSend: console.log, | |
onError: console.log, | |
onLoad: console.log | |
}); |
@acerbastimur sure, there are libraries that do this better - this is just a useful trick I use to debug things.
I think netflix has a library for this https://github.com/Netflix/pollyjs
On line 53 (inside the blob prototype) would be good to also get the response headers for blobs. On my use case (not patching on fetch the initial page load) I don't get the onFetchResponse called (I think a lib is caching a copy of fetch somewhere - so this is not doing anything). I do get the Response.prototype.blob function called, but I also need the header to see if this is a network call I want or not.
this.arguments
should be this, arguments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks