camstreamerlib 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CameraVapix.js CHANGED
@@ -1,4 +1,3 @@
1
- const util = require('util');
2
1
  const EventEmitter = require('eventemitter2');
3
2
  const parseString = require('xml2js').parseString;
4
3
  const prettifyXml = require('prettify-xml')
@@ -6,253 +5,369 @@ const prettifyXml = require('prettify-xml')
6
5
  const RtspClient = require('./RtspClient');
7
6
  const httpRequest = require('./HTTPRequest');
8
7
 
9
- function CameraVapix(options) {
10
- this.protocol = 'http';
11
- this.ip = '127.0.0.1';
12
- this.port = 80;
13
- this.auth = '';
14
- if (options) {
15
- this.protocol = options['protocol'] || this.protocol;
16
- this.ip = options['ip'] || this.ip;
17
- this.port = options['port'];
18
- if (this.port == undefined) {
19
- this.port = this.protocol == 'http' ? 80 : 443
20
- }
21
- this.auth = options['auth'] || this.auth;
22
- }
8
+ const WebSocket = require('ws');
9
+ const Digest = require('./Digest');
23
10
 
24
- this.rtsp = null;
25
11
 
26
- EventEmitter.call(this);
27
- }
12
+ class CameraVapix extends EventEmitter {
13
+ constructor(options) {
14
+ super();
15
+ this.protocol = 'http';
16
+ this.ip = '127.0.0.1';
17
+ this.port = 80;
18
+ this.auth = '';
28
19
 
29
- util.inherits(CameraVapix, EventEmitter);
30
-
31
- CameraVapix.prototype.getParameterGroup = function(groupNames) {
32
- var promise = new Promise(function(resolve, reject) {
33
- this.vapixGet('/axis-cgi/param.cgi?action=list&group=' + encodeURIComponent(groupNames)).then(function(response) {
34
- var params = {};
35
- var lines = response.split(/[\r\n]/);
36
- for (var i = 0; i < lines.length; i++) {
37
- if (lines[i].length) {
38
- var p = lines[i].split('=');
39
- if (p.length >= 2) {
40
- params[p[0]] = p[1];
41
- }
20
+ if (options) {
21
+ this.protocol = options['protocol'] || this.protocol;
22
+ this.ip = options['ip'] || this.ip;
23
+ this.port = options['port'];
24
+ if (this.port == undefined) {
25
+ this.port = this.protocol == 'http' ? 80 : 443
26
+ }
27
+ this.auth = options['auth'] || this.auth;
42
28
  }
43
- }
44
- resolve(params);
45
- }, reject);
46
- }.bind(this));
47
- return promise;
48
- }
49
29
 
50
- CameraVapix.prototype.setParameter = function(params) {
51
- var postData = 'action=update&';
52
- Object.keys(params).forEach(function(key) {
53
- postData += key + '=' + params[key] + '&';
54
- });
55
- postData = postData.slice(0, postData.length - 1);
56
- return this.vapixPost('/axis-cgi/param.cgi', postData);
57
- }
30
+ this.rtsp = null;
31
+ this.ws = null;
32
+ }
58
33
 
59
- CameraVapix.prototype.getPTZPresetList = function(channel) {
60
- var promise = new Promise(function(resolve, reject) {
61
- this.vapixGet('/axis-cgi/com/ptz.cgi?query=presetposcam&camera=' + encodeURIComponent(channel)).then(function(response) {
62
- var positions = [];
63
- var lines = response.split(/[\r\n]/);
64
- for (var i = 0; i < lines.length; i++) {
65
- if (lines[i].length && lines[i].indexOf('presetposno') != -1) {
66
- var p = lines[i].split('=');
67
- if (p.length >= 2) {
68
- positions.push(p[1]);
69
- }
70
- }
71
- }
72
- resolve(positions);
73
- }, reject);
74
- }.bind(this));
75
- return promise;
76
- }
34
+ getParameterGroup(groupNames) {
35
+ let promise = new Promise((resolve, reject) => {
36
+ this.vapixGet('/axis-cgi/param.cgi?action=list&group=' + encodeURIComponent(groupNames)).then((response) => {
37
+ let params = {};
38
+ let lines = response.split(/[\r\n]/);
39
+ for (let i = 0; i < lines.length; i++) {
40
+ if (lines[i].length) {
41
+ let p = lines[i].split('=');
42
+ if (p.length >= 2) {
43
+ params[p[0]] = p[1];
44
+ }
45
+ }
46
+ }
47
+ resolve(params);
48
+ }, reject);
49
+ });
50
+ return promise;
51
+ }
77
52
 
78
- CameraVapix.prototype.goToPreset = function(channel, presetName) {
79
- return this.vapixPost('/axis-cgi/com/ptz.cgi', 'camera=' + encodeURIComponent(channel) + '&gotoserverpresetname=' + encodeURIComponent(presetName));
80
- }
53
+ setParameter(params) {
54
+ let postData = 'action=update&';
55
+ Object.keys(params).forEach((key) => {
56
+ postData += key + '=' + params[key] + '&';
57
+ });
58
+ postData = postData.slice(0, postData.length - 1);
59
+ return this.vapixPost('/axis-cgi/param.cgi', postData);
60
+ }
81
61
 
82
- CameraVapix.prototype.getGuardTourList = function() {
83
- var promise = new Promise(function(resolve, reject) {
84
- var gTourList = [];
85
- this.getParameterGroup('GuardTour').then(function(response) {
86
- for (var i = 0; i < 20; i++) {
87
- var gTourBaseName = 'root.GuardTour.G' + i;
88
- if (gTourBaseName + '.CamNbr' in response) {
89
- var gTour = {
90
- 'ID': gTourBaseName,
91
- 'CamNbr': response[gTourBaseName + '.CamNbr'],
92
- 'Name': response[gTourBaseName + '.Name'],
93
- 'RandomEnabled': response[gTourBaseName + '.RandomEnabled'],
94
- 'Running': response[gTourBaseName + '.Running'],
95
- 'TimeBetweenSequences': response[gTourBaseName + '.TimeBetweenSequences'],
96
- 'Tour': []
97
- };
98
- for (var j = 0; j < 100; j++) {
99
- var tourBaseName = 'root.GuardTour.G' + i + '.Tour.T' + j;
100
- if (tourBaseName + '.MoveSpeed' in response) {
101
- var tour = {
102
- 'MoveSpeed': response[tourBaseName + '.MoveSpeed'],
103
- 'Position': response[tourBaseName + '.Position'],
104
- 'PresetNbr': response[tourBaseName + '.PresetNbr'],
105
- 'WaitTime': response[tourBaseName + '.WaitTime'],
106
- 'WaitTimeViewType': response[tourBaseName + '.WaitTimeViewType']
107
- };
108
- gTour.Tour.push(tour);
109
- }
110
- }
111
- gTourList.push(gTour);
112
- } else {
113
- break;
114
- }
115
- }
116
- resolve(gTourList);
117
- }, reject)
118
- }.bind(this));
119
- return promise;
120
- }
62
+ getPTZPresetList(channel) {
63
+ let promise = new Promise((resolve, reject) => {
64
+ this.vapixGet('/axis-cgi/com/ptz.cgi?query=presetposcam&camera=' + encodeURIComponent(channel)).then((response) => {
65
+ let positions = [];
66
+ let lines = response.split(/[\r\n]/);
67
+ for (let i = 0; i < lines.length; i++) {
68
+ if (lines[i].length && lines[i].indexOf('presetposno') != -1) {
69
+ let p = lines[i].split('=');
70
+ if (p.length >= 2) {
71
+ positions.push(p[1]);
72
+ }
73
+ }
74
+ }
75
+ resolve(positions);
76
+ }, reject);
77
+ });
78
+ return promise;
79
+ }
121
80
 
122
- CameraVapix.prototype.setGuardTourEnabled = function(gourTourID, enable) {
123
- var options = {};
124
- options[gourTourID + '.Running'] = enable ? 'yes' : 'no';
125
- return this.setParameter(options);
126
- }
81
+ goToPreset(channel, presetName) {
82
+ return this.vapixPost('/axis-cgi/com/ptz.cgi', 'camera=' + encodeURIComponent(channel) + '&gotoserverpresetname=' + encodeURIComponent(presetName));
83
+ }
127
84
 
128
- CameraVapix.prototype.getInputState = function(port) {
129
- var promise = new Promise(function(resolve, reject) {
130
- this.vapixPost('/axis-cgi/io/port.cgi', 'checkactive=' + encodeURIComponent(port)).then(function(response) {
131
- resolve(response.split('=')[1].indexOf('active') == 0);
132
- }, reject);
133
- }.bind(this));
134
- return promise;
135
- }
85
+ getGuardTourList() {
86
+ let promise = new Promise((resolve, reject) => {
87
+ let gTourList = [];
88
+ this.getParameterGroup('GuardTour').then((response) => {
89
+ for (let i = 0; i < 20; i++) {
90
+ let gTourBaseName = 'root.GuardTour.G' + i;
91
+ if (gTourBaseName + '.CamNbr' in response) {
92
+ let gTour = {
93
+ 'ID': gTourBaseName,
94
+ 'CamNbr': response[gTourBaseName + '.CamNbr'],
95
+ 'Name': response[gTourBaseName + '.Name'],
96
+ 'RandomEnabled': response[gTourBaseName + '.RandomEnabled'],
97
+ 'Running': response[gTourBaseName + '.Running'],
98
+ 'TimeBetweenSequences': response[gTourBaseName + '.TimeBetweenSequences'],
99
+ 'Tour': []
100
+ };
101
+ for (let j = 0; j < 100; j++) {
102
+ let tourBaseName = 'root.GuardTour.G' + i + '.Tour.T' + j;
103
+ if (tourBaseName + '.MoveSpeed' in response) {
104
+ let tour = {
105
+ 'MoveSpeed': response[tourBaseName + '.MoveSpeed'],
106
+ 'Position': response[tourBaseName + '.Position'],
107
+ 'PresetNbr': response[tourBaseName + '.PresetNbr'],
108
+ 'WaitTime': response[tourBaseName + '.WaitTime'],
109
+ 'WaitTimeViewType': response[tourBaseName + '.WaitTimeViewType']
110
+ };
111
+ gTour.Tour.push(tour);
112
+ }
113
+ }
114
+ gTourList.push(gTour);
115
+ } else {
116
+ break;
117
+ }
118
+ }
119
+ resolve(gTourList);
120
+ }, reject)
121
+ });
122
+ return promise;
123
+ }
136
124
 
137
- CameraVapix.prototype.setOutputState = function(port, active) {
138
- return this.vapixPost('/axis-cgi/io/port.cgi', 'action=' + encodeURIComponent(port) + ':' + (active ? '/' : '\\'));
139
- }
125
+ setGuardTourEnabled(gourTourID, enable) {
126
+ let options = {};
127
+ options[gourTourID + '.Running'] = enable ? 'yes' : 'no';
128
+ return this.setParameter(options);
129
+ }
130
+
131
+ getInputState(port) {
132
+ let promise = new Promise((resolve, reject) => {
133
+ this.vapixPost('/axis-cgi/io/port.cgi', 'checkactive=' + encodeURIComponent(port)).then((response) => {
134
+ resolve(response.split('=')[1].indexOf('active') == 0);
135
+ }, reject);
136
+ });
137
+ return promise;
138
+ }
139
+
140
+ setOutputState(port, active) {
141
+ return this.vapixPost('/axis-cgi/io/port.cgi', 'action=' + encodeURIComponent(port) + ':' + (active ? '/' : '\\'));
142
+ }
143
+
144
+ getApplicationList() {
145
+ const promise = new Promise((resolve, reject) => {
146
+ this.vapixGet('/axis-cgi/applications/list.cgi').then((xml) => {
147
+ parseString(xml, (err, result) => {
148
+ if (err) {
149
+ reject(err);
150
+ return;
151
+ }
152
+ let apps = [];
153
+ for (let i = 0; i < result.reply.application.length; i++) {
154
+ apps.push(result.reply.application[i].$);
155
+ }
156
+ resolve(apps);
157
+ });
158
+ }, reject);
159
+ });
160
+ return promise;
161
+ }
162
+
163
+ getEventDeclarations() {
164
+ const promise = new Promise((resolve, reject) => {
165
+ let data =
166
+ '<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">' +
167
+ '<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' +
168
+ 'xmlns:xsd="http://www.w3.org/2001/XMLSchema">' +
169
+ '<GetEventInstances xmlns="http://www.axis.com/vapix/ws/event1"/>' +
170
+ '</s:Body>' +
171
+ '</s:Envelope>';
172
+ this.vapixPost('/vapix/services', data, 'application/soap+xml').then((declarations) => {
173
+ resolve(prettifyXml(declarations));
174
+ }, reject);
175
+ });
176
+ return promise;
177
+ }
178
+
179
+ isReservedEventName(eventName) {
180
+ return (eventName == 'eventsConnect' || eventName == 'eventsDisconnect');
181
+ }
140
182
 
141
- CameraVapix.prototype.getApplicationList = function() {
142
- var promise = new Promise(function(resolve, reject) {
143
- this.vapixGet('/axis-cgi/applications/list.cgi').then(function(xml) {
144
- parseString(xml, function (err, result) {
145
- if (err) {
146
- reject(err);
147
- return;
183
+ eventsConnect(channel = "RTSP") {
184
+ if (this.ws != null) {
185
+ throw new Error("Websocket is already opened.");
148
186
  }
149
- var apps = [];
150
- for (var i = 0; i < result.reply.application.length; i++) {
151
- apps.push(result.reply.application[i].$);
187
+ if (this.rtsp != null) {
188
+ throw new Error("RTSP is already opened.");
152
189
  }
153
- resolve(apps);
154
- });
155
- }, reject);
156
- }.bind(this));
157
- return promise;
158
- }
159
-
160
- CameraVapix.prototype.getEventDeclarations = function() {
161
- var promise = new Promise(function(resolve, reject) {
162
- var data =
163
- '<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">' +
164
- '<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' +
165
- 'xmlns:xsd="http://www.w3.org/2001/XMLSchema">' +
166
- '<GetEventInstances xmlns="http://www.axis.com/vapix/ws/event1"/>' +
167
- '</s:Body>' +
168
- '</s:Envelope>';
169
- this.vapixPost('/vapix/services', data, 'application/soap+xml').then(function(declarations) {
170
- resolve(prettifyXml(declarations));
171
- }, reject);
172
- }.bind(this));
173
- return promise;
174
- }
190
+ if (channel == "RTSP") {
191
+ this.rtspConnect();
192
+ }
193
+ else if (channel == "websocket") {
194
+ this.websocketConnect();
195
+ }
196
+ else {
197
+ throw new Error("Unknown channel.");
198
+ }
199
+ }
175
200
 
176
- CameraVapix.prototype.eventsConnect = function() {
177
- this.rtsp = new RtspClient({
178
- 'ip': this.ip,
179
- 'port': this.port,
180
- 'auth': this.auth,
181
- });
182
-
183
- this.rtsp.on('connect', function() { this.emit('eventsConnect'); }.bind(this));
184
- this.rtsp.on('disconnect', function(err) { this.emit('eventsDisconnect', err); }.bind(this));
185
- this.rtsp.on('event', function(event) {
186
- var eventNames = this.eventNames();
187
- for (var i = 0; i < eventNames.length; i++) {
188
- if (eventNames[i] != 'eventsConnect' && eventNames[i] != 'eventsDisconnect') {
189
- var name = eventNames[i];
190
- // Remove special chars from the end
191
- while (name[name.length - 1] == '.' || name[name.length - 1] == '/') {
192
- name = name.substring(0, name.length - 1);
201
+ eventsDisconnect() {
202
+ if (this.rtsp != null) {
203
+ this.rtsp.disconnect();
193
204
  }
194
- // Find registered event name in the message
195
- if (event.indexOf(name) != -1) {
196
- // Convert to JSON and emit signal
197
- parseString(event, function (err, eventJson) {
198
- if (err) {
199
- this.eventsDisconnect();
200
- return;
205
+ if (this.ws != null) {
206
+ this.ws.close();
207
+ }
208
+ }
209
+
210
+ rtspConnect() {
211
+ this.rtsp = new RtspClient({
212
+ 'ip': this.ip,
213
+ 'port': this.port,
214
+ 'auth': this.auth,
215
+ });
216
+
217
+ this.rtsp.on('connect', () => {
218
+ this.emit('eventsConnect');
219
+ });
220
+ this.rtsp.on('disconnect', (err) => {
221
+ this.emit('eventsDisconnect', err);
222
+ this.rtsp = null;
223
+ });
224
+ this.rtsp.on('event', (event) => {
225
+ let eventNames = this.eventNames();
226
+ for (let i = 0; i < eventNames.length; i++) {
227
+ if (!this.isReservedEventName(eventNames[i])) {
228
+ let name = eventNames[i];
229
+ // Remove special chars from the end
230
+ while (name[name.length - 1] == '.' || name[name.length - 1] == '/') {
231
+ name = name.substring(0, name.length - 1);
232
+ }
233
+ // Find registered event name in the message
234
+ if (event.indexOf(name) != -1) {
235
+ // Convert to JSON and emit signal
236
+ parseString(event, (err, eventJson) => {
237
+ if (err) {
238
+ this.eventsDisconnect();
239
+ return;
240
+ }
241
+ this.emit(eventNames[i], eventJson);
242
+ });
243
+ break;
244
+ }
245
+ }
246
+ }
247
+ });
248
+
249
+ let eventTopicFilter = '';
250
+ let eventNames = this.eventNames();
251
+ for (let i = 0; i < eventNames.length; i++) {
252
+ if (!this.isReservedEventName(eventNames[i])) {
253
+ if (eventTopicFilter.length != 0) {
254
+ eventTopicFilter += '|';
255
+ }
256
+
257
+ let topic = eventNames[i].replace(/tns1/g, 'onvif');
258
+ topic = topic.replace(/tnsaxis/g, 'axis');
259
+ eventTopicFilter += topic;
201
260
  }
202
- this.emit(eventNames[i], eventJson);
203
- }.bind(this));
204
- break;
205
261
  }
206
- }
262
+ this.rtsp.connect(eventTopicFilter);
207
263
  }
208
- }.bind(this));
209
-
210
- var eventTopicFilter = '';
211
- var eventNames = this.eventNames();
212
- for (var i = 0; i < eventNames.length; i++) {
213
- if (eventNames[i] != 'eventsConnect' && eventNames[i] != 'eventsDisconnect') {
214
- if (eventTopicFilter.length != 0) {
215
- eventTopicFilter += '|';
216
- }
217
-
218
- var topic = eventNames[i].replace(/tns1/g, 'onvif');
219
- topic = topic.replace(/tnsaxis/g, 'axis');
220
- eventTopicFilter += topic;
264
+
265
+ websocketConnect(digestHeader) {
266
+ const address = `ws://${this.ip}:${this.port}/vapix/ws-data-stream?sources=events`;
267
+
268
+ let options =
269
+ {
270
+ 'auth': this.auth
271
+ };
272
+
273
+ if (digestHeader !== undefined) {
274
+ let userPass = this.auth.split(':');
275
+ options.headers = options.headers || {};
276
+ options['headers']['Authorization'] = Digest.getAuthHeader(userPass[0], userPass[1], 'GET', '/vapix/ws-data-stream?sources=events', digestHeader);
277
+ }
278
+
279
+ return new Promise((resolve, reject) => {
280
+ this.ws = new WebSocket(address, options);
281
+
282
+ this.ws.on('open', () => {
283
+ let topics = [];
284
+ let eventNames = this.eventNames();
285
+ for (let i = 0; i < eventNames.length; i++) {
286
+ if (!this.isReservedEventName(eventNames[i])) {
287
+ let topic =
288
+ {
289
+ "topicFilter": eventNames[i]
290
+ }
291
+ topics.push(topic);
292
+ }
293
+ }
294
+
295
+ const topicFilter = {
296
+ "apiVersion": "1.0",
297
+ "method": "events:configure",
298
+ "params": {
299
+ "eventFilterList": topics
300
+ }
301
+ }
302
+ this.ws.send(JSON.stringify(topicFilter));
303
+ });
304
+
305
+ this.ws.on('unexpected-response', (req, res) => {
306
+ if (res.statusCode == 401 && res.headers['www-authenticate'] != undefined)
307
+ this.websocketConnect(res.headers['www-authenticate']).then(resolve, reject);
308
+ else {
309
+ reject('Error: status code: ' + res.statusCode + ', ' + res.data);
310
+ }
311
+ });
312
+
313
+ this.ws.on('message', (data) => {
314
+ let dataJSON = JSON.parse(data);
315
+ if (dataJSON.method === 'events:configure') {
316
+ if (dataJSON.error === undefined) {
317
+ this.emit("eventsConnect");
318
+ }
319
+ else {
320
+ this.emit("eventsDisconnect", dataJSON.error);
321
+ this.eventsDisconnect();
322
+ }
323
+ return;
324
+ }
325
+ let eventName = dataJSON.params.notification.topic;
326
+ this.emit(eventName, dataJSON);
327
+ });
328
+ this.ws.on('error', (error) => {
329
+ this.emit("eventsDisconnect", error);
330
+ this.ws = null;
331
+ });
332
+ this.ws.on('close', () => {
333
+ if (this.ws !== null) {
334
+ this.emit("websocketDisconnect");
335
+ }
336
+ this.ws = null;
337
+ });
338
+ });
221
339
  }
222
- }
223
- this.rtsp.connect(eventTopicFilter);
224
- }
225
340
 
226
- CameraVapix.prototype.eventsDisconnect = function() {
227
- if (this.rtsp) {
228
- this.rtsp.disconnect();
229
- this.rtsp = null;
230
- }
231
- }
341
+ vapixGet(path, noWaitForData) {
342
+ let options = this.getBaseVapixConnectionParams();
343
+ options['path'] = encodeURI(path);
344
+ return httpRequest(options, undefined, noWaitForData);
345
+ }
232
346
 
233
- CameraVapix.prototype.vapixGet = function(path) {
234
- var options = this.getBaseVapixConnectionParams();
235
- options['path'] = encodeURI(path);
236
- return httpRequest(options);
237
- }
347
+ async getCameraImage(camera, compression, resolution, outputStream) {
348
+ const path = `/axis-cgi/jpg/image.cgi?resolution=${resolution}&compression=${compression}&camera=${camera}`;
349
+ const res = await this.vapixGet(path, true);
350
+ res.pipe(outputStream);
351
+ return outputStream;
352
+ }
238
353
 
239
- CameraVapix.prototype.vapixPost = function(path, data, contentType) {
240
- var options = this.getBaseVapixConnectionParams();
241
- options['method'] = 'POST';
242
- options['path'] = path;
243
- if (contentType) {
244
- options['headers'] = {'Content-Type': contentType};
245
- }
246
- return httpRequest(options, data);
247
- }
354
+ vapixPost(path, data, contentType) {
355
+ let options = this.getBaseVapixConnectionParams();
356
+ options['method'] = 'POST';
357
+ options['path'] = path;
358
+ if (contentType) {
359
+ options['headers'] = { 'Content-Type': contentType };
360
+ }
361
+ return httpRequest(options, data);
362
+ }
248
363
 
249
- CameraVapix.prototype.getBaseVapixConnectionParams = function(options, postData) {
250
- return {
251
- 'protocol': this.protocol + ':',
252
- 'host': this.ip,
253
- 'port': this.port,
254
- 'auth': this.auth
255
- };
364
+ getBaseVapixConnectionParams(options, postData) {
365
+ return {
366
+ 'protocol': this.protocol + ':',
367
+ 'host': this.ip,
368
+ 'port': this.port,
369
+ 'auth': this.auth
370
+ };
371
+ }
256
372
  }
257
-
258
373
  module.exports = CameraVapix;
package/HTTPRequest.js CHANGED
@@ -1,73 +1,118 @@
1
1
  const http = require("http");
2
- const Digest = require('./Digest');
2
+ const https = require("https");
3
+ const Digest = require("./Digest");
3
4
 
4
- function httpRequest(options, postData) {
5
- return new Promise(function(resolve, reject) {
6
- if (postData != undefined) {
7
- options.headers = options.headers || {}
8
- if (options.headers['Content-Type'] == undefined) {
9
- options.headers['Content-Type'] = 'application/x-www-form-urlencoded';
5
+ function httpRequest(options, postData, noWaitForData) {
6
+ return new Promise(
7
+ function (resolve, reject) {
8
+ if (postData !== undefined) {
9
+ options.headers = options.headers || {};
10
+ if (options.headers["Content-Type"] == undefined) {
11
+ options.headers["Content-Type"] = "application/x-www-form-urlencoded";
12
+ }
13
+ options.headers["Content-Length"] = Buffer.byteLength(postData);
10
14
  }
11
- options.headers['Content-Length'] = Buffer.byteLength(postData);
12
- }
13
15
 
14
- request(options, postData).then(function(response) {
15
- if (response.resp.statusCode == 200) {
16
- resolve(response.data);
17
- } else if (response.resp.statusCode == 401) {
18
- if (response.resp.headers['www-authenticate'] != undefined && response.resp.headers['www-authenticate'].indexOf('Digest') != -1) {
19
- request(options, postData, response.resp.headers['www-authenticate']).then(function(response) {
20
- if (response.resp.statusCode == 200) {
21
- resolve(response.data);
22
- } else {
23
- reject('Error: status code: ' + response.resp.statusCode + ', ' + response.data);
24
- }
25
- }, reject);
16
+ request(options, postData, undefined, noWaitForData).then(function (response) {
17
+ if (response.resp.statusCode == 200) {
18
+ if (noWaitForData){
19
+ resolve(response.resp);
20
+ }else{
21
+ resolve(response.data);
22
+ }
23
+ } else if (response.resp.statusCode == 401) {
24
+ if (
25
+ response.resp.headers["www-authenticate"] != undefined &&
26
+ response.resp.headers["www-authenticate"].indexOf("Digest") != -1
27
+ ) {
28
+ request(
29
+ options,
30
+ postData,
31
+ response.resp.headers["www-authenticate"],
32
+ noWaitForData
33
+ ).then(function (response) {
34
+ if (response.resp.statusCode == 200) {
35
+ if (noWaitForData){
36
+ resolve(response.resp);
37
+ }else{
38
+ resolve(response.data);
39
+ }
40
+
41
+ } else {
42
+ reject(
43
+ "Error: status code: " +
44
+ response.resp.statusCode +
45
+ ", " +
46
+ response.data
47
+ );
48
+ }
49
+ }, reject);
50
+ } else {
51
+ reject(
52
+ "Error: status code: " +
53
+ response.resp.statusCode +
54
+ ", " +
55
+ response.data
56
+ );
57
+ }
26
58
  } else {
27
- reject('Error: status code: ' + response.resp.statusCode + ', ' + response.data);
59
+ reject(
60
+ "Error: status code: " +
61
+ response.resp.statusCode +
62
+ ", " +
63
+ response.data
64
+ );
28
65
  }
29
- } else {
30
- reject('Error: status code: ' + response.resp.statusCode + ', ' + response.data);
31
- }
32
- }, reject);
33
- }.bind(this));
66
+ }, reject);
67
+ }.bind(this)
68
+ );
34
69
  }
35
70
 
36
- function request(options, postData, digestHeader) {
37
- return new Promise(function(resolve, reject) {
71
+ function request(options, postData, digestHeader, noWaitForData) {
72
+ return new Promise((resolve, reject) => {
38
73
  if (digestHeader != undefined) {
39
- var auth = options.auth;
74
+ let auth = options.auth;
40
75
  if (auth == undefined) {
41
- reject('No credentials found');
42
- return;
76
+ reject("No credentials found");
43
77
  }
44
- auth = auth.split(':');
78
+ auth = auth.split(":");
45
79
  delete options.auth;
46
80
 
47
81
  if (options.method == undefined) {
48
- options.method = 'GET';
82
+ options.method = "GET";
49
83
  }
50
84
 
51
- options.headers = options.headers || {}
52
- options['headers']['Authorization'] = Digest.getAuthHeader(auth[0], auth[1], options.method, options.path, digestHeader);
85
+ options.headers = options.headers || {};
86
+ options["headers"]["Authorization"] = Digest.getAuthHeader(
87
+ auth[0],
88
+ auth[1],
89
+ options.method,
90
+ options.path,
91
+ digestHeader
92
+ );
53
93
  }
54
94
  let client = http;
55
95
 
56
- if (options.protocol && options.protocol==='https:'){
96
+ if (options.protocol && options.protocol === "https:") {
57
97
  client = https;
58
98
  }
59
-
60
- var req = client.request(options, function(resp) {
61
-   var data = '';
62
-   resp.on('data', (chunk) => {
63
-     data += chunk;
99
+ let req = client
100
+ .request(options, function (resp) {
101
+ if (!noWaitForData){
102
+ let data = "";
103
+ resp.on("data", (chunk) => {
104
+ data += chunk;
105
+ });
106
+ resp.on("end", () => {
107
+ resolve({ 'resp': resp, 'data': data });
108
+ });
109
+ } else {
110
+ resolve({'resp' : resp});
111
+ }
112
+ }).on("error", (err) => {
113
+ reject(err.message);
64
114
  });
65
-   resp.on('end', () => {
66
- resolve({'resp': resp, 'data': data});
67
-   });
68
- }).on('error', (err) => {
69
- reject(err.message);
70
- });
115
+
71
116
  if (postData != undefined) {
72
117
  req.write(postData);
73
118
  }
@@ -75,4 +120,4 @@ function request(options, postData, digestHeader) {
75
120
  });
76
121
  }
77
122
 
78
- module.exports = httpRequest
123
+ module.exports = httpRequest;
package/HttpServer.js CHANGED
@@ -4,7 +4,7 @@ const fs = require('fs');
4
4
  const path = require('path');
5
5
  const EventEmitter = require('events');
6
6
 
7
- export class HttpServer extends EventEmitter {
7
+ class HttpServer extends EventEmitter {
8
8
  constructor(options) {
9
9
  super();
10
10
  this.port = process.env.HTTP_PORT;
@@ -97,4 +97,6 @@ export class HttpServer extends EventEmitter {
97
97
  this.sockets[socketID].destroy();
98
98
  }
99
99
  }
100
- }
100
+ }
101
+
102
+ module.exports = HttpServer;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "camstreamerlib",
3
- "version": "1.3.0",
3
+ "version": "1.5.0",
4
4
  "description": "Helper library for CamStreamer ACAP applications.",
5
5
  "main": "CameraVapix.js",
6
6
  "dependencies": {