Перезапись http.request с помощью EventEmitter
Я использую модуль fakeweb, который перезаписывает Node's http.request
со следующей функцией:
var old_request = http.request;
http.request = function(options, callback){
var rule = match_rule(options);
if(rule){
var res = new events.EventEmitter();
res.headers = rule.headers || {'Content-Type': 'text/html'};
return {end: function(){
callback(res);
res.emit('data', rule.body || '');
res.emit('end');
}
};
} else {
return old_request.call(http, options, callback);
}
};
Моя проблема в том, что я получаю ошибку: TypeError: Object #<Object> has no method 'on'
из следующего кода в другом файле:
var req = proto.request(options, function (res) { ... });
req.on('error', function (err) {
err.success = false;
settings.complete(err);
});
Я думаю, что моя проблема возникает, потому что это больше не EventEmitter
хотя я могу ошибаться Как я могу успешно перезаписать http.request
без получения этой проблемы?
Фон: я использую Node версии 0.8.2. Запрос NPM версии 2.12.0
Обновление (11 февраля 2013 г.): я хочу предоставить больше информации о том, где вызывается http.request, чтобы я мог быть более конкретным о том, что нужно и что вызывает ошибки. Вот как это называется:
var proto = (options.protocol === 'https:') ? https : http;
var req = proto.request(options, function (res) {
var output = new StringStream();
switch (res.headers['content-encoding']) {
case 'gzip':
res.pipe(zlib.createGunzip()).pipe(output);
break;
case 'deflate':
res.pipe(zlib.createInflate()).pipe(output);
break;
default:
// Treat as uncompressed string
res.pipe(output);
break;
}
output.on('end', function() {
if (settings.cookieJar && res.headers['set-cookie']) {
var cookies = res.headers['set-cookie'];
for (var i = 0; i < cookies.length; i++) {
settings.cookieJar.set(cookies[i]);
}
}
if (res.statusCode >= 300 && res.statusCode < 400) {
if (settings.maxRedirects > settings.nRedirects++) {
// Follow redirect
var baseUrl = options.protocol + '//' + ((proxy) ? options.headers['host'] : options.host),
location = url.resolve(baseUrl, res.headers['location']);
request(location, settings);
} else {
var err = new Error('Max redirects reached.');
err.success = false;
settings.complete(err);
}
} else if (res.statusCode >= 400) {
var err = new Error(output.caught);
err.success = false;
err.code = res.statusCode;
settings.complete(err);
} else {
settings.complete(null, output.caught, res);
}
});
});
req.on('error', function (err) {
err.success = false;
settings.complete(err);
});
if (data) { req.write(data); }
req.end();
1 ответ
РЕДАКТИРОВАТЬ
Если вы хотите, чтобы запрос действовал точно так же, просто без приложения, поразившего сервер запроса, попробуйте использовать nock, который будет перехватывать заданные вами запросы и возвращать заданные вами данные.
Оригинальный ответ:
Я думаю, что вы ищете что-то вроде этого:
var old_request = http.request;
http.request = function(options, callback){
var rule = match_rule(options);
if(rule){
var res = new events.EventEmitter(),
req = new events.EventEmitter();
res.headers = rule.headers || {'Content-Type': 'text/html'};
req.end = function(){
if(callback) callback(res);
res.emit('data', rule.body || '');
res.emit('end');
};
return req;
} else {
return old_request.call(http, options, callback);
}
};