http-proxy-middleware raising: ERR_CONTENT_LENGTH_MISMATCH

Do you have any idea of why the following code is raising the error: ERR_CONTENT_LENGTH_MISMATCH?

If I set res.setHeader('content-length', 0); then there is no error. Probably because the actual output is empty. Which makes the content-length match the actual output.

If I set res.setHeader('content-length', output.length); then there is an error. Probably because output.length is 40, but the actual output length is: 0.

// run
$ node 01.js

file content: 01.js

var express = require('express');
var http = require('http');
var proxy = require('http-proxy-middleware');

function bodyTransform(body) {
    body = body.replace('is running', 'is now running');
    body = body.replace('3001', '3002');
    return body;
}

var onProxyRes = (proxyRes, req, res) => {

    const _writeHead = res.writeHead;
    const _end = res.end;
    var buffer = new Buffer('');
    let body = '';

    proxyRes.on('data', (chunk) => {
        console.log("inside: .on('data', ...)");
        buffer = Buffer.concat([buffer, chunk]);
    });
    proxyRes.on('end', () => {
        console.log("inside: .on('end', ...)");
        body = buffer.toString('utf8');
    });

    // defer writeHead
    res.writeHead = (...writeHeadArgs) => {
        const output = bodyTransform(body);
        if (proxyRes.headers && proxyRes.headers['content-length']) {
            // if 'content-length' is set to: 'output.length' it causes:
            // ERR_CONTENT_LENGTH_MISMATCH (Google Chrome is explicit about the error)
            // because it seems that the actual content output is an empty string (length: 0)
            res.setHeader('content-length', output.length);
            console.log('assigned => content-length: ' + output.length);

            // if the following line is uncommented, there are no errors
            // because it seems that the actual content output is an empty string (length: 0)
            // so the 'content-length' will match
            // res.setHeader('content-length', 0);
        }
        // disabling chunked encoding
        res.setHeader('transfer-encoding', '');
        // disabling cache for all http as well
        res.setHeader('cache-control', 'no-cache');
        _writeHead.apply(res, writeHeadArgs);
    };

    // defer all writes
    res.write = (chunk) => { };

    res.end = (...endArgs) => {
        const output = bodyTransform(body);
        if (body.length) {
            _end.apply(res, [output]);
        }
        else {
            _end.apply(res, endArgs);
        }
        console.log('after: _end.apply(...);');
    };
}

const portApp01 = 3001;
const app01 = express()
app01.get('/', (req, res) => {
    res.send('This server is running on port: 3001');
});
app01.listen(portApp01, () => {
    console.log('app01 is listening on port: ' + portApp01);
});

const portProxy = 3002;
const appProxy = express()
appProxy.use(proxy('/', { target: 'http://localhost:3001', onProxyRes: onProxyRes }));
http.createServer(appProxy).listen(portProxy, function () {
    console.log('appProxy is listening on port: ' + portProxy);
});

Terminal output:

inside: .on('data', ...)
inside: .on('end', ...)
assigned => content-length: 40
after: _end.apply(...);

I think I'm omitting a very tiny detail.

Do you have any idea on how to make this work?

Thanks.

Answers:

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.