Changed output to processor to break dependancy on HTTP
This commit is contained in:
parent
1b29f0bac1
commit
8d3ce97474
|
@ -0,0 +1,71 @@
|
||||||
|
var util = require('util');
|
||||||
|
var http = require('http');
|
||||||
|
|
||||||
|
var BaseProcessor = require('./baseprocessor');
|
||||||
|
|
||||||
|
|
||||||
|
function BaseHTTPStreamProcessor(camId, cam, now)
|
||||||
|
{
|
||||||
|
BaseProcessor.apply(this, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
util.inherits(BaseHTTPStreamProcessor, BaseProcessor);
|
||||||
|
|
||||||
|
|
||||||
|
BaseHTTPStreamProcessor.prototype.run = function()
|
||||||
|
{
|
||||||
|
var self = this;
|
||||||
|
var timer = null;
|
||||||
|
var req = null;
|
||||||
|
|
||||||
|
var doCleanup = function()
|
||||||
|
{
|
||||||
|
if (timer !== null)
|
||||||
|
{
|
||||||
|
clearTimeout(timer);
|
||||||
|
timer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.cleanup();
|
||||||
|
self.doEnd();
|
||||||
|
};
|
||||||
|
|
||||||
|
req = http.request(self.cam.options.url, function(res)
|
||||||
|
{
|
||||||
|
self.doStart();
|
||||||
|
|
||||||
|
timer = setTimeout(function()
|
||||||
|
{
|
||||||
|
req.abort();
|
||||||
|
doCleanup();
|
||||||
|
}, self.cam.options.time || 10000);
|
||||||
|
|
||||||
|
|
||||||
|
res.on('end', function()
|
||||||
|
{
|
||||||
|
doCleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
res.pipe(self.getStream());
|
||||||
|
});
|
||||||
|
|
||||||
|
req.on('error', function(e)
|
||||||
|
{
|
||||||
|
console.log(e);
|
||||||
|
doCleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
req.end();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
BaseHTTPStreamProcessor.prototype.getStream = function()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BaseHTTPStreamProcessor.prototype.cleanup = function()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = BaseHTTPStreamProcessor;
|
|
@ -0,0 +1,42 @@
|
||||||
|
var events = require('events');
|
||||||
|
var util = require('util');
|
||||||
|
|
||||||
|
function BaseProcessor(camId, cam, now)
|
||||||
|
{
|
||||||
|
this.camId = camId;
|
||||||
|
this.cam = cam;
|
||||||
|
this.now = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Descendants are required to call the following functions:
|
||||||
|
|
||||||
|
doStart
|
||||||
|
Call when the processing starts. This may be delayed slightly, for example,
|
||||||
|
right after the stream is connected or when the first chunk of data arrives.
|
||||||
|
|
||||||
|
doEnd
|
||||||
|
Call when the processor is done.
|
||||||
|
|
||||||
|
*/
|
||||||
|
util.inherits(BaseProcessor, events.EventEmitter);
|
||||||
|
|
||||||
|
|
||||||
|
BaseProcessor.prototype.run = function()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BaseProcessor.prototype.doStart = function()
|
||||||
|
{
|
||||||
|
this.emit('start');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BaseProcessor.prototype.doEnd = function()
|
||||||
|
{
|
||||||
|
this.emit('end');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = BaseProcessor;
|
69
capture.js
69
capture.js
|
@ -76,7 +76,7 @@ module.exports =
|
||||||
{
|
{
|
||||||
if (cams.hasOwnProperty(camId))
|
if (cams.hasOwnProperty(camId))
|
||||||
{
|
{
|
||||||
require('./output-' + cams[camId].output);
|
require('./processor-' + cams[camId].processor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -84,71 +84,38 @@ module.exports =
|
||||||
|
|
||||||
start: function(camId, cam, now)
|
start: function(camId, cam, now)
|
||||||
{
|
{
|
||||||
var timer = null;
|
var processor = new (require('./processor-' + cam.processor))(camId, cam, now);
|
||||||
var req = null;
|
var duringCommandsDone = false;
|
||||||
var output = new (require('./output-' + cam.output))(camId, cam.outputOptions, now);
|
var queueAfterCommand = false;
|
||||||
var duringDone = false;
|
|
||||||
var queueAfter = false;
|
|
||||||
|
|
||||||
|
|
||||||
runCommands(cam.before, 'before', function()
|
runCommands(cam.before, 'before', function()
|
||||||
{
|
{
|
||||||
var cleanup = function()
|
processor.on('start', function()
|
||||||
{
|
|
||||||
if (timer !== null)
|
|
||||||
{
|
|
||||||
clearTimeout(timer);
|
|
||||||
timer = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (output !== null)
|
|
||||||
{
|
|
||||||
output.cleanup();
|
|
||||||
output = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the stream is cut short, or the time is configured
|
|
||||||
// to be less than the duration of the 'during' commands,
|
|
||||||
// queue it up.
|
|
||||||
if (duringDone)
|
|
||||||
runCommands(cam.after, 'after', function() { });
|
|
||||||
else
|
|
||||||
queueAfter = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
req = http.request(cam.url, function(res)
|
|
||||||
{
|
{
|
||||||
runCommands(cam.during, 'during', function()
|
runCommands(cam.during, 'during', function()
|
||||||
{
|
{
|
||||||
if (queueAfter)
|
// Check if the processor has already finished and the
|
||||||
|
// 'after' commands should be run immediately.
|
||||||
|
if (queueAfterCommand)
|
||||||
runCommands(cam.after, 'after', function() { });
|
runCommands(cam.after, 'after', function() { });
|
||||||
else
|
else
|
||||||
duringDone = true;
|
duringCommandsDone = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
timer = setTimeout(function()
|
|
||||||
{
|
|
||||||
req.abort();
|
|
||||||
cleanup();
|
|
||||||
}, cam.time || config.defaultTime || 10000);
|
|
||||||
|
|
||||||
|
|
||||||
res.on('end', function()
|
|
||||||
{
|
|
||||||
cleanup();
|
|
||||||
});
|
|
||||||
|
|
||||||
res.pipe(output.getStream());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
req.on('error', function(e)
|
processor.on('end', function()
|
||||||
{
|
{
|
||||||
console.log(e);
|
// If the stream is cut short, or the time is configured
|
||||||
cleanup();
|
// to be less than the duration of the 'during' commands,
|
||||||
|
// queue it up.
|
||||||
|
if (duringCommandsDone)
|
||||||
|
runCommands(cam.after, 'after', function() { });
|
||||||
|
else
|
||||||
|
queueAfterCommand = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
req.end();
|
processor.run();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
|
@ -2,23 +2,23 @@ var foscam = require('./config-foscam');
|
||||||
var config = {};
|
var config = {};
|
||||||
|
|
||||||
config.port = 5705;
|
config.port = 5705;
|
||||||
config.defaultTime = 5000;
|
|
||||||
|
|
||||||
config.cams =
|
config.cams =
|
||||||
{
|
{
|
||||||
frontdoor:
|
frontdoor:
|
||||||
{
|
{
|
||||||
// You can specify any URL string here, the Foscam helper just makes it easier
|
processor: 'ffmpeg',
|
||||||
// for compatible models. If you add your own config helper, please publish!
|
options:
|
||||||
url: foscam.mjpegStream('10.138.1.10', 'viewer', 'verysecure'),
|
|
||||||
time: 5000,
|
|
||||||
|
|
||||||
output: 'ffmpeg',
|
|
||||||
outputOptions:
|
|
||||||
{
|
{
|
||||||
|
// You can specify any URL string here, the Foscam helper just makes it easier
|
||||||
|
// for compatible models. If you add your own config helper, please publish!
|
||||||
|
url: foscam.mjpegStream('10.138.1.10', 'viewer', 'verysecure'),
|
||||||
|
time: 5000,
|
||||||
|
|
||||||
inputFormat: 'mjpeg',
|
inputFormat: 'mjpeg',
|
||||||
outputFormat: 'avi',
|
outputFormat: 'avi',
|
||||||
videoCodec: 'libx264',
|
videoCodec: 'libx264',
|
||||||
|
|
||||||
filename: '[/srv/www/publiccam/]YYYY-MM-DD HH.mm.ss[/<camId>.avi]'
|
filename: '[/srv/www/publiccam/]YYYY-MM-DD HH.mm.ss[/<camId>.avi]'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,16 +27,16 @@ config.cams =
|
||||||
|
|
||||||
backdoor:
|
backdoor:
|
||||||
{
|
{
|
||||||
// You can use username:password@ in the URL to log in with basic
|
processor: 'mjpeg-split',
|
||||||
// authentication. Note that some cams, like Foscam, use Digest
|
options:
|
||||||
// authentication which is not supported. For Foscam you can provide
|
|
||||||
// the login in the parameters instead.
|
|
||||||
url: 'http://viewer:verysecure@10.138.1.11/video.cgi',
|
|
||||||
time: 5000,
|
|
||||||
|
|
||||||
output: 'mjpeg-split',
|
|
||||||
outputOptions:
|
|
||||||
{
|
{
|
||||||
|
// You can use username:password@ in the URL to log in with basic
|
||||||
|
// authentication. Note that some cams, like Foscam, use Digest
|
||||||
|
// authentication which is not supported. For Foscam you can provide
|
||||||
|
// the login in the parameters instead.
|
||||||
|
url: 'http://viewer:verysecure@10.138.1.11/video.cgi',
|
||||||
|
time: 5000,
|
||||||
|
|
||||||
filename: '[/srv/www/publiccam/]YYYY-MM-DD HH.mm.ss[/<camId> <frame>.avi]'
|
filename: '[/srv/www/publiccam/]YYYY-MM-DD HH.mm.ss[/<camId> <frame>.avi]'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
var util = require('util');
|
|
||||||
var stream = require('stream');
|
|
||||||
var FfmpegCommand = require('fluent-ffmpeg');
|
|
||||||
|
|
||||||
var helpers = require('./helpers');
|
|
||||||
|
|
||||||
|
|
||||||
function OutputFFMPEG(camId, options, now)
|
|
||||||
{
|
|
||||||
this.output = new stream.PassThrough();
|
|
||||||
var command = new FfmpegCommand();
|
|
||||||
command
|
|
||||||
.input(this.output)
|
|
||||||
.inputFormat(options.inputFormat);
|
|
||||||
|
|
||||||
if (options.inputFormat === 'mjpeg')
|
|
||||||
command.inputOption('-use_wallclock_as_timestamps 1');
|
|
||||||
|
|
||||||
command
|
|
||||||
.output(helpers.createVariableFilename(options.filename, now,
|
|
||||||
{
|
|
||||||
camId: camId
|
|
||||||
}))
|
|
||||||
.videoCodec(options.videoCodec)
|
|
||||||
.outputFormat(options.outputFormat)
|
|
||||||
.run();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
OutputFFMPEG.prototype.getStream = function()
|
|
||||||
{
|
|
||||||
return this.output;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
OutputFFMPEG.prototype.cleanup = function()
|
|
||||||
{
|
|
||||||
if (this.output !== null)
|
|
||||||
{
|
|
||||||
this.output.end();
|
|
||||||
this.output = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = OutputFFMPEG;
|
|
|
@ -1,44 +0,0 @@
|
||||||
var MjpegConsumer = require('mjpeg-consumer');
|
|
||||||
var FileOnWrite = require('file-on-write');
|
|
||||||
|
|
||||||
var helpers = require('./helpers');
|
|
||||||
|
|
||||||
|
|
||||||
function OutputMJPEGSplit(camId, options, now)
|
|
||||||
{
|
|
||||||
var frameCounter = 0;
|
|
||||||
|
|
||||||
this.output = new FileOnWrite({
|
|
||||||
filename: function(data)
|
|
||||||
{
|
|
||||||
frameCounter++;
|
|
||||||
|
|
||||||
return helpers.createVariableFilename(options.filename, now,
|
|
||||||
{
|
|
||||||
camId: camId,
|
|
||||||
frame: frameCounter
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.consumer = new MjpegConsumer();
|
|
||||||
this.consumer.pipe(this.output);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
OutputMJPEGSplit.prototype.getStream = function()
|
|
||||||
{
|
|
||||||
return this.consumer;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
OutputMJPEGSplit.prototype.cleanup = function()
|
|
||||||
{
|
|
||||||
if (this.consumer !== null)
|
|
||||||
{
|
|
||||||
this.consumer.end();
|
|
||||||
this.consumer = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = OutputMJPEGSplit;
|
|
|
@ -1,30 +0,0 @@
|
||||||
var fs = require('fs');
|
|
||||||
|
|
||||||
var helpers = require('./helpers');
|
|
||||||
|
|
||||||
|
|
||||||
function OutputRaw(camId, options, now)
|
|
||||||
{
|
|
||||||
this.output = fs.createWriteStream(helpers.createVariableFilename(options.filename, now,
|
|
||||||
{
|
|
||||||
camId: camId
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
OutputRaw.prototype.getStream = function()
|
|
||||||
{
|
|
||||||
return this.output;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
OutputRaw.prototype.cleanup = function()
|
|
||||||
{
|
|
||||||
if (this.output !== null)
|
|
||||||
{
|
|
||||||
this.output.end();
|
|
||||||
this.output = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = OutputRaw;
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
var fs = require('fs');
|
||||||
|
var util = require('util');
|
||||||
|
var stream = require('stream');
|
||||||
|
|
||||||
|
var FfmpegCommand = require('fluent-ffmpeg');
|
||||||
|
|
||||||
|
var helpers = require('./helpers');
|
||||||
|
var BaseProcessor = require('./baseprocessor');
|
||||||
|
|
||||||
|
|
||||||
|
function FFMPEGProcessor()
|
||||||
|
{
|
||||||
|
BaseProcessor.apply(this, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
util.inherits(FFMPEGProcessor, BaseProcessor);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
FFMPEGProcessor.prototype.run = function()
|
||||||
|
{
|
||||||
|
var self = this;
|
||||||
|
var command = new FfmpegCommand();
|
||||||
|
command
|
||||||
|
.input(this.cam.options.input)
|
||||||
|
.inputOptions(['-t ' + this.cam.options.time]);
|
||||||
|
|
||||||
|
if (typeof(this.cam.options.inputFormat) !== 'undefined')
|
||||||
|
{
|
||||||
|
command.inputFormat(this.cam.options.inputFormat);
|
||||||
|
if (this.cam.options.inputFormat === 'mjpeg')
|
||||||
|
command.inputOption('-use_wallclock_as_timestamps 1');
|
||||||
|
}
|
||||||
|
|
||||||
|
command
|
||||||
|
.output(helpers.createVariableFilename(this.cam.options.filename, this.now,
|
||||||
|
{
|
||||||
|
camId: this.camId
|
||||||
|
}))
|
||||||
|
.videoCodec(this.cam.options.videoCodec)
|
||||||
|
.outputFormat(this.cam.options.outputFormat);
|
||||||
|
|
||||||
|
command.on('end', function()
|
||||||
|
{
|
||||||
|
self.doEnd();
|
||||||
|
});
|
||||||
|
|
||||||
|
self.doStart();
|
||||||
|
command.run();
|
||||||
|
|
||||||
|
FFMPEGProcessor.super_.prototype.run.call(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = FFMPEGProcessor;
|
|
@ -0,0 +1,59 @@
|
||||||
|
var fs = require('fs');
|
||||||
|
var util = require('util');
|
||||||
|
var stream = require('stream');
|
||||||
|
|
||||||
|
var FfmpegCommand = require('fluent-ffmpeg');
|
||||||
|
|
||||||
|
var helpers = require('./helpers');
|
||||||
|
var BaseHTTPStreamProcessor = require('./basehttpstreamprocessor');
|
||||||
|
|
||||||
|
|
||||||
|
function HTTPFFMPEGProcessor()
|
||||||
|
{
|
||||||
|
BaseHTTPStreamProcessor.apply(this, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
util.inherits(HTTPFFMPEGProcessor, BaseHTTPStreamProcessor);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
HTTPFFMPEGProcessor.prototype.run = function()
|
||||||
|
{
|
||||||
|
this.output = new stream.PassThrough();
|
||||||
|
var command = new FfmpegCommand();
|
||||||
|
command
|
||||||
|
.input(this.output)
|
||||||
|
.inputFormat(this.cam.options.inputFormat);
|
||||||
|
|
||||||
|
if (this.cam.options.inputFormat === 'mjpeg')
|
||||||
|
command.inputOption('-use_wallclock_as_timestamps 1');
|
||||||
|
|
||||||
|
command
|
||||||
|
.output(helpers.createVariableFilename(this.cam.options.filename, this.now,
|
||||||
|
{
|
||||||
|
camId: this.camId
|
||||||
|
}))
|
||||||
|
.videoCodec(this.cam.options.videoCodec)
|
||||||
|
.outputFormat(this.cam.options.outputFormat)
|
||||||
|
.run();
|
||||||
|
|
||||||
|
HTTPFFMPEGProcessor.super_.prototype.run.call(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HTTPFFMPEGProcessor.prototype.getStream = function()
|
||||||
|
{
|
||||||
|
return this.output;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HTTPFFMPEGProcessor.prototype.cleanup = function()
|
||||||
|
{
|
||||||
|
if (this.output !== null)
|
||||||
|
{
|
||||||
|
this.output.end();
|
||||||
|
this.output = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = HTTPFFMPEGProcessor;
|
|
@ -0,0 +1,64 @@
|
||||||
|
var fs = require('fs');
|
||||||
|
var util = require('util');
|
||||||
|
|
||||||
|
var MjpegConsumer = require('mjpeg-consumer');
|
||||||
|
var FileOnWrite = require('file-on-write');
|
||||||
|
|
||||||
|
var helpers = require('./helpers');
|
||||||
|
var BaseHTTPStreamProcessor = require('./basehttpstreamprocessor');
|
||||||
|
|
||||||
|
function HTTPMJPEGSplitProcessor()
|
||||||
|
{
|
||||||
|
BaseHTTPStreamProcessor.apply(this, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
util.inherits(HTTPMJPEGSplitProcessor, BaseHTTPStreamProcessor);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
HTTPMJPEGSplitProcessor.prototype.run = function()
|
||||||
|
{
|
||||||
|
var self = this;
|
||||||
|
var frameCounter = 0;
|
||||||
|
|
||||||
|
this.output = new FileOnWrite({
|
||||||
|
filename: function(data)
|
||||||
|
{
|
||||||
|
frameCounter++;
|
||||||
|
|
||||||
|
return helpers.createVariableFilename(self.cam.options.filename, self.now,
|
||||||
|
{
|
||||||
|
camId: self.camId,
|
||||||
|
frame: frameCounter
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.consumer = new MjpegConsumer();
|
||||||
|
this.consumer.pipe(this.output);
|
||||||
|
|
||||||
|
|
||||||
|
HTTPMJPEGSplitProcessor.super_.prototype.run.call(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HTTPMJPEGSplitProcessor.prototype.getStream = function()
|
||||||
|
{
|
||||||
|
return this.consumer;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = HTTPMJPEGSplitProcessor;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
HTTPMJPEGSplitProcessor.prototype.cleanup = function()
|
||||||
|
{
|
||||||
|
if (this.consumer !== null)
|
||||||
|
{
|
||||||
|
this.consumer.end();
|
||||||
|
this.consumer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = HTTPMJPEGSplitProcessor;
|
|
@ -0,0 +1,46 @@
|
||||||
|
var fs = require('fs');
|
||||||
|
var util = require('util');
|
||||||
|
|
||||||
|
var helpers = require('./helpers');
|
||||||
|
var BaseHTTPStreamProcessor = require('./basehttpstreamprocessor');
|
||||||
|
|
||||||
|
function HTTPRawProcessor()
|
||||||
|
{
|
||||||
|
BaseHTTPStreamProcessor.apply(this, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
util.inherits(HTTPRawProcessor, BaseHTTPStreamProcessor);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
HTTPRawProcessor.prototype.run = function()
|
||||||
|
{
|
||||||
|
this.output = fs.createWriteStream(helpers.createVariableFilename(this.cam.options.filename, this.now,
|
||||||
|
{
|
||||||
|
camId: this.camId
|
||||||
|
}));
|
||||||
|
|
||||||
|
HTTPRawProcessor.super_.prototype.run.call(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HTTPRawProcessor.prototype.getStream = function()
|
||||||
|
{
|
||||||
|
return this.output;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = HTTPRawProcessor;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
HTTPRawProcessor.prototype.cleanup = function()
|
||||||
|
{
|
||||||
|
if (this.output !== null)
|
||||||
|
{
|
||||||
|
this.output.end();
|
||||||
|
this.output = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = HTTPRawProcessor;
|
Loading…
Reference in New Issue