2013-02-09 2 views
2

J'utilise le module fakeweb qui remplace http.request de nœud avec la fonction suivante:Écrasement http.request avec EventEmitter

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); 
    } 
}; 

Mon problème est que je reçois le bug: TypeError: Object #<Object> has no method 'on' du code suivant dans un autre fichier:

var req = proto.request(options, function (res) { ... }); 
req.on('error', function (err) { 
     err.success = false; 
     settings.complete(err); 
    }); 

Je pense que mon problème se produit parce qu'il est plus un EventEmitter, si je peux me tromper. Comment puis-je écraser avec succès http.request sans problème? Contexte: J'utilise la version du nœud 0.8.2. La demande NPM est une version 2.12.0

mise à jour (11 février 2013): Je veux donner un peu plus d'informations sur l'endroit où le http.request est appelé pour que je puisse être plus précis sur ce qui est nécessaire et ce qui cause les bugs. Voici où il est appelé:

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(); 
+0

la valeur de retour dans le 'si (règle) {'block n'est pas un EventEmitter – Chad

+0

Oui, comment pourrais-je renvoyer un EventEmitter ici correctement? – babonk

+0

Dépend de ce que vous voulez avoir émis. Vous êtes censé appeler 'req.end()' et vous obtiendrez un événement 'data' puis un événement' end'. C'est ainsi que fonctionne la bibliothèque. Comme aucun appel n'est jamais fait, vous n'obtiendrez jamais d'erreur. Vous devez vraiment expliquer votre objectif final ici. – Chad

Répondre

0

EDIT

Si vous voulez demande d'agir exactement la même, juste sans l'application réellement frapper le serveur de la requête puis essayez d'utiliser nock qui intercepter les demandes que vous définir et renvoyer les données que vous définissez.



Réponse d'origine:

Je pense que ce que vous recherchez est quelque chose comme ceci:

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); 
    } 
}; 
+0

Hey man, une fois que je fais ce changement, je reçois une nouvelle erreur: 'TypeError: Object # n'a pas de méthode 'pipe'' causée par' var req = http.request (options, function (res) {res.pipe (output);}); ' – babonk

+0

car' req' est normalement un flux inscriptible, et pas seulement 'EventEmitter'; Comme je l'ai dit avant je ne peux pas vous aider sans savoir quel est votre objectif final ici, je devine juste. Dites-moi ce que vous voulez et je peux vous aider, mais cela ressemble à un problème que vous devriez publier sur fakeweb si c'est ce que vous utilisez. – Chad

+0

J'essaie de faire fonctionner Fakeweb Node, en créant une fausse requête http qui ressemble à Node. C'est mon seul but. Je pensais que peut-être quelques hacks mineurs comme celui que vous avez déjà suggéré le feraient "quacking" comme le vieux canard http.request. – babonk