amqplib 0.5.2 → 0.5.6
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/.npmignore +8 -0
- package/CHANGELOG.md +68 -0
- package/Makefile +2 -1
- package/README.md +2 -2
- package/bin/generate-defs.js +723 -0
- package/examples/tutorials/package.json +1 -1
- package/lib/api_args.js +2 -0
- package/lib/channel.js +28 -10
- package/lib/connect.js +6 -16
- package/lib/connection.js +2 -1
- package/lib/credentials.js +14 -0
- package/lib/defs.js +129 -1
- package/lib/mux.js +6 -21
- package/package-lock.json +711 -0
- package/package.json +11 -10
- package/test/channel.js +73 -61
- package/test/channel_api.js +13 -0
- package/test/connect.js +32 -7
- package/test/connection.js +47 -47
- package/test/mux.js +44 -6
- package/test/util.js +2 -2
package/lib/api_args.js
CHANGED
|
@@ -58,6 +58,8 @@ Args.assertQueue = function(queue, options) {
|
|
|
58
58
|
options.deadLetterRoutingKey);
|
|
59
59
|
setIfDefined(argt, 'x-max-length', options.maxLength);
|
|
60
60
|
setIfDefined(argt, 'x-max-priority', options.maxPriority);
|
|
61
|
+
setIfDefined(argt, 'x-overflow', options.overflow);
|
|
62
|
+
setIfDefined(argt, 'x-queue-mode', options.queueMode);
|
|
61
63
|
|
|
62
64
|
return {
|
|
63
65
|
queue: queue,
|
package/lib/channel.js
CHANGED
|
@@ -33,6 +33,12 @@ function Channel(connection) {
|
|
|
33
33
|
this.on('nack', this.handleConfirm.bind(this, function(cb) {
|
|
34
34
|
if (cb) cb(new Error('message nacked'));
|
|
35
35
|
}));
|
|
36
|
+
this.on('close', function () {
|
|
37
|
+
var cb;
|
|
38
|
+
while (cb = this.unconfirmed.shift()) {
|
|
39
|
+
if (cb) cb(new Error('channel closed'));
|
|
40
|
+
}
|
|
41
|
+
})
|
|
36
42
|
// message frame state machine
|
|
37
43
|
this.handleMessage = acceptDeliveryOrReturn;
|
|
38
44
|
}
|
|
@@ -103,9 +109,10 @@ C._rpc = function(method, fields, expect, cb) {
|
|
|
103
109
|
// We have detected a problem, so it's up to us to close the
|
|
104
110
|
// channel
|
|
105
111
|
var expectedName = methodName(expect);
|
|
112
|
+
|
|
106
113
|
var e = new Error(fmt("Expected %s; got %s",
|
|
107
114
|
expectedName, inspect(f, false)));
|
|
108
|
-
self.closeWithError(fmt('Expected %s; got %s',
|
|
115
|
+
self.closeWithError(f.id, fmt('Expected %s; got %s',
|
|
109
116
|
expectedName, methodName(f.id)),
|
|
110
117
|
defs.constants.UNEXPECTED_FRAME, e);
|
|
111
118
|
return cb(e);
|
|
@@ -124,7 +131,11 @@ C._rpc = function(method, fields, expect, cb) {
|
|
|
124
131
|
? fmt("Operation failed: %s; %s",
|
|
125
132
|
methodName(method), closeMsg(err))
|
|
126
133
|
: fmt("Channel closed by server: %s", closeMsg(err));
|
|
127
|
-
|
|
134
|
+
var closeFrameError = new Error(e);
|
|
135
|
+
closeFrameError.code = err.fields.replyCode;
|
|
136
|
+
closeFrameError.classId = err.fields.classId;
|
|
137
|
+
closeFrameError.methodId = err.fields.methodId;
|
|
138
|
+
return cb(closeFrameError);
|
|
128
139
|
}
|
|
129
140
|
}
|
|
130
141
|
|
|
@@ -186,7 +197,7 @@ C.toClosing = function(capturedStack, k) {
|
|
|
186
197
|
};
|
|
187
198
|
|
|
188
199
|
C._rejectPending = function() {
|
|
189
|
-
function rej(r) {
|
|
200
|
+
function rej(r) {
|
|
190
201
|
r(new Error("Channel ended, no reply will be forthcoming"));
|
|
191
202
|
}
|
|
192
203
|
if (this.reply !== null) rej(this.reply);
|
|
@@ -210,10 +221,15 @@ C.closeBecause = function(reason, code, k) {
|
|
|
210
221
|
// If we close because there's been an error, we need to distinguish
|
|
211
222
|
// between what we tell the server (`reason`) and what we report as
|
|
212
223
|
// the cause in the client (`error`).
|
|
213
|
-
C.closeWithError = function(reason, code, error) {
|
|
224
|
+
C.closeWithError = function(id, reason, code, error) {
|
|
214
225
|
var self = this;
|
|
215
226
|
this.closeBecause(reason, code, function() {
|
|
216
227
|
error.code = code;
|
|
228
|
+
// content frames and consumer errors do not provide a method a class/method ID
|
|
229
|
+
if (id) {
|
|
230
|
+
error.classId = defs.info(id).classId;
|
|
231
|
+
error.methodId = defs.info(id).methodId;
|
|
232
|
+
}
|
|
217
233
|
self.emit('error', error);
|
|
218
234
|
});
|
|
219
235
|
};
|
|
@@ -232,15 +248,15 @@ C.acceptMessageFrame = function(f) {
|
|
|
232
248
|
}
|
|
233
249
|
catch (msg) {
|
|
234
250
|
if (typeof msg === 'string') {
|
|
235
|
-
this.closeWithError(msg, defs.constants.UNEXPECTED_FRAME,
|
|
251
|
+
this.closeWithError(f.id, msg, defs.constants.UNEXPECTED_FRAME,
|
|
236
252
|
new Error(msg));
|
|
237
253
|
}
|
|
238
254
|
else if (msg instanceof Error) {
|
|
239
|
-
this.closeWithError('Error while processing message',
|
|
255
|
+
this.closeWithError(f.id, 'Error while processing message',
|
|
240
256
|
defs.constants.INTERNAL_ERROR, msg);
|
|
241
257
|
}
|
|
242
258
|
else {
|
|
243
|
-
this.closeWithError('Internal error while processing message',
|
|
259
|
+
this.closeWithError(f.id, 'Internal error while processing message',
|
|
244
260
|
defs.constants.INTERNAL_ERROR,
|
|
245
261
|
new Error(msg.toString()));
|
|
246
262
|
}
|
|
@@ -283,7 +299,7 @@ function acceptMessage(continuation) {
|
|
|
283
299
|
if (f.id === defs.BasicProperties) {
|
|
284
300
|
message.properties = f.fields;
|
|
285
301
|
totalSize = remaining = f.size;
|
|
286
|
-
|
|
302
|
+
|
|
287
303
|
// for zero-length messages, content frames aren't required.
|
|
288
304
|
if (totalSize === 0) {
|
|
289
305
|
message.content = Buffer.alloc(0);
|
|
@@ -291,7 +307,7 @@ function acceptMessage(continuation) {
|
|
|
291
307
|
return acceptDeliveryOrReturn;
|
|
292
308
|
}
|
|
293
309
|
else {
|
|
294
|
-
return content;
|
|
310
|
+
return content;
|
|
295
311
|
}
|
|
296
312
|
}
|
|
297
313
|
else {
|
|
@@ -405,6 +421,8 @@ C.accept = function(f) {
|
|
|
405
421
|
|
|
406
422
|
var error = new Error(emsg);
|
|
407
423
|
error.code = f.fields.replyCode;
|
|
424
|
+
error.classId = f.fields.classId;
|
|
425
|
+
error.methodId = f.fields.methodId;
|
|
408
426
|
this.emit('error', error);
|
|
409
427
|
|
|
410
428
|
var s = stackCapture(emsg);
|
|
@@ -413,7 +431,7 @@ C.accept = function(f) {
|
|
|
413
431
|
|
|
414
432
|
case defs.BasicFlow:
|
|
415
433
|
// RabbitMQ doesn't send this, it just blocks the TCP socket
|
|
416
|
-
return this.closeWithError("Flow not implemented",
|
|
434
|
+
return this.closeWithError(f.id, "Flow not implemented",
|
|
417
435
|
defs.constants.NOT_IMPLEMENTED,
|
|
418
436
|
new Error('Flow not implemented'));
|
|
419
437
|
|
package/lib/connect.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
|
-
var URL = require('url');
|
|
9
|
+
var URL = require('url-parse');
|
|
10
10
|
var QS = require('querystring');
|
|
11
11
|
var Connection = require('./connection').Connection;
|
|
12
12
|
var fmt = require('util').format;
|
|
@@ -76,22 +76,12 @@ function openFrames(vhost, query, credentials, extraClientProperties) {
|
|
|
76
76
|
};
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
// Decide on credentials based on what we're supplied.
|
|
80
|
-
// parsed URL, the auth part is already URL-decoded, so e.g., '%3a' in
|
|
81
|
-
// the URL is already decoded to ':'. This is a bit unhelpful, as it
|
|
82
|
-
// means we can't tell whether a colon is a separator, or part of the
|
|
83
|
-
// username. Assume no colons in usernames.
|
|
79
|
+
// Decide on credentials based on what we're supplied.
|
|
84
80
|
function credentialsFromUrl(parts) {
|
|
85
81
|
var user = 'guest', passwd = 'guest';
|
|
86
|
-
if (parts.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
user = parts.auth;
|
|
90
|
-
passwd = '';
|
|
91
|
-
} else {
|
|
92
|
-
user = parts.auth.substring(0, colon);
|
|
93
|
-
passwd = parts.auth.substring(colon+1);
|
|
94
|
-
}
|
|
82
|
+
if (parts.username != '' || parts.password != '') {
|
|
83
|
+
user = (parts.username) ? unescape(parts.username) : '';
|
|
84
|
+
passwd = (parts.password) ? unescape(parts.password) : '';
|
|
95
85
|
}
|
|
96
86
|
return credentials.plain(user, passwd);
|
|
97
87
|
}
|
|
@@ -137,7 +127,7 @@ function connect(url, socketOptions, openCallback) {
|
|
|
137
127
|
|
|
138
128
|
fields = openFrames(url.vhost, config, sockopts.credentials || credentials.plain(user, pass), extraClientProperties);
|
|
139
129
|
} else {
|
|
140
|
-
var parts = URL
|
|
130
|
+
var parts = URL(url, true); // yes, parse the query string
|
|
141
131
|
protocol = parts.protocol;
|
|
142
132
|
sockopts.host = parts.hostname;
|
|
143
133
|
sockopts.port = parseInt(parts.port) || ((protocol === 'amqp:') ? 5672 : 5671);
|
package/lib/connection.js
CHANGED
|
@@ -205,6 +205,7 @@ C.open = function(allFields, openCallback0) {
|
|
|
205
205
|
allFields.mechanism)));
|
|
206
206
|
return;
|
|
207
207
|
}
|
|
208
|
+
self.serverProperties = start.fields.serverProperties;
|
|
208
209
|
send(defs.ConnectionStartOk);
|
|
209
210
|
wait(afterStartOk);
|
|
210
211
|
}
|
|
@@ -465,7 +466,7 @@ C.freshChannel = function(channel, options) {
|
|
|
465
466
|
C.releaseChannel = function(channel) {
|
|
466
467
|
this.freeChannels.clear(channel);
|
|
467
468
|
var buffer = this.channels[channel].buffer;
|
|
468
|
-
|
|
469
|
+
buffer.end(); // will also cause it to be unpiped
|
|
469
470
|
this.channels[channel] = null;
|
|
470
471
|
};
|
|
471
472
|
|
package/lib/credentials.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
// * EXTERNAL (assume the server will figure out who you are from
|
|
10
10
|
// context, i.e., your SSL certificate)
|
|
11
11
|
var Buffer = require('safe-buffer').Buffer
|
|
12
|
+
var codec = require('./codec')
|
|
12
13
|
|
|
13
14
|
module.exports.plain = function(user, passwd) {
|
|
14
15
|
return {
|
|
@@ -21,6 +22,19 @@ module.exports.plain = function(user, passwd) {
|
|
|
21
22
|
}
|
|
22
23
|
}
|
|
23
24
|
|
|
25
|
+
module.exports.amqplain = function(user, passwd) {
|
|
26
|
+
return {
|
|
27
|
+
mechanism: 'AMQPLAIN',
|
|
28
|
+
response: function() {
|
|
29
|
+
const buffer = Buffer.alloc(16384);
|
|
30
|
+
const size = codec.encodeTable(buffer, { LOGIN: user, PASSWORD: passwd}, 0);
|
|
31
|
+
return buffer.slice(4, size);
|
|
32
|
+
},
|
|
33
|
+
username: user,
|
|
34
|
+
password: passwd
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
24
38
|
module.exports.external = function() {
|
|
25
39
|
return {
|
|
26
40
|
mechanism: 'EXTERNAL',
|