How to intercept all http requests including form submits
Asked Answered
P

3

63

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

Presume answered 5/5, 2017 at 21:9 Comment(5)
I don't think Javascript can intercept regular form submits. You can capture the submit event and then send the form using AJAX instead.Firstnighter
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.Kissable
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?Presume
Perhaps. the class selector in Jquery might work for me! Thanks!Presume
@Presume 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.Firstnighter
S
65

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:

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, you need to:

  1. Serialize the request.
  2. Modify that serialized request.
  3. Deserialize the modified request to create a new request.
  4. Call fetch(…) with that new request.

So, 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://mcmap.net/q/323210/-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

Scheming answered 6/5, 2017 at 1:31 Comment(3)
this was so cool, I have what i need to fix my issues. The next second I check this and the dearest of all - IE & Edge :) god bless themBaier
Is a service worker another name for a web worker or are they different?Asthenosphere
is it track a api calls when is triggering in a page with a iframe? and if the call going to other domain(sso) and come back to same domain(is it intercept that api too?)Yount
I
6

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);
Intent answered 14/11, 2017 at 9:38 Comment(3)
That does not intercept form submits.Sacttler
This is not intercepting a simple fetch request.Zachary
Of course it's not intercepting a fetch call, this is plainly XHR, they are different things.Noetic
Y
4
// Override the open method of XMLHttpRequest to intercept all requests
var originalOpen = XMLHttpRequest.prototype.open;

XMLHttpRequest.prototype.open = function(method, url) {
  console.log("Intercepted HTTP request: " + method + " " + url);
  originalOpen.apply(this, arguments);
};
Yajairayajurveda answered 5/3, 2023 at 11:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.