node.js http.request поток событий - куда делось мое событие END? - PullRequest
3 голосов
/ 04 июня 2011

Я работаю над хитрым планом, который предполагает использование node.js в качестве прокси-сервера перед другим сервисом.

Вкратце:

  1. Отправка входящего запроса в статический файл (если он существует)
  2. В противном случае, отправка запроса в другую службу

У меня работают основы, но сейчас я пытаюсь заставить все это работать с Sencha Connect , чтобы я мог получить доступ ко всему предоставленному промежуточному программному обеспечению.

Все действие происходит в dispatchProxy ниже

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

Вы заметите proxyRequest.end () впоследняя строка выше.

Я обнаружил, что при обработке запросов GET событие END запроса никогда не запускается и, следовательно, требуется вызов proxyRequest.end ().POST-запросы вызывают события DATA и END, как и ожидалось.

Итак, несколько вопросов:

  • Безопасен ли этот вызов proxyRequest.end ()?То есть будет ли proxyResponse завершаться, даже если он вызывается вне циклов событий?

  • Это нормально для GET, чтобы не вызывать события END, или END захватывается где-тов стеке подключения?

Ответы [ 2 ]

4 голосов
/ 04 июня 2011

Проблема заключается не в событии end, а в событии data.Если клиент делает запросы GET, есть заголовки и нет данных.Это отличается от POST, когда запрашивающая сторона отправляет данные, поэтому обработчик on("data") получает удар.Итак (извините за пример JS, я не очень знаком с 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/');

Если я сделаю вызов curl этому серверу, событие данных никогда не будет получено, потому что GETзапрос не более чем заголовки.Из-за этого ваша логика становится такой:

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

Так что да, вам придется вручную вызывать proxyRequest.end() для GET запросов из-за разветвления логики, которое я только что упомянул.

0 голосов
/ 16 августа 2013

Мой опыт показывает, что request.on('end',) не постоянно , если только это не POST. Я подозреваю, что событие (когда кто-то создает http.request) закончилось, прежде чем сценарий сможет его обнаружить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...