Node.js http.request flux d'événements – où est-ce que mon événement END est passé?

Je travaille sur un plan astucieux qui consiste à utiliser node.js comme serveur proxy devant un autre service.

En bref:

  1. Envoyer une demande entrante à un fichier statique (s'il existe)
  2. Sinon, envoyez la demande à un autre service

J'ai les bases de travail, mais maintenant je tente d'utiliser tout le travail avec Sencha Connect pour pouvoir accéder à tous les middleware kick-ass fournis.

Toute l'action se produit dans dispatchProxy ci-dessous

connect( connect.logger(), connect.static(__dirname + '/public'), (request, response) -> dispatchProxy(request, response) ).listen(8000) dispatchProxy = (request, response) -> options = {host: host, port: port, method: request.method, headers: request.headers, path: request.url} proxyRequest = http.request(options, (proxyResponse) -> proxyResponse.on('data', (chunk) -> response.write(chunk, 'binary') ) proxyResponse.on('end', (chunk) -> response.end() ) response.writeHead proxyResponse.statusCode, proxyResponse.headers ) request.on('data', (chunk) -> proxyRequest.write(chunk, 'binary') ) # this is never triggered for GETs request.on('end', -> proxyRequest.end() ) # so I have to have this here proxyRequest.end() 

Vous remarquerez proxyRequest.end () sur la dernière ligne ci-dessus.

Ce que j'ai constaté, c'est que lorsque vous manipulez les requêtes GET, l'événement END de la requête n'est jamais déclenché et, par conséquent, un appel à proxyRequest.end () est requis. Les requêtes POST déclenchent les événements DATA et END comme prévu.

Donc, plusieurs questions:

  • Cet appel à proxyRequest.end () est-il sécurisé? C'est-à-dire que la réponse de proxy sera-t-elle complétée même si cela est appelé en dehors des boucles d'événements?

  • Est-il normal que GET ne déclenche pas d'événements END ou est-ce que END est capturé quelque part dans la pile connectée?

Le problème est moins l'événement end et plus l'événement de data . Si un client effectue des requêtes GET, il y a des en-têtes et pas de données. Ceci est différent de POST, où le demandeur envoie des données, de sorte que le gestionnaire on("data") est touché. Donc (pardonnez-moi pour l'exemple de JS, je ne suis pas familier avec coffeescript):

 var http = require('http'); // You won't see the output of request.on("data") http.createServer(function (request, response) { request.on("end", function(){ console.log("here"); }); request.on("data", function(data) { console.log("I am here"); console.log(data.toString("utf8")); }); response.writeHead(200, {'Content-Type': 'text/plain'}); response.end('Hello World\n'); }).listen(8124); console.log('Server running at http://127.0.0.1:8124/'); 

Si je fais un appel curl à ce serveur, l'événement de données n'est jamais frappé, car la requête GET n'est rien d'autre que les en-têtes. Pour cette raison, votre logique devient:

 // okay setup the request... // However, the callback doesn't get hit until you // start writing some data or ending the proxyRequest! proxyRequest = http.request(options, (proxyResponse) -> // So this doesn't get hit yet... proxyResponse.on('data', (chunk) -> response.write(chunk, 'binary') ) // and this doesn't get hit yet proxyResponse.on('end', (chunk) -> // which is why your response.on("end") event isn't getting hit yet response.end() ) response.writeHead proxyResponse.statusCode, proxyResponse.headers ) // This doesn't get hit! request.on('data', (chunk) -> proxyRequest.write(chunk, 'binary') ) // So this isn't going to happen until your proxyRequest // callback handler gets hit, which hasn't happened because // unlike POST there's no data in your GET request request.on('end', -> proxyRequest.end() ) // now the proxy request call is finally made, which // triggers the callback function in your http request setup proxyRequest.end() 

Donc, oui, vous devrez appeler manuellement proxyRequest.end() pour GET requêtes GET raison de la ramification logique que je viens de mentionner.

Mon expérience est que request.on('end',) n'est pas toujours appelé à moins qu'il s'agisse d'un POST. Je soupçonne que l'événement (de quelqu'un qui fait une requête http) est terminé avant que le script ait la possibilité de le détecter.