joeferner / node-http-mitm-proxy

HTTP Man In The Middle (MITM) Proxy
660 stars 163 forks source link

proxy.close() does not close the proxy completely - which make the test suite hang after test completion. #184

Open hjain60 opened 5 years ago

hjain60 commented 5 years ago

Hi,

I am running a test using mocha, selenium-webdriver and http-mitm-proxy.

I set proxy using selenium to divert https traffic to the mitm-proxy. After my test cases are done, I call proxy.close() in after() method to close proxy. However, whenever any https traffic is sent to the proxy, the proxy does not get closed.

I tried to manually kill all the ports and close ssl servers however still no luck.

stop: function () {
    if (process.env.NODE_ENV && process.env.NODE_ENV === 'local') {
      Utils.resetSystemProxy(proxySet);
    }

    if (proxy) {
      try {

        console.log(proxy.sslServers);
        (Object.keys(proxy.sslServers)).forEach(function (srvName) {
          console.log(srvName);
          killPort(proxy.sslServers[srvName].port);
          proxy.sslServers[srvName].server.close();
          delete proxy.sslServers[srvName];
          console.log('HTTPS Server: "' + srvName + '" closed.');
        });

        killPort(proxy.options.port);
        proxy.close();
      } catch (e) {
        Logger.warn('Unable to close Proxy Server' + e.message);
      }
    }

    Logger.info('returning controll....');
    return 0;
  }

I would really appreciate any help as I am completely stuck and cannot run my test cases in CI/CD env.

freewil commented 5 years ago

While proxy.close() should be fixed so it doesn't cause the process to continue running, an easy fix is to just use mocha --exit or just call process.exit() yourself.

hjain60 commented 5 years ago

Hi freewil - I am using the mocha -exit flag however not everyone uses mocha. In case of nightwatch tests for iOS this is causing the issue.

Would appreciate if this could be fixed.

bjowes commented 5 years ago

Hi @hjain60 - I have experienced something similar.

Are you using keep-alive? Keep-alive agents won't drop their connections on proxy.close(). In this case you could pass in your own agent as an option to the proxy, and then do agent.destroy() when you are done.

Also, I just added #194 which could be interesting for you. It provides a callback from proxy.close() when all connections have been closed.

bjowes commented 5 years ago

194 is a bit delayed due to testing issues. But #196 was just merged and that one helps in some scenarios when the proxy wouldn’t quit. Try it out.

Apollon77 commented 3 years ago

I still expereince this issue in the most current npm version ... so in fact both mentioned PRs are merged and I expect also released ... anyone have an idea?

bjowes commented 3 years ago

It might help to know that the proxy acts just like the Node HttpServer on close - it stops accepting new incoming connections, but keeps executing until all ongoing connections have been terminated. The close call does not initiate closing of connections. Try to make your clients kill their connections.

Apollon77 commented 3 years ago

Ok, but in the end thats not that "end user friendly" ;-)) But if it is that way ... should it then not work to destroy the sockets on close? Effectively I added already the following to proxy.onRequest:

                ctx.onResponse((ctx, callback) => {
                    ctx.proxyToServerRequest.socket.once('close', () => {
                        ctx.clientToProxyRequest.socket.destroy()
                    });
                    return callback();
                });

But it seems not enough ...

Or do I need to "collect" all sockets from all sorts and destroy them all by myself on close? What would be the best place for that?

bjowes commented 3 years ago

Maybe a new issue would be better to discuss this further. I would need some more info about your use case (what are the clients and what are the servers) to give some recommendation.

I think the code you added shouldn't be needed. It will forward a socket close event from the socket between the proxy and the server by destroying the socket between the client and the proxy. Generally this would be taken care of by the applications without this custom code. To clarify - calling close() on the proxy will not close the "proxy to server" sockets. Such a close would need to be initiated by the server.