amqplib 0.4.2 → 0.5.3
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/CHANGELOG.md +88 -0
- package/Makefile +2 -1
- package/README.md +4 -4
- package/callback_api.js +1 -0
- package/channel_api.js +7 -6
- package/examples/headers.js +2 -2
- package/examples/receive_generator.js +39 -0
- package/examples/send_generators.js +42 -0
- package/examples/ssl.js +1 -1
- package/examples/tutorials/README.md +1 -1
- package/examples/tutorials/callback_api/emit_log.js +1 -1
- package/examples/tutorials/callback_api/emit_log_direct.js +1 -1
- package/examples/tutorials/callback_api/emit_log_topic.js +1 -1
- package/examples/tutorials/callback_api/new_task.js +1 -1
- package/examples/tutorials/callback_api/rpc_client.js +1 -1
- package/examples/tutorials/callback_api/rpc_server.js +1 -1
- package/examples/tutorials/callback_api/send.js +1 -1
- package/examples/tutorials/emit_log.js +4 -5
- package/examples/tutorials/emit_log_direct.js +4 -5
- package/examples/tutorials/emit_log_topic.js +4 -5
- package/examples/tutorials/new_task.js +5 -6
- package/examples/tutorials/package.json +2 -3
- package/examples/tutorials/receive.js +4 -4
- package/examples/tutorials/receive_logs.js +1 -1
- package/examples/tutorials/receive_logs_direct.js +2 -2
- package/examples/tutorials/receive_logs_topic.js +6 -6
- package/examples/tutorials/rpc_client.js +25 -26
- package/examples/tutorials/rpc_server.js +2 -2
- package/examples/tutorials/send.js +4 -5
- package/examples/tutorials/worker.js +1 -1
- package/examples/waitForConfirms.js +2 -2
- package/lib/api_args.js +2 -0
- package/lib/callback_model.js +11 -10
- package/lib/channel.js +24 -12
- package/lib/channel_model.js +57 -65
- package/lib/codec.js +64 -38
- package/lib/connect.js +26 -15
- package/lib/connection.js +6 -4
- package/lib/credentials.js +20 -3
- package/lib/defs.js +203 -75
- package/lib/frame.js +2 -1
- package/lib/heartbeat.js +1 -1
- package/package.json +10 -8
- package/test/callback_api.js +6 -5
- package/test/channel.js +125 -107
- package/test/channel_api.js +125 -136
- package/test/codec.js +48 -9
- package/test/connect.js +88 -3
- package/test/connection.js +57 -56
- package/test/data.js +32 -9
- package/test/frame.js +4 -4
- package/test/mux.js +10 -6
- package/test/util.js +35 -21
- package/.npmignore +0 -9
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
var amqp = require('amqplib');
|
|
4
|
-
var when = require('when');
|
|
5
4
|
|
|
6
5
|
amqp.connect('amqp://localhost').then(function(conn) {
|
|
7
|
-
return
|
|
6
|
+
return conn.createChannel().then(function(ch) {
|
|
8
7
|
var q = 'hello';
|
|
9
8
|
var msg = 'Hello World!';
|
|
10
9
|
|
|
@@ -16,9 +15,9 @@ amqp.connect('amqp://localhost').then(function(conn) {
|
|
|
16
15
|
// (when `false`) that you should wait for the event `'drain'`
|
|
17
16
|
// to fire before writing again. We're just doing the one write,
|
|
18
17
|
// so we'll ignore it.
|
|
19
|
-
ch.sendToQueue(q,
|
|
18
|
+
ch.sendToQueue(q, Buffer.from(msg));
|
|
20
19
|
console.log(" [x] Sent '%s'", msg);
|
|
21
20
|
return ch.close();
|
|
22
21
|
});
|
|
23
|
-
})
|
|
24
|
-
}).
|
|
22
|
+
}).finally(function() { conn.close(); });
|
|
23
|
+
}).catch(console.warn);
|
|
@@ -12,11 +12,11 @@ function mkCallback(i) {
|
|
|
12
12
|
amqp.connect().then(function(c) {
|
|
13
13
|
c.createConfirmChannel().then(function(ch) {
|
|
14
14
|
for (var i=0; i < NUM_MSGS; i++) {
|
|
15
|
-
ch.publish('amq.topic', 'whatever',
|
|
15
|
+
ch.publish('amq.topic', 'whatever', Buffer.from('blah'), {}, mkCallback(i));
|
|
16
16
|
}
|
|
17
17
|
ch.waitForConfirms().then(function() {
|
|
18
18
|
console.log('All messages done');
|
|
19
19
|
c.close();
|
|
20
|
-
}
|
|
20
|
+
}).catch(console.error);
|
|
21
21
|
});
|
|
22
22
|
});
|
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/callback_model.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
'use strict';
|
|
6
6
|
|
|
7
7
|
var defs = require('./defs');
|
|
8
|
-
var
|
|
8
|
+
var Promise = require('bluebird');
|
|
9
9
|
var inherits = require('util').inherits;
|
|
10
10
|
var EventEmitter = require('events').EventEmitter;
|
|
11
11
|
var BaseChannel = require('./channel').BaseChannel;
|
|
@@ -215,7 +215,7 @@ Channel.prototype.get = function(queue, options, cb0) {
|
|
|
215
215
|
if (f.id === defs.BasicGetEmpty) {
|
|
216
216
|
cb(null, false);
|
|
217
217
|
}
|
|
218
|
-
else if (f.id
|
|
218
|
+
else if (f.id === defs.BasicGetOk) {
|
|
219
219
|
self.handleMessage = acceptMessage(function(m) {
|
|
220
220
|
m.fields = f.fields;
|
|
221
221
|
cb(null, m);
|
|
@@ -313,15 +313,16 @@ ConfirmChannel.prototype.waitForConfirms = function(k) {
|
|
|
313
313
|
unconfirmed.forEach(function(val, index) {
|
|
314
314
|
if (val === null); // already confirmed
|
|
315
315
|
else {
|
|
316
|
-
var confirmed =
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
316
|
+
var confirmed = new Promise(function(resolve, reject) {
|
|
317
|
+
unconfirmed[index] = function(err) {
|
|
318
|
+
if (val) val(err);
|
|
319
|
+
if (err === null) resolve();
|
|
320
|
+
else reject(err);
|
|
321
|
+
};
|
|
322
|
+
});
|
|
323
|
+
awaiting.push(confirmed);
|
|
323
324
|
}
|
|
324
325
|
});
|
|
325
|
-
return
|
|
326
|
+
return Promise.all(awaiting).then(function() { k(); },
|
|
326
327
|
function(err) { k(err); });
|
|
327
328
|
};
|
package/lib/channel.js
CHANGED
|
@@ -16,7 +16,7 @@ var EventEmitter = require('events').EventEmitter;
|
|
|
16
16
|
var fmt = require('util').format;
|
|
17
17
|
var IllegalOperationError = require('./error').IllegalOperationError;
|
|
18
18
|
var stackCapture = require('./error').stackCapture;
|
|
19
|
-
|
|
19
|
+
var Buffer = require('safe-buffer').Buffer
|
|
20
20
|
function Channel(connection) {
|
|
21
21
|
EventEmitter.call( this );
|
|
22
22
|
this.connection = connection;
|
|
@@ -103,9 +103,10 @@ C._rpc = function(method, fields, expect, cb) {
|
|
|
103
103
|
// We have detected a problem, so it's up to us to close the
|
|
104
104
|
// channel
|
|
105
105
|
var expectedName = methodName(expect);
|
|
106
|
+
|
|
106
107
|
var e = new Error(fmt("Expected %s; got %s",
|
|
107
108
|
expectedName, inspect(f, false)));
|
|
108
|
-
self.closeWithError(fmt('Expected %s; got %s',
|
|
109
|
+
self.closeWithError(f.id, fmt('Expected %s; got %s',
|
|
109
110
|
expectedName, methodName(f.id)),
|
|
110
111
|
defs.constants.UNEXPECTED_FRAME, e);
|
|
111
112
|
return cb(e);
|
|
@@ -124,7 +125,11 @@ C._rpc = function(method, fields, expect, cb) {
|
|
|
124
125
|
? fmt("Operation failed: %s; %s",
|
|
125
126
|
methodName(method), closeMsg(err))
|
|
126
127
|
: fmt("Channel closed by server: %s", closeMsg(err));
|
|
127
|
-
|
|
128
|
+
var closeFrameError = new Error(e);
|
|
129
|
+
closeFrameError.code = err.fields.replyCode;
|
|
130
|
+
closeFrameError.classId = err.fields.classId;
|
|
131
|
+
closeFrameError.methodId = err.fields.methodId;
|
|
132
|
+
return cb(closeFrameError);
|
|
128
133
|
}
|
|
129
134
|
}
|
|
130
135
|
|
|
@@ -186,7 +191,7 @@ C.toClosing = function(capturedStack, k) {
|
|
|
186
191
|
};
|
|
187
192
|
|
|
188
193
|
C._rejectPending = function() {
|
|
189
|
-
function rej(r) {
|
|
194
|
+
function rej(r) {
|
|
190
195
|
r(new Error("Channel ended, no reply will be forthcoming"));
|
|
191
196
|
}
|
|
192
197
|
if (this.reply !== null) rej(this.reply);
|
|
@@ -210,10 +215,15 @@ C.closeBecause = function(reason, code, k) {
|
|
|
210
215
|
// If we close because there's been an error, we need to distinguish
|
|
211
216
|
// between what we tell the server (`reason`) and what we report as
|
|
212
217
|
// the cause in the client (`error`).
|
|
213
|
-
C.closeWithError = function(reason, code, error) {
|
|
218
|
+
C.closeWithError = function(id, reason, code, error) {
|
|
214
219
|
var self = this;
|
|
215
220
|
this.closeBecause(reason, code, function() {
|
|
216
221
|
error.code = code;
|
|
222
|
+
// content frames and consumer errors do not provide a method a class/method ID
|
|
223
|
+
if (id) {
|
|
224
|
+
error.classId = defs.info(id).classId;
|
|
225
|
+
error.methodId = defs.info(id).methodId;
|
|
226
|
+
}
|
|
217
227
|
self.emit('error', error);
|
|
218
228
|
});
|
|
219
229
|
};
|
|
@@ -232,15 +242,15 @@ C.acceptMessageFrame = function(f) {
|
|
|
232
242
|
}
|
|
233
243
|
catch (msg) {
|
|
234
244
|
if (typeof msg === 'string') {
|
|
235
|
-
this.closeWithError(msg, defs.constants.UNEXPECTED_FRAME,
|
|
245
|
+
this.closeWithError(f.id, msg, defs.constants.UNEXPECTED_FRAME,
|
|
236
246
|
new Error(msg));
|
|
237
247
|
}
|
|
238
248
|
else if (msg instanceof Error) {
|
|
239
|
-
this.closeWithError('Error while processing message',
|
|
249
|
+
this.closeWithError(f.id, 'Error while processing message',
|
|
240
250
|
defs.constants.INTERNAL_ERROR, msg);
|
|
241
251
|
}
|
|
242
252
|
else {
|
|
243
|
-
this.closeWithError('Internal error while processing message',
|
|
253
|
+
this.closeWithError(f.id, 'Internal error while processing message',
|
|
244
254
|
defs.constants.INTERNAL_ERROR,
|
|
245
255
|
new Error(msg.toString()));
|
|
246
256
|
}
|
|
@@ -283,15 +293,15 @@ function acceptMessage(continuation) {
|
|
|
283
293
|
if (f.id === defs.BasicProperties) {
|
|
284
294
|
message.properties = f.fields;
|
|
285
295
|
totalSize = remaining = f.size;
|
|
286
|
-
|
|
296
|
+
|
|
287
297
|
// for zero-length messages, content frames aren't required.
|
|
288
298
|
if (totalSize === 0) {
|
|
289
|
-
message.content =
|
|
299
|
+
message.content = Buffer.alloc(0);
|
|
290
300
|
continuation(message);
|
|
291
301
|
return acceptDeliveryOrReturn;
|
|
292
302
|
}
|
|
293
303
|
else {
|
|
294
|
-
return content;
|
|
304
|
+
return content;
|
|
295
305
|
}
|
|
296
306
|
}
|
|
297
307
|
else {
|
|
@@ -405,6 +415,8 @@ C.accept = function(f) {
|
|
|
405
415
|
|
|
406
416
|
var error = new Error(emsg);
|
|
407
417
|
error.code = f.fields.replyCode;
|
|
418
|
+
error.classId = f.fields.classId;
|
|
419
|
+
error.methodId = f.fields.methodId;
|
|
408
420
|
this.emit('error', error);
|
|
409
421
|
|
|
410
422
|
var s = stackCapture(emsg);
|
|
@@ -413,7 +425,7 @@ C.accept = function(f) {
|
|
|
413
425
|
|
|
414
426
|
case defs.BasicFlow:
|
|
415
427
|
// RabbitMQ doesn't send this, it just blocks the TCP socket
|
|
416
|
-
return this.closeWithError("Flow not implemented",
|
|
428
|
+
return this.closeWithError(f.id, "Flow not implemented",
|
|
417
429
|
defs.constants.NOT_IMPLEMENTED,
|
|
418
430
|
new Error('Flow not implemented'));
|
|
419
431
|
|
package/lib/channel_model.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
'use strict';
|
|
6
6
|
|
|
7
7
|
var defs = require('./defs');
|
|
8
|
-
var
|
|
8
|
+
var Promise = require('bluebird');
|
|
9
9
|
var inherits = require('util').inherits;
|
|
10
10
|
var EventEmitter = require('events').EventEmitter;
|
|
11
11
|
var BaseChannel = require('./channel').BaseChannel;
|
|
@@ -29,12 +29,7 @@ module.exports.ChannelModel = ChannelModel;
|
|
|
29
29
|
var CM = ChannelModel.prototype;
|
|
30
30
|
|
|
31
31
|
CM.close = function() {
|
|
32
|
-
|
|
33
|
-
this.connection.close(function (err) {
|
|
34
|
-
if (err === null) closed.resolve();
|
|
35
|
-
else closed.reject(err);
|
|
36
|
-
});
|
|
37
|
-
return closed.promise;
|
|
32
|
+
return Promise.fromCallback(this.connection.close.bind(this.connection));
|
|
38
33
|
};
|
|
39
34
|
|
|
40
35
|
// Channels
|
|
@@ -59,17 +54,18 @@ var C = Channel.prototype;
|
|
|
59
54
|
// response's fields; this is intended to be suitable for implementing
|
|
60
55
|
// API procedures.
|
|
61
56
|
C.rpc = function(method, fields, expect) {
|
|
62
|
-
var
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
57
|
+
var self = this;
|
|
58
|
+
return Promise.fromCallback(function(cb) {
|
|
59
|
+
return self._rpc(method, fields, expect, cb);
|
|
60
|
+
})
|
|
61
|
+
.then(function(f) {
|
|
62
|
+
return f.fields;
|
|
66
63
|
});
|
|
67
|
-
return reply.promise;
|
|
68
64
|
};
|
|
69
65
|
|
|
70
66
|
// Do the remarkably simple channel open handshake
|
|
71
67
|
C.open = function() {
|
|
72
|
-
return
|
|
68
|
+
return Promise.try(this.allocate.bind(this)).then(
|
|
73
69
|
function(ch) {
|
|
74
70
|
return ch.rpc(defs.ChannelOpen, {outOfBand: ""},
|
|
75
71
|
defs.ChannelOpenOk);
|
|
@@ -77,10 +73,11 @@ C.open = function() {
|
|
|
77
73
|
};
|
|
78
74
|
|
|
79
75
|
C.close = function() {
|
|
80
|
-
var
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
76
|
+
var self = this;
|
|
77
|
+
return Promise.fromCallback(function(cb) {
|
|
78
|
+
return self.closeBecause("Goodbye", defs.constants.REPLY_SUCCESS,
|
|
79
|
+
cb);
|
|
80
|
+
});
|
|
84
81
|
};
|
|
85
82
|
|
|
86
83
|
// === Public API, declaring queues and stuff ===
|
|
@@ -151,7 +148,7 @@ C.bindExchange = function(dest, source, pattern, argt) {
|
|
|
151
148
|
C.unbindExchange = function(dest, source, pattern, argt) {
|
|
152
149
|
return this.rpc(defs.ExchangeUnbind,
|
|
153
150
|
Args.unbindExchange(dest, source, pattern, argt),
|
|
154
|
-
defs.ExchangeUnbindOk);
|
|
151
|
+
defs.ExchangeUnbindOk);
|
|
155
152
|
};
|
|
156
153
|
|
|
157
154
|
// Working with messages
|
|
@@ -170,58 +167,52 @@ C.consume = function(queue, callback, options) {
|
|
|
170
167
|
// NB we want the callback to be run synchronously, so that we've
|
|
171
168
|
// registered the consumerTag before any messages can arrive.
|
|
172
169
|
var fields = Args.consume(queue, options);
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
else reply.reject(err);
|
|
182
|
-
});
|
|
183
|
-
return reply.promise;
|
|
170
|
+
return Promise.fromCallback(function(cb) {
|
|
171
|
+
self._rpc(defs.BasicConsume, fields, defs.BasicConsumeOk, cb);
|
|
172
|
+
})
|
|
173
|
+
.then(function(ok) {
|
|
174
|
+
self.registerConsumer(ok.fields.consumerTag, callback);
|
|
175
|
+
return ok.fields;
|
|
176
|
+
});
|
|
184
177
|
};
|
|
185
178
|
|
|
186
179
|
C.cancel = function(consumerTag) {
|
|
187
180
|
var self = this;
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
});
|
|
198
|
-
return reply.promise;
|
|
181
|
+
return Promise.fromCallback(function(cb) {
|
|
182
|
+
self._rpc(defs.BasicCancel, Args.cancel(consumerTag),
|
|
183
|
+
defs.BasicCancelOk,
|
|
184
|
+
cb);
|
|
185
|
+
})
|
|
186
|
+
.then(function(ok) {
|
|
187
|
+
self.unregisterConsumer(consumerTag);
|
|
188
|
+
return ok.fields;
|
|
189
|
+
});
|
|
199
190
|
};
|
|
200
191
|
|
|
201
192
|
C.get = function(queue, options) {
|
|
202
|
-
var reply = defer();
|
|
203
193
|
var self = this;
|
|
204
194
|
var fields = Args.get(queue, options);
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
195
|
+
return Promise.fromCallback(function(cb) {
|
|
196
|
+
return self.sendOrEnqueue(defs.BasicGet, fields, cb);
|
|
197
|
+
})
|
|
198
|
+
.then(function(f) {
|
|
199
|
+
if (f.id === defs.BasicGetEmpty) {
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
else if (f.id === defs.BasicGetOk) {
|
|
203
|
+
var fields = f.fields;
|
|
204
|
+
return new Promise(function(resolve) {
|
|
212
205
|
self.handleMessage = acceptMessage(function(m) {
|
|
213
206
|
m.fields = fields;
|
|
214
|
-
|
|
207
|
+
resolve(m);
|
|
215
208
|
});
|
|
216
|
-
}
|
|
217
|
-
else {
|
|
218
|
-
reply.reject(new Error("Unexpected response to BasicGet: " +
|
|
219
|
-
inspect(f)));
|
|
220
|
-
}
|
|
209
|
+
});
|
|
221
210
|
}
|
|
222
|
-
else
|
|
223
|
-
|
|
224
|
-
|
|
211
|
+
else {
|
|
212
|
+
throw new Error("Unexpected response to BasicGet: " +
|
|
213
|
+
inspect(f));
|
|
214
|
+
}
|
|
215
|
+
})
|
|
225
216
|
};
|
|
226
217
|
|
|
227
218
|
C.ack = function(message, allUpTo) {
|
|
@@ -313,14 +304,15 @@ CC.waitForConfirms = function() {
|
|
|
313
304
|
unconfirmed.forEach(function(val, index) {
|
|
314
305
|
if (val === null); // already confirmed
|
|
315
306
|
else {
|
|
316
|
-
var confirmed =
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
307
|
+
var confirmed = new Promise(function(resolve, reject) {
|
|
308
|
+
unconfirmed[index] = function(err) {
|
|
309
|
+
if (val) val(err);
|
|
310
|
+
if (err === null) resolve();
|
|
311
|
+
else reject(err);
|
|
312
|
+
};
|
|
313
|
+
});
|
|
314
|
+
awaiting.push(confirmed);
|
|
323
315
|
}
|
|
324
316
|
});
|
|
325
|
-
return
|
|
317
|
+
return Promise.all(awaiting);
|
|
326
318
|
};
|
package/lib/codec.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//
|
|
1
|
+
//
|
|
2
2
|
//
|
|
3
3
|
//
|
|
4
4
|
|
|
@@ -110,6 +110,40 @@ function encodeFieldValue(buffer, value, offset) {
|
|
|
110
110
|
type = value['!'];
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
// If it's a JS number, we'll have to guess what type to encode it
|
|
114
|
+
// as.
|
|
115
|
+
if (type == 'number') {
|
|
116
|
+
// Making assumptions about the kind of number (floating point
|
|
117
|
+
// v integer, signed, unsigned, size) desired is dangerous in
|
|
118
|
+
// general; however, in practice RabbitMQ uses only
|
|
119
|
+
// longstrings and unsigned integers in its arguments, and
|
|
120
|
+
// other clients generally conflate number types anyway. So
|
|
121
|
+
// the only distinction we care about is floating point vs
|
|
122
|
+
// integers, preferring integers since those can be promoted
|
|
123
|
+
// if necessary. If floating point is required, we may as well
|
|
124
|
+
// use double precision.
|
|
125
|
+
if (isFloatingPoint(val)) {
|
|
126
|
+
type = 'double';
|
|
127
|
+
}
|
|
128
|
+
else { // only signed values are used in tables by
|
|
129
|
+
// RabbitMQ. It *used* to (< v3.3.0) treat the byte 'b'
|
|
130
|
+
// type as unsigned, but most clients (and the spec)
|
|
131
|
+
// think it's signed, and now RabbitMQ does too.
|
|
132
|
+
if (val < 128 && val >= -128) {
|
|
133
|
+
type = 'byte';
|
|
134
|
+
}
|
|
135
|
+
else if (val >= -0x8000 && val < 0x8000) {
|
|
136
|
+
type = 'short'
|
|
137
|
+
}
|
|
138
|
+
else if (val >= -0x80000000 && val < 0x80000000) {
|
|
139
|
+
type = 'int';
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
type = 'long';
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
113
147
|
function tag(t) { buffer.write(t, offset); offset++; }
|
|
114
148
|
|
|
115
149
|
switch (type) {
|
|
@@ -141,44 +175,36 @@ function encodeFieldValue(buffer, value, offset) {
|
|
|
141
175
|
tag('t');
|
|
142
176
|
buffer.writeUInt8((val) ? 1 : 0, offset); offset++;
|
|
143
177
|
break;
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
// type as unsigned, but most clients (and the spec)
|
|
162
|
-
// think it's signed, and now RabbitMQ does too.
|
|
163
|
-
if (val < 128 && val >= -128) {
|
|
164
|
-
tag('b');
|
|
165
|
-
buffer.writeInt8(val, offset); offset++;
|
|
166
|
-
}
|
|
167
|
-
else if (val >= -0x8000 && val < 0x8000) { // short
|
|
168
|
-
tag('s');
|
|
169
|
-
buffer.writeInt16BE(val, offset); offset += 2;
|
|
170
|
-
}
|
|
171
|
-
else if (val >= -0x80000000 && val < 0x80000000) { // int
|
|
172
|
-
tag('I');
|
|
173
|
-
buffer.writeInt32BE(val, offset); offset += 4;
|
|
174
|
-
}
|
|
175
|
-
else { // long
|
|
176
|
-
tag('l');
|
|
177
|
-
ints.writeInt64BE(buffer, val, offset); offset += 8;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
178
|
+
// These are the types that are either guessed above, or
|
|
179
|
+
// explicitly given using the {'!': type} notation.
|
|
180
|
+
case 'double':
|
|
181
|
+
case 'float64':
|
|
182
|
+
tag('d');
|
|
183
|
+
buffer.writeDoubleBE(val, offset);
|
|
184
|
+
offset += 8;
|
|
185
|
+
break;
|
|
186
|
+
case 'byte':
|
|
187
|
+
case 'int8':
|
|
188
|
+
tag('b');
|
|
189
|
+
buffer.writeInt8(val, offset); offset++;
|
|
190
|
+
break;
|
|
191
|
+
case 'short':
|
|
192
|
+
case 'int16':
|
|
193
|
+
tag('s');
|
|
194
|
+
buffer.writeInt16BE(val, offset); offset += 2;
|
|
180
195
|
break;
|
|
181
|
-
|
|
196
|
+
case 'int':
|
|
197
|
+
case 'int32':
|
|
198
|
+
tag('I');
|
|
199
|
+
buffer.writeInt32BE(val, offset); offset += 4;
|
|
200
|
+
break;
|
|
201
|
+
case 'long':
|
|
202
|
+
case 'int64':
|
|
203
|
+
tag('l');
|
|
204
|
+
ints.writeInt64BE(buffer, val, offset); offset += 8;
|
|
205
|
+
break;
|
|
206
|
+
|
|
207
|
+
// Now for exotic types, those can _only_ be denoted by using
|
|
182
208
|
// `{'!': type, value: val}
|
|
183
209
|
case 'timestamp':
|
|
184
210
|
tag('T');
|
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,13 +76,12 @@ function openFrames(vhost, query, credentials, extraClientProperties) {
|
|
|
76
76
|
};
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
// Decide on credentials based on what we're supplied
|
|
79
|
+
// Decide on credentials based on what we're supplied.
|
|
80
80
|
function credentialsFromUrl(parts) {
|
|
81
81
|
var user = 'guest', passwd = 'guest';
|
|
82
|
-
if (parts.
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
passwd = auth[1];
|
|
82
|
+
if (parts.username != '' || parts.password != '') {
|
|
83
|
+
user = (parts.username) ? unescape(parts.username) : '';
|
|
84
|
+
passwd = (parts.password) ? unescape(parts.password) : '';
|
|
86
85
|
}
|
|
87
86
|
return credentials.plain(user, passwd);
|
|
88
87
|
}
|
|
@@ -110,17 +109,25 @@ function connect(url, socketOptions, openCallback) {
|
|
|
110
109
|
sockopts.port = url.port || ((protocol === 'amqp:') ? 5672 : 5671);
|
|
111
110
|
|
|
112
111
|
var user, pass;
|
|
113
|
-
if
|
|
114
|
-
|
|
115
|
-
|
|
112
|
+
// Only default if both are missing, to have the same behaviour as
|
|
113
|
+
// the stringly URL.
|
|
114
|
+
if (url.username == undefined && url.password == undefined) {
|
|
115
|
+
user = 'guest'; pass = 'guest';
|
|
116
116
|
} else {
|
|
117
|
-
user = url.username;
|
|
118
|
-
pass = url.password;
|
|
117
|
+
user = url.username || '';
|
|
118
|
+
pass = url.password || '';
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
var config = {
|
|
122
|
+
locale: url.locale,
|
|
123
|
+
channelMax: url.channelMax,
|
|
124
|
+
frameMax: url.frameMax,
|
|
125
|
+
heartbeat: url.heartbeat,
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
fields = openFrames(url.vhost, config, sockopts.credentials || credentials.plain(user, pass), extraClientProperties);
|
|
122
129
|
} else {
|
|
123
|
-
var parts = URL
|
|
130
|
+
var parts = URL(url, true); // yes, parse the query string
|
|
124
131
|
protocol = parts.protocol;
|
|
125
132
|
sockopts.host = parts.hostname;
|
|
126
133
|
sockopts.port = parseInt(parts.port) || ((protocol === 'amqp:') ? 5672 : 5671);
|
|
@@ -159,8 +166,11 @@ function connect(url, socketOptions, openCallback) {
|
|
|
159
166
|
}
|
|
160
167
|
|
|
161
168
|
if (timeout) {
|
|
162
|
-
sock.setTimeout(
|
|
163
|
-
|
|
169
|
+
sock.setTimeout(timeout, function() {
|
|
170
|
+
sock.end();
|
|
171
|
+
sock.destroy();
|
|
172
|
+
openCallback(new Error('connect ETIMEDOUT'));
|
|
173
|
+
});
|
|
164
174
|
}
|
|
165
175
|
|
|
166
176
|
sock.once('error', function(err) {
|
|
@@ -170,3 +180,4 @@ function connect(url, socketOptions, openCallback) {
|
|
|
170
180
|
}
|
|
171
181
|
|
|
172
182
|
module.exports.connect = connect;
|
|
183
|
+
module.exports.credentialsFromUrl = credentialsFromUrl;
|
package/lib/connection.js
CHANGED
|
@@ -9,6 +9,7 @@ var constants = defs.constants;
|
|
|
9
9
|
var frame = require('./frame');
|
|
10
10
|
var HEARTBEAT = frame.HEARTBEAT;
|
|
11
11
|
var Mux = require('./mux').Mux;
|
|
12
|
+
var Buffer = require('safe-buffer').Buffer
|
|
12
13
|
|
|
13
14
|
var Duplex =
|
|
14
15
|
require('stream').Duplex ||
|
|
@@ -43,7 +44,7 @@ function Connection(underlying) {
|
|
|
43
44
|
this.muxer = new Mux(stream);
|
|
44
45
|
|
|
45
46
|
// frames
|
|
46
|
-
this.rest =
|
|
47
|
+
this.rest = Buffer.alloc(0);
|
|
47
48
|
this.frameMax = constants.FRAME_MIN_SIZE;
|
|
48
49
|
this.sentSinceLastCheck = false;
|
|
49
50
|
this.recvSinceLastCheck = false;
|
|
@@ -204,6 +205,7 @@ C.open = function(allFields, openCallback0) {
|
|
|
204
205
|
allFields.mechanism)));
|
|
205
206
|
return;
|
|
206
207
|
}
|
|
208
|
+
self.serverProperties = start.fields.serverProperties;
|
|
207
209
|
send(defs.ConnectionStartOk);
|
|
208
210
|
wait(afterStartOk);
|
|
209
211
|
}
|
|
@@ -464,7 +466,7 @@ C.freshChannel = function(channel, options) {
|
|
|
464
466
|
C.releaseChannel = function(channel) {
|
|
465
467
|
this.freeChannels.clear(channel);
|
|
466
468
|
var buffer = this.channels[channel].buffer;
|
|
467
|
-
|
|
469
|
+
buffer.end(); // will also cause it to be unpiped
|
|
468
470
|
this.channels[channel] = null;
|
|
469
471
|
};
|
|
470
472
|
|
|
@@ -550,7 +552,7 @@ C.sendMessage = function(channel,
|
|
|
550
552
|
var allLen = methodHeaderLen + bodyLen;
|
|
551
553
|
|
|
552
554
|
if (allLen < SINGLE_CHUNK_THRESHOLD) {
|
|
553
|
-
var all =
|
|
555
|
+
var all = Buffer.alloc(allLen);
|
|
554
556
|
var offset = mframe.copy(all, 0);
|
|
555
557
|
offset += pframe.copy(all, offset);
|
|
556
558
|
|
|
@@ -560,7 +562,7 @@ C.sendMessage = function(channel,
|
|
|
560
562
|
}
|
|
561
563
|
else {
|
|
562
564
|
if (methodHeaderLen < SINGLE_CHUNK_THRESHOLD) {
|
|
563
|
-
var both =
|
|
565
|
+
var both = Buffer.alloc(methodHeaderLen);
|
|
564
566
|
var offset = mframe.copy(both, 0);
|
|
565
567
|
pframe.copy(both, offset);
|
|
566
568
|
buffer.write(both);
|