35

I would like to intercept all http requests going out from my web page and add a parameter to the request body. My page includes forms - I also want to capture form submits. I have tried using Jquery ajaxSend and Javascript's setRequestHeader but both did not work for me. How do I achieve this?

Thanks

lenniekid
  • 531
  • 1
  • 7
  • 16
  • 1
    I don't think Javascript can intercept regular form submits. You can capture the submit event and then send the form using AJAX instead. – Barmar May 05 '17 at 21:10
  • 1
    You can capture a form submit and insert an input into the form. As far as ajax requests go, global ajax events work if you're only using jquery. No one solution is going to solve the problem. – Kevin B May 05 '17 at 21:12
  • 1
    In my case, the pages are being generated using Apache velocity view templates - this means every page is generated by combining the page template with the header template. There are many pages and I want all pages to be able to send a token to the server. The only way seems to achieve this seems to be adding code to the header to intercept the request. So the solutions suggested would not work. Is there any other way? – lenniekid May 05 '17 at 21:13
  • Perhaps. the class selector in Jquery might work for me! Thanks! – lenniekid May 05 '17 at 21:21
  • @lenniekid You want to add a parameter to the request body or the request header? If it's the body, you can add a hidden form field as suggested above. – Barmar May 05 '17 at 21:40

2 Answers2

39

https://developer.mozilla.org/en/docs/Web/API/Service_Worker_API

Service workers essentially act as proxy servers that sit between web applications, and the browser and network (when available).

It takes the form of a JavaScript file that can control the web page/site it is associated with, intercepting and modifying navigation and resource requests

You register a service worker in your application code from a file named, e.g., sw.js by doing this:

if ('serviceWorker' in navigator) {
  window.addEventListener('load', function() {
    navigator.serviceWorker.register('sw.js').then(function(registration) {
      console.log('Service worker registered with scope: ', registration.scope);
    }, function(err) {
      console.log('ServiceWorker registration failed: ', err);
    });
  });
}

And in the sw.js file (the actual service-worker code): To intercept requests, you attach a fetch event listener to the service worker that calls the respondWith() method and does something with the .request member from the event object:

self.addEventListener('fetch', function(event) {
  event.respondWith(
    // intercept requests by handling event.request here
  );
});

A simple service worker that just passes through requests unchanged looks like this:

self.addEventListener('fetch', function(event) {
  event.respondWith(
    fetch(event.request)
  );
});

To add a param to the request body, I think you need to serialize the request, modify that serialized request, then deserialize it to recreate a new request, then call fetch(…) with that new request.

So I think a service worker that does all that would look like this (untested):

self.addEventListener('fetch', function(event) {
  event.respondWith(
    fetchWithParamAddedToRequestBody(event.request)
  );
});
function fetchWithParamAddedToRequestBody(request) {
  serialize(request).then(function(serialized) {
    // modify serialized.body here to add your request parameter
    deserialize(serialized).then(function(request) {
      return fetch(request);
    });
  }); // fixed this
}
function serialize(request) {
  var headers = {};
  for (var entry of request.headers.entries()) {
    headers[entry[0]] = entry[1];
  }
  var serialized = {
    url: request.url,
    headers: headers,
    method: request.method,
    mode: request.mode,
    credentials: request.credentials,
    cache: request.cache,
    redirect: request.redirect,
    referrer: request.referrer
  };  
  if (request.method !== 'GET' && request.method !== 'HEAD') {
    return request.clone().text().then(function(body) {
      serialized.body = body;
      return Promise.resolve(serialized);
    });
  }
  return Promise.resolve(serialized);
}
function deserialize(data) {
  return Promise.resolve(new Request(data.url, data));
}

Note: https://serviceworke.rs/request-deferrer_service-worker_doc.html, a page from the Service Worker Cookbook, is where I lifted that serialize(…) code/approach from—by way of the answer at https://stackoverflow.com/questions/35420980/how-to-alter-the-headers-of-a-request/35421644#35421644—and it’s worth taking a look at, because the code there has detailed annotations explaining what it’s all doing

Rehmat
  • 1,437
  • 17
  • 23
sideshowbarker
  • 62,215
  • 21
  • 143
  • 153
4

try this code :

(function(send) {

XMLHttpRequest.prototype.send = function(data) {

    var _valuToAdd = $("input[name='valuToAdd']").val();
    this.setRequestHeader('valueName', _valuToAdd);
    send.call(this, data);
};
})(XMLHttpRequest.prototype.send);
abdelhadi
  • 137
  • 2
  • 5