0

so I want to add some functionality to an already existing site, this is to make my life easier. One of the things I need that I can't seem to figure out is: how to capture the body payload data a specific outgoing "POST" request. I found the code to do it before but didn't save it and I been searching for that code for 2 days to no avail.

So here is an example of the request the site is making to server.

fetch("https://my.site/api/req", {"credentials":"include","headers":{"accept":"*/*","content-type":"application/json"},"referrerPolicy":"no-referrer-when-downgrade","body":"{\"symbol\":\"mySYM\",\"results\":[{\"data\":{\"id\":\"dataID\"},\"result\":\"signature\"}]}","method":"POST","mode":"cors"});

and the part I need to catch is the "body" portion and then unescape it so it looks like this.

{"symbol":"mySYM","results":[{"data":{"id":"dataID"},"result":"signature"}]}

Also, if possible I would like to have it only catch data when the method = POST and requests going to a specific URL, so it will catch /api/req/ and not pay attention to other URL's and/or when the method is = GET, HEAD.

Currently, I manually get the data from the request using dev tools and clicking on the correct request then scrolling down to find the POST data.

In case you need to know the reason for this. The server signs the data through the websocket connection and I am essentially trying to capture that signature to be able to replay it. I am not trying to catch the websocket data as its incomplete for my needs I need to catch the whole outgoing request body data.

Thanks in advance.

cigol on
  • 337
  • 3
  • 12
  • It’s unclear why you can’t just get the request body from within your own existing JavaScript code. Your code is calling the fetch method with the request body as one of parameters in the fetch invocation. So why can’t you just have your own JavaScript code get the request body from wherever your existing code is getting it now in order to pass it to the fetch invocation? – sideshowbarker Jun 22 '19 at 14:05
  • Its not my code. like I said its an existing site. The original code that compiles the request body and passes it to the fetch request is pre-existing. The rest of my code works perfectly and I'm just trying to automate some things that I do manually. I am adding code and injecting it into the site to make some things I do much easier to do. It functions fine currently but I want to automate the process of getting the request body data. – cigol on Jun 22 '19 at 15:04
  • I am willing to accept a generalized Catch-ALL outgoing requests body from every fetch request sent to server. I know it can be done because I had the code before. I just cant find it again. if its not possible, how about getting the request payload for all XMLHttpRequests? I think I can modify that to fit my needs. There should be an easy way to catch outgoing headers and such right? similar to the way devtools do it in the network tab for chrome? – cigol on Jun 22 '19 at 17:09

2 Answers2

2

Chosen Solution:

Thanks @thirtydot for your responses. Note that my specific situation involved only fetch requests so that is the reason I went with this route. With your response, a bit of more of my own research, and the help of this post I came up with this solution. Since I don't really care to see the responses (I have other functions taking care of the responses which are important to me.).

const constantMock = window.fetch;
 window.fetch = function() {
    if (arguments[0] === '/api/req' && arguments[1].method === 'post'){
        bodyResults(arguments[1].body)
    }
    return constantMock.apply(this, arguments)
 }


function bodyResults(reqBody){
    console.log(reqBody)
}

which put the following in console (Exactly as I wanted).

{"symbol":"NEON","results":[{"data":{"expires_at":"1561273300","id":"2469c8dd"},"signature":"6d712b9fbb22469c8dd240be13a2c261c7af0dfbe3328469eeadbf6cda00475c"}]}

except now I can return this data through that function and continue to run the rest of my script fully automated.

Extra Solution:

In case there are others struggling with similar issues and care to catch the responses of those fetch requests I could have alternatively used:

const constMock = window.fetch;
window.fetch = function() {
    if (arguments[0] === '/api/req' && arguments[1].method === 'post'){
        bodyResults(arguments[1].body)
    }

    return new Promise((resolve, reject) => {
        constantMock.apply(this, arguments)
            .then((response) => {
                if(response.url.indexOf("/me") > -1 && response.type != "cors"){
                    console.log(response);
                    // do something for specificconditions
                }
                resolve(response);
            })
            .catch((error) => {
                reject(response);
            })
    });
}

function bodyResults(reqBody){
    console.log(reqBody)
}

Possible XHR Solution

NOTE: this one is untested! An alternative Solution for XHR requests could be done similarly using something along the lines of:

(function(open) {
  XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {
    alert('Intercept');
    open.call(this, method, url+".ua", async, user, pass);
  };
})(XMLHttpRequest.prototype.open);

Hope this helps!

cigol on
  • 337
  • 3
  • 12
1

So I came across this today and I'm not quite sure if its exactly what you've been looking for over 2 years ago, but solved my problem and I thought I should share it if others needed.

I'm currently using a marketing automation tool which is quite limiting when it comes to landing pages, but I wanted the client to be able to update the content whenever needed and still have access to custom functionality, so I needed the payload which was being sent by the form submission.

Here is what I used to get the form submission payload:

(function() {
    var origOpen = XMLHttpRequest.prototype.send;
    XMLHttpRequest.prototype.send = function() {
        console.log('request started!');
        console.log(arguments[0]);
        this.addEventListener('load', function() {
            console.log('request completed!');
            console.log(this.status);
        });
        origOpen.apply(this, arguments);
    };
})();

The arguments[0] piece is actually the JSON sent as the payload, and the status code is the response (200), stating the request was successfull.

I partially used code from this other response here: https://stackoverflow.com/a/27363569/1576797

Fogolin
  • 41
  • 2