I have got some error when use http.request to make a client request(node v0.6.18, v0.6.3), the following code produces the error and I have some questions.
var http = require('http');
var url = require('url');
http.createServer(function(req, res) {
var data = '多情自古空余恨';
res.writeHead(200, {
'Content-Type': 'text/plain',
'Content-Length': 1 //ERROR
});
res.end(data);
}).listen(3000);
function request(options, callback) {
var req = http.request(options, function(res) {
var data = '';
res.setEncoding = 'utf8';
res.on('data', function(chunk) {
data += chunk;
});
res.on('error', function(err) {
callback(new Error('res error: ' + err));
});
res.on('end', function() {
console.log('res on end');
callback(null, data);
});
});
req.on('socket', function(socket) {
socket.on('error', function(err) {
console.log('socket on error');
callback('socket error: ' + err);
req.abort();
});
});
req.end();
}
request({
host: 'localhost',
port: 3000,
method: 'GET'
}, function(err, data) {
console.log('result, err: ' + err + ', data: ' + data);
});
Outputs:
res on end
result, err: null, data: �
socket on error
result, err: socket error: Error: Parse Error, data: undefined
Here are my questions:
I need your help! Thanks.
===============================
I found the same code outputs:
res on end
result, err: null, data: �
in node v0.6.6 and v0.6.11. Why?
Because there's a content-length header of 1, when the request
receives exactly 1 octet of data, it assumes that's all there is and fires the end
callback. After that, more data is received that the socket doesn't know what to do with, so it fires the error.
To work around this, you could perhaps wait a short period before firing the callback for success and track if it's been fired. For example:
var req = http.request(options, function(res) {
var data = '';
res.setEncoding = 'utf8';
res.on('data', function(chunk) {
data += chunk;
});
res.on('error', function(err) {
if(!callback.called) { // check before firing the callback
callback(new Error('res error: ' + err));
callback.called = true; // set after firing the callback
} // ..
});
res.on('end', function() {
process.nextTick(function() { // use setTimeout if nextTick is too short
if(!callback.called) { //..
console.log('res on end');
callback(null, data);
callback.called = true; // ..
} // ..
}); // ..
});
});
req.on('socket', function(socket) {
socket.on('error', function(err) {
if(!callback.called) { // ..
console.log('socket on error');
callback('socket error: ' + err);
callback.called = true; // ..
} // ..
req.abort();
});
});
req.end();
(I tried to add comments after all of the new lines to make them stand out a little.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With