2016-09-24 3 views
1

Как мне отменить HTTP-ответ с помощью экспресс-сообщения в середине? В моем случае я обслуживаю данные, созданные из внешнего источника, и до того, как я начал его обслуживать, я знаю размер (длина контента). Однако, если внешний источник перестает подавать мне данные перед подачей полного содержимого, я хочу прервать запрос, чтобы на конце приемника возникло событие ошибки.nodejs: отменить HTTP-ответ во время выполнения

Вот простой код, сервер:

//server 
var express = require('express'); 
var app = express(); 
app.use(function(req, res, next){ 
    res.setHeader('Content-Length', 100); 
    res.writeHead(200); 
    res.write('1234567890'); 
    setTimeout(function() { res.connection.destroy(); }, 500); 
}); 
app.listen(8080); 

и

//client 
var http = require('http'); 
http.get('http://localhost:8080/', function(res){ 
    var length = 0; 
    console.log('expected size: ', res.headers['content-length']); 
    res.on('data', function(chunk){ length += chunk.length; }); 
    res.on('end', function(){ console.log('received: ', length); }); 
}).on('error', function(e){ 
    console.log('error', e); 
}); 

Ожидается, что клиент должен показать ошибку, что соединение сброшено и не ведут себя, как все было нормально, хотя только 10 байт из 100.

Как прервать соединение на стороне отправителя, когда известно, что запрос не может быть выполнен? Один из способов, которым я узнал, заключается в том, чтобы исключить исключение из этого таймера, тогда приемник будет регистрировать ошибку, но я не хочу бросать исключение, я хочу сделать это правильно.

+0

Хм. Я думаю, вам придется захватить полные данные из внешнего источника, прежде чем возвращать его с сервера узлов. –

+0

@RobertMoskal не вариант, мне нужно знать, как hot to abort tcp connection. Не могу поверить, что такого метода нет. Мне действительно нужно отменить, никаких обходных решений или других решений. – Pavel

ответ

1

В идеале для завершения ответа HTTP вы должны позвонить res.end(). В случае закодированного кодирования передачи или соединения без сохранения HTTP это приведет к чистому завершению ответа.

Однако большинство HTTP-соединений будут поддерживать HTTP-поддержку, и поскольку у вас есть заголовок Content-Length, ваша кодировка передачи не разрывается. В вашем случае вам придется закрыть основной сокет. Проверьте недвижимость req.connection и позвоните по телефону .end(). Это недокументировано, но существует уже много лет и, вероятно, сейчас безопасно. Более законные методы для подключения включают listening for it on the server object, но тогда трудно связать соединение с запросом.

Следует помнить, что с большинством HTTP-клиентов это предупреждение в лучшем случае, а не как правило ошибка. Если вы контролируете код клиента, вы можете обнаружить это условие, сравнив длину полученных данных с ожидаемой длиной.

+0

Вы проверили мой код? Я делаю req.connection.destroy(). Очевидно, я знаю о res.end(). Вы не можете выполнить res.end(), вы обязательно должны закрыть соединение. Вы это понимаете? – Pavel

+0

Да, я проверил ваш код. Используйте '.end()' в вашем сокете ... '.destroy()' не то, что вы хотите. И, как вы думаете, 'res.end()' делает в ситуации отсутствия keepalive? Он закрывает соединение. Я упоминаю это, потому что это может быть актуально в вашем случае. Пожалуйста, перечитайте мой ответ, два варианта, которые я предложил, и выберите тот, который относится к вам. – Brad

+0

точно, res.end() приведет к хаосу в случае keepalive, если используется не-канальная передача. Я попробую socket.end, еще не пробовал. – Pavel

Смежные вопросы