21
votes

Regular client initiated requests to the node server are captured fine in Fiddler. However, requests sent from node to a web service are not captured. It did not help to pass in config for proxy (127.0.0.1:8888) to the request method. How can I route the request messages through Fiddler?

var http = require('http');
var request = require('request');

request.get(webserviceURL, { "auth" : {"user": "user", "pass" = "pass", sendImmediately: true },
"proxy" : { "host" : "127.0.0.1", "port" : 8888 }},
function (error, response) { console.log( "response received" );
});

Request repo: https://github.com/mikeal/request

5
Setting the proxy on the request object should be all you need to do, but I don't see a "proxy" property in the docs? nodejs.org/api/http.html#http_http_request_options_callbackEricLaw
I'm using the third-party request package. Link in description.mupersan82
Poking around in the source, it seems to imply that the syntax would be "hostname" rather than "host"? Or you could define proxy as the string "127.0.0.1:8888" rather than as an object?EricLaw
Changing "host" to "hostname" did not help. Can you get it working?mupersan82

5 Answers

26
votes

I just tried to do this myself (using Fiddler and the request library from npm). Here's how I got it working:

process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0'; // Ignore 'UNABLE_TO_VERIFY_LEAF_SIGNATURE' authorization error

// Issue the request
request(
{
    method: "GET",
    uri: "https://secure.somewebsite.com/",
    proxy: "http://127.0.0.1:8888" // Note the fully-qualified path to Fiddler proxy. No "https" is required, even for https connections to outside.
},
function(err, response, body) {
    console.log("done");
});

This is with Fiddler2 using the default port and proxy options (and no proxy authentication).

5
votes

Fiddler works by setting your "Internet Options" (from start menu) "Connections" > "LAN Settings" > "Proxy Server" to its port, thus making all HTTP traffic (clients which obey this setting) go through it.

You should point your node.js client lib to use a proxy, the settings are written in that options dialog after you start Fiddler.

4
votes

The proxy option should be a full url, like this:

proxy : "http://127.0.0.1:8888"
3
votes

To do this on an ad-hoc basis, without changing your code, you can use environment variables.

Request respects:

  • HTTP_PROXY
  • HTTPS_PROXY
  • NO_PROXY

So, to proxy just set these in your console before running your process.

For example, to setup http and https proxy use:

set HTTP_PROXY="http://127.0.0.1:8888"
set HTTPS_PROXY="http://127.0.0.1:8888"
set NODE_TLS_REJECT_UNAUTHORIZED=0

The latter line stops issues with SSL through the fiddler proxy.

0
votes

I've been wanting the same... an equivalent of the Network tab in chrome DevTools, only for Nodejs. Unfortunately, it doesn't appear as though one exists. I don't have Fiddler on macos, so this is how I went about stubbing the require('http') methods to log and pass though. Leaving this here in case I need it again or someone else finds it helpful. You can turn it on by attaching a debugger and require('filename')() the file containing this script.

module.exports = () => {
    const http = require('http');
    http._request = http.request;

    global.DO_LOG_AJAX = true;
    const log = str => {
        if (global.DO_LOG_AJAX) {
            console.debug(str);
        }
    };

    const flushLog = (requestLines, responseLines) => {
        if (global.DO_LOG_AJAX) {
            log([
                '----------------Begin Request-----------------------------------',
                ...requestLines,
                '----------------End Request / Begin Response--------------------',
                ...responseLines,
                '----------------End Reponse-------------------------------------',
            ].join('\n'));
        }
    };

    let write;
    let end;
    http.request = (...requestParams) => {
        const req = http._request(...requestParams);
        const { method, path, headers, host, port } = requestParams[0];
        const requestLogLines = [];
        requestLogLines.push(`${method} ${path}`);
        requestLogLines.push(`Host: ${host}:${port}`);
        for (const header of Object.keys(headers)) {
            requestLogLines.push(`${header}: ${headers[header]}`);
        }
        write = write || req.write;
        end = end || req.end;

        req.on('error', err => {
            log({ err });
        });

        req._write = write;
        req._end = end;
        const requestBody = [];
        req.write = (...writeParams) => {
            requestBody.push(writeParams[0].toString());
            return req._write(...writeParams);
        };
        req.end = (...endParams) => {
            if (endParams[0]) {
                requestBody.push(endParams[0].toString());
            }
            requestLogLines.push('');
            requestLogLines.push(requestBody.join(''));
            return req._end(...endParams);
        };

        const responseLogLines = [];
        req.once('response', response => {
            const responseBody = [];
            responseLogLines.push(`${response.statusCode} ${response.statusMessage}`);
            for (const header of Object.keys(response.headers)) {
                responseLogLines.push(`${header}: ${response.headers[header]}`);
            }
            const onData = chunk => {
                responseBody.push(chunk.toString());
            };
            const onClose = err => {
                responseLogLines.push('');
                responseLogLines.push(responseBody.join(''));
                responseLogLines.push('');
                responseLogLines.push(`--- ERROR --- ${err.toString()}`);
                flushLog(requestLogLines, responseLogLines);
                req.removeListener('data', onData);
            };
            const onEnd = () => {
                responseLogLines.push('');
                responseLogLines.push(responseBody.join(''));
                flushLog(requestLogLines, responseLogLines);
                req.removeListener('data', onData);
            };
            response.on('data', onData);
            response.once('close', onClose);
            response.once('end', onEnd);
        });

        return req;
    };
};