Skip to content

Missing response for certain POST requests #12339

Closed
@kanongil

Description

@kanongil
  • Version: 7.8.0 (also affects 4 & 6)
  • Platform: macOS 10.12.4
  • Subsystem: http / net

When a server responds with a short payload to a POST http.request() with a large payload that has not finished uploading, a node client throws an EPIPE error on the request object. E.g. with NODE_DEBUG=http:

HTTP 90220: SOCKET ERROR: write EPIPE Error: write EPIPE
    at exports._errnoException (util.js:1034:11)
    at WriteWrap.afterWrite [as oncomplete] (net.js:812:14)

This destroys the node socket, and the http client never receives the response or any of the payload data.

Expected result

The EPIPE error should be deferred (or possibly just ignored) until the client has had a chance to handle the response and payload.

Serverside workaround

This can be mitigated serverside, by consuming all the uploaded data before sending a response.

Background

I need clients to be able to handle my server responding to POST requests without consuming the entire payload.

Example

I have created a failing example, which when run will trigger the EPIPE error.

To visualise that this is indeed a node bug, I added an ignore_epipe option, which can be set to true, to ignore EPIPE errors on the socket. This results in the client behaving as I expected, properly delivering the response and payload, before emitting an error.

var http = require('http');
var port = 8080;

var ignore_epipe = false;

var upload = function () {

    var req = http.request({
        port: port,
        method: 'POST'
    }, function (res) {

        console.log('received response code', res.statusCode);

        var length = 0

        res.setEncoding('utf8');
        res.on('data', function (chunk) {
            //console.log('BODY: ' + chunk);
            length += chunk.length;
        });
        res.on('end', function () {
            console.log('received ' + length + ' bytes');
        });

        res.on('error', function (err) {

            console.log('got response error', err);
        });
    });

    req.end(new Buffer(10*1024*1024));

    req.on('error', function (err) {

        console.log('got request error', err);
    });

    if (ignore_epipe) {
        req.on('socket', function (socket) {

            var destroy = socket._destroy;
            socket._destroy = function (exception, cb) {

                if (exception && (exception.code === 'EPIPE')) {
                    return;
                }

                return destroy.call(this, exception, cb);
            };
        });
    }
};

// create server

var server = http.createServer(function (req, res) {

    res.end('done');
});

server.listen(port, function (err) {

    if (err) {
        return console.log('something bad happened', err)
    }

    console.log('server is listening on', port);

    upload();
});

Metadata

Metadata

Assignees

No one assigned

    Labels

    httpIssues or PRs related to the http subsystem.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions