nodejs/node

responses corresponding to requests queued by http agent are attached to incorrect domain

Open

#25 460 ouverte le 12 janv. 2019

Voir sur GitHub
 (2 commentaires) (0 réactions) (0 assignés)JavaScript (35 535 forks)batch import
domainhelp wantedhttpstale

Métriques du dépôt

Stars
 (117 218 stars)
Métriques de merge PR
 (Merge moyen 18j 17h) (219 PRs mergées en 30 j)

Description

  • Version: Current tip of master (cf9bcdeabe), but possibly most versions.
  • Platform: All platforms.
  • Subsystem: domain, http.

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.

However, it seems that event handler's execution is scheduled from within the lifecycle of the first request, 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, 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.

Guide contributeur