Hook all Fetch Api AJAX requests Hook all Fetch Api AJAX requests ajax ajax

Hook all Fetch Api AJAX requests


It is easy to do due to nature of promises:

var taperFunction = response => response;var originalFetch = fetch;fetch = (input, init) => originalFetch(input, init)    .then(response => new Promise((resolve) => {        resolve(taperFunction(response));    }));

and a bit more complex(explicit) example:

var originalFetch = fetch;fetch = (input, init) => {    debugger; // do what ever you want with request or reject it immediately    return originalFetch(input, init).then(response => {        // it is not important to create new Promise in ctor, we can await existing one, then wrap result into new one        return new Promise((resolve) => {            response.clone() // we can invoke `json()` only once, but clone do the trick                .json()                .then(json => {                    debugger; // do what ever you want with response, even `resolve(new Response(body, options));`                    resolve(response);                });        });    });};


In fact, Fetch Api is supported by native browser and only has one interface: fetch.The constructor return one Promise, and you can't get the RequestResponse when you want to return your Promise to rewrite the fetch's constructor.

The following code doesn't work well.

(function() {    var oldFectch = fetch;    fetch.consotructor = function() {        return new Promise(resolve, reject) {            // your hook code        };    };})();

So,Does it mean we can't hook all Fetch Api ? NO!

Firstly, thanks the window.fetch polyfill.

Then, let's do something(edit fetch.js) and rock.

(function(self) {    'use strict';    // comment or delete the following code block    // if (self.fetch) {    //    return    // }    var support = {        searchParams: 'URLSearchParams' in self,        iterable: 'Symbol' in self && 'iterator' in Symbol,        // ...

Last, hook every thing as your better!

self.fetch = function(input, init) {  return new Promise(function(resolve, reject) {    var request = new Request(input, init)    var xhr = new XMLHttpRequest()    // Here we go!    // Now we get the XMLHttpRequest Object    // Do what you want!    xhr.onload = function() {      var options = {        status: xhr.status,        statusText: xhr.statusText,        headers: parseHeaders(xhr.getAllResponseHeaders() || '')      }      options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL')      var body = 'response' in xhr ? xhr.response : xhr.responseText      resolve(new Response(body, options))    }    // ...


Using async and await, it's quite simple:

const oldFetch = window.fetchwindow.fetch = async (input, options) => {    return await oldFetch(input, options)}

An example:

const oldFetch = window.fetchwindow.fetch = async (input, options) => {    // modify the request here    console.log(input)    let response = await oldFetch(input, options)    // modify the response    let content = await response.text()    content = 'goodbye!'    return new Response(content, {        status: response.status,        statusText: response.statusText,        headers: response.headers    })}console.log(await (await fetch('/hello')).text())