Repository: node
Issue: responses corresponding to requests queued by http agent are attached to incorrect domain
Labels: help wanted,http,domain

<!--
Thank you for reporting a possible bug in Node.js.

Please fill in as much of the template below as you can.

Version: output of `node -v`
Platform: output of `uname -a` (UNIX), or version and 32 or 64-bit (Windows)
Subsystem: if known, please specify the affected core module name

If possible, please provide code that demonstrates the problem, keeping it as
simple and free of external dependencies as you can.
-->

* **Version**: Current tip of master (cf9bcdeabe), but possibly most versions.
* **Platform**: All platforms.
* **Subsystem**: domain, http.

<!-- Please provide more details below this comment. -->

Running the following code:

```
'use strict';

const common = require('../common');
const domain = require('domain');
const http = require('http');

const server = http.createServer((req, res) => {
    res.end();
});

function performHttpRequestWithDomain(domainId, agent, cb) {
    const d = domain.create();
    d._id = domainId;
    d.run(() => {
        const req = http.get({
            host: '127.0.0.1', port: server.address().port, agent
        }, res => {
            if (req.domain._id !== domainId) {
                console.log('req.domain._id !== domainId');
                console.log('req.domain._id:', req.domain._id);
                console.log('domainId:', domainId);
                process.exit(1);
            }

            if (req.domain._id !== res.domain._id) {
		        console.log('req.domain._id !== res.domain._id');
                console.log('req.domain._id:', req.domain._id);
                console.log('res.domain._id:', res.domain._id);
                process.exit(1);
            }

            res.on('data', () => {});
            res.on('end', cb);
        });

        req.end();
    });

    d.on('error', (domainErr) => {
        console.log('got domain error:', domainErr);
        process.exit(1);
    });
}

server.listen(0, '127.0.0.1', () => {
    const agent = new http.Agent({maxSockets: 1});
    let nbReqComplete = 0;

    function maybeCloseServer() {
        if (nbReqComplete === 2) {
            server.close();
        }
    }

    performHttpRequestWithDomain(1, agent, common.mustCall(() => {
        ++nbReqComplete;
        maybeCloseServer();
    }));

    performHttpRequestWithDomain(2, agent, common.mustCall(() => {
        ++nbReqComplete;
        maybeCloseServer();
    }));
});
```

exits with a status code of 1 when I'd expect it to exit with a status code of 0:

```
$ ./node test/parallel/test-agent-queued-request-domain.js 
req.domain._id !== res.domain._id
req.domain._id: 2
res.domain._id: 1
$ echo $?
1
$ 
```

In this repro, we basically force the http agent to queue the second request. When the first request finishes, [the second request is assigned a socket from the agent's `'free'` event handler](https://github.com/nodejs/node/blob/91ef9c4c3f7d8acc21ad934dd520071b8bdfcab8/lib/_http_agent.js#L70).

However, it seems that event handler's execution is [scheduled from within the lifecycle of the first request](https://github.com/nodejs/node/blob/91ef9c4c3f7d8acc21ad934dd520071b8bdfcab8/lib/_http_client.js#L601), and thus its active domain is the one of the first request.

As a result, when the parser for the response is instantiated and [its corresponding async resource is initialized](https://github.com/nodejs/node/blob/91ef9c4c3f7d8acc21ad934dd520071b8bdfcab8/lib/domain.js#L53-L59), it is attached to the first request's domain, and not to the active domain when the http request was originally created.

I'll see if I can put together a PR that fixes this.