Node.js http.request event stream - where did my END event go?

I am working on a clever plan that involves using node.js as a proxy in front of another service.

In short:

  • Sending an incoming request to a static file (if one exists)
  • Otherwise, send the request to another service

I have the basics of work, but now I'm trying to get everything that works with Sencha Connect so that I can access all the hits, middleware.

All actions take place in dispatchProxy below

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() 

You will see proxyRequest.end () in the last line above.

I found that when processing GET requests, the END request event never fires, and therefore a call to proxyRequest.end () is required. POST requests fire both DATA and END events as expected.

So a few questions:

  • Is this call to proxyRequest.end () safe? That is, will the proxyResponse request be executed even if it is called outside of the event loops?

  • Is it normal for GET not to fire END events, and END is written somewhere in the connection stack?

+3
source share
2 answers

The problem is less than the end event and more data . If the client makes GET requests, there are headers and data. This is different from POST when the requestor sends data, so the on("data") handler gets hit. So (excuse me for the JS example, I'm not so familiar with 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/'); 

If I make a curl call for this server, the data event never gets caught, because the GET request is nothing more than a header. Because of this, your logic becomes:

 // 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 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() 

So yes, you will have to manually call proxyRequest.end() for GET requests due to the logical branching just mentioned.

+4
source

my experience is that request.on('end',) not called sequentially unless it is POST. I suspect that the event (someone does http.request) has ended before the script is able to detect it.

0
source

Source: https://habr.com/ru/post/1239542/


All Articles