amqplib 0.7.0 → 0.9.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.
@@ -4,264 +4,259 @@
4
4
 
5
5
  'use strict';
6
6
 
7
- var defs = require('./defs');
8
- var Promise = require('bluebird');
9
- var inherits = require('util').inherits;
10
- var EventEmitter = require('events').EventEmitter;
11
- var BaseChannel = require('./channel').BaseChannel;
12
- var acceptMessage = require('./channel').acceptMessage;
13
- var Args = require('./api_args');
14
-
15
- function ChannelModel(connection) {
16
- if (!(this instanceof ChannelModel))
17
- return new ChannelModel(connection);
18
- EventEmitter.call( this );
19
- this.connection = connection;
20
- var self = this;
21
- ['error', 'close', 'blocked', 'unblocked'].forEach(function(ev) {
22
- connection.on(ev, self.emit.bind(self, ev));
23
- });
7
+ const EventEmitter = require('events');
8
+ const Promise = require('bluebird');
9
+ const defs = require('./defs');
10
+ const {BaseChannel} = require('./channel');
11
+ const {acceptMessage} = require('./channel');
12
+ const Args = require('./api_args');
13
+ const {inspect} = require('./format');
14
+
15
+ class ChannelModel extends EventEmitter {
16
+ constructor(connection) {
17
+ super();
18
+ this.connection = connection;
19
+
20
+ ['error', 'close', 'blocked', 'unblocked'].forEach(ev => {
21
+ connection.on(ev, this.emit.bind(this, ev));
22
+ });
23
+ }
24
+
25
+ close() {
26
+ return Promise.fromCallback(this.connection.close.bind(this.connection));
27
+ }
28
+
29
+ async createChannel() {
30
+ const channel = new Channel(this.connection);
31
+ await channel.open();
32
+ return channel;
33
+ }
34
+
35
+ async createConfirmChannel() {
36
+ const channel = new ConfirmChannel(this.connection);
37
+ await channel.open();
38
+ await channel.rpc(defs.ConfirmSelect, {nowait: false}, defs.ConfirmSelectOk);
39
+ return channel;
40
+ }
24
41
  }
25
- inherits(ChannelModel, EventEmitter);
26
-
27
- module.exports.ChannelModel = ChannelModel;
28
-
29
- var CM = ChannelModel.prototype;
30
-
31
- CM.close = function() {
32
- return Promise.fromCallback(this.connection.close.bind(this.connection));
33
- };
34
42
 
35
43
  // Channels
36
44
 
37
- function Channel(connection) {
38
- BaseChannel.call(this, connection);
39
- this.on('delivery', this.handleDelivery.bind(this));
40
- this.on('cancel', this.handleCancel.bind(this));
41
- }
42
- inherits(Channel, BaseChannel);
43
-
44
- module.exports.Channel = Channel;
45
+ class Channel extends BaseChannel {
46
+ constructor(connection) {
47
+ super(connection);
48
+ this.on('delivery', this.handleDelivery.bind(this));
49
+ this.on('cancel', this.handleCancel.bind(this));
50
+ }
51
+
52
+ // An RPC that returns a 'proper' promise, which resolves to just the
53
+ // response's fields; this is intended to be suitable for implementing
54
+ // API procedures.
55
+ async rpc(method, fields, expect) {
56
+ const f = await Promise.fromCallback(cb => {
57
+ return this._rpc(method, fields, expect, cb);
58
+ })
45
59
 
46
- CM.createChannel = function() {
47
- var c = new Channel(this.connection);
48
- return c.open().then(function(openOk) { return c; });
49
- };
50
-
51
- var C = Channel.prototype;
52
-
53
- // An RPC that returns a 'proper' promise, which resolves to just the
54
- // response's fields; this is intended to be suitable for implementing
55
- // API procedures.
56
- C.rpc = function(method, fields, expect) {
57
- var self = this;
58
- return Promise.fromCallback(function(cb) {
59
- return self._rpc(method, fields, expect, cb);
60
- })
61
- .then(function(f) {
62
60
  return f.fields;
63
- });
64
- };
65
-
66
- // Do the remarkably simple channel open handshake
67
- C.open = function() {
68
- return Promise.try(this.allocate.bind(this)).then(
69
- function(ch) {
70
- return ch.rpc(defs.ChannelOpen, {outOfBand: ""},
71
- defs.ChannelOpenOk);
61
+ }
62
+
63
+ // Do the remarkably simple channel open handshake
64
+ open() {
65
+ return Promise.try(this.allocate.bind(this)).then(
66
+ ch => {
67
+ return ch.rpc(defs.ChannelOpen, {outOfBand: ""},
68
+ defs.ChannelOpenOk);
69
+ });
70
+ }
71
+
72
+ close() {
73
+ return Promise.fromCallback(cb => {
74
+ return this.closeBecause("Goodbye", defs.constants.REPLY_SUCCESS,
75
+ cb);
76
+ });
77
+ }
78
+
79
+ // === Public API, declaring queues and stuff ===
80
+
81
+ assertQueue(queue, options) {
82
+ return this.rpc(defs.QueueDeclare,
83
+ Args.assertQueue(queue, options),
84
+ defs.QueueDeclareOk);
85
+ }
86
+
87
+ checkQueue(queue) {
88
+ return this.rpc(defs.QueueDeclare,
89
+ Args.checkQueue(queue),
90
+ defs.QueueDeclareOk);
91
+ }
92
+
93
+ deleteQueue(queue, options) {
94
+ return this.rpc(defs.QueueDelete,
95
+ Args.deleteQueue(queue, options),
96
+ defs.QueueDeleteOk);
97
+ }
98
+
99
+ purgeQueue(queue) {
100
+ return this.rpc(defs.QueuePurge,
101
+ Args.purgeQueue(queue),
102
+ defs.QueuePurgeOk);
103
+ }
104
+
105
+ bindQueue(queue, source, pattern, argt) {
106
+ return this.rpc(defs.QueueBind,
107
+ Args.bindQueue(queue, source, pattern, argt),
108
+ defs.QueueBindOk);
109
+ }
110
+
111
+ unbindQueue(queue, source, pattern, argt) {
112
+ return this.rpc(defs.QueueUnbind,
113
+ Args.unbindQueue(queue, source, pattern, argt),
114
+ defs.QueueUnbindOk);
115
+ }
116
+
117
+ assertExchange(exchange, type, options) {
118
+ // The server reply is an empty set of fields, but it's convenient
119
+ // to have the exchange name handed to the continuation.
120
+ return this.rpc(defs.ExchangeDeclare,
121
+ Args.assertExchange(exchange, type, options),
122
+ defs.ExchangeDeclareOk)
123
+ .then(_ok => { return { exchange }; });
124
+ }
125
+
126
+ checkExchange(exchange) {
127
+ return this.rpc(defs.ExchangeDeclare,
128
+ Args.checkExchange(exchange),
129
+ defs.ExchangeDeclareOk);
130
+ }
131
+
132
+ deleteExchange(name, options) {
133
+ return this.rpc(defs.ExchangeDelete,
134
+ Args.deleteExchange(name, options),
135
+ defs.ExchangeDeleteOk);
136
+ }
137
+
138
+ bindExchange(dest, source, pattern, argt) {
139
+ return this.rpc(defs.ExchangeBind,
140
+ Args.bindExchange(dest, source, pattern, argt),
141
+ defs.ExchangeBindOk);
142
+ }
143
+
144
+ unbindExchange(dest, source, pattern, argt) {
145
+ return this.rpc(defs.ExchangeUnbind,
146
+ Args.unbindExchange(dest, source, pattern, argt),
147
+ defs.ExchangeUnbindOk);
148
+ }
149
+
150
+ // Working with messages
151
+
152
+ publish(exchange, routingKey, content, options) {
153
+ const fieldsAndProps = Args.publish(exchange, routingKey, options);
154
+ return this.sendMessage(fieldsAndProps, fieldsAndProps, content);
155
+ }
156
+
157
+ sendToQueue(queue, content, options) {
158
+ return this.publish('', queue, content, options);
159
+ }
160
+
161
+ consume(queue, callback, options) {
162
+ // NB we want the callback to be run synchronously, so that we've
163
+ // registered the consumerTag before any messages can arrive.
164
+ const fields = Args.consume(queue, options);
165
+ return Promise.fromCallback(cb => {
166
+ this._rpc(defs.BasicConsume, fields, defs.BasicConsumeOk, cb);
167
+ })
168
+ .then(ok => {
169
+ this.registerConsumer(ok.fields.consumerTag, callback);
170
+ return ok.fields;
171
+ });
172
+ }
173
+
174
+ async cancel(consumerTag) {
175
+ const ok = await Promise.fromCallback(cb => {
176
+ this._rpc(defs.BasicCancel, Args.cancel(consumerTag),
177
+ defs.BasicCancelOk,
178
+ cb);
179
+ })
180
+ .then(ok => {
181
+ this.unregisterConsumer(consumerTag);
182
+ return ok.fields;
72
183
  });
73
- };
74
-
75
- C.close = function() {
76
- var self = this;
77
- return Promise.fromCallback(function(cb) {
78
- return self.closeBecause("Goodbye", defs.constants.REPLY_SUCCESS,
79
- cb);
80
- });
81
- };
82
-
83
- // === Public API, declaring queues and stuff ===
84
-
85
- C.assertQueue = function(queue, options) {
86
- return this.rpc(defs.QueueDeclare,
87
- Args.assertQueue(queue, options),
88
- defs.QueueDeclareOk);
89
- };
90
-
91
- C.checkQueue = function(queue) {
92
- return this.rpc(defs.QueueDeclare,
93
- Args.checkQueue(queue),
94
- defs.QueueDeclareOk);
95
- };
96
-
97
- C.deleteQueue = function(queue, options) {
98
- return this.rpc(defs.QueueDelete,
99
- Args.deleteQueue(queue, options),
100
- defs.QueueDeleteOk);
101
- };
102
-
103
- C.purgeQueue = function(queue) {
104
- return this.rpc(defs.QueuePurge,
105
- Args.purgeQueue(queue),
106
- defs.QueuePurgeOk);
107
- };
108
-
109
- C.bindQueue = function(queue, source, pattern, argt) {
110
- return this.rpc(defs.QueueBind,
111
- Args.bindQueue(queue, source, pattern, argt),
112
- defs.QueueBindOk);
113
- };
114
-
115
- C.unbindQueue = function(queue, source, pattern, argt) {
116
- return this.rpc(defs.QueueUnbind,
117
- Args.unbindQueue(queue, source, pattern, argt),
118
- defs.QueueUnbindOk);
119
- };
120
-
121
- C.assertExchange = function(exchange, type, options) {
122
- // The server reply is an empty set of fields, but it's convenient
123
- // to have the exchange name handed to the continuation.
124
- return this.rpc(defs.ExchangeDeclare,
125
- Args.assertExchange(exchange, type, options),
126
- defs.ExchangeDeclareOk)
127
- .then(function(_ok) { return { exchange: exchange }; });
128
- };
129
-
130
- C.checkExchange = function(exchange) {
131
- return this.rpc(defs.ExchangeDeclare,
132
- Args.checkExchange(exchange),
133
- defs.ExchangeDeclareOk);
134
- };
135
-
136
- C.deleteExchange = function(name, options) {
137
- return this.rpc(defs.ExchangeDelete,
138
- Args.deleteExchange(name, options),
139
- defs.ExchangeDeleteOk);
140
- };
141
-
142
- C.bindExchange = function(dest, source, pattern, argt) {
143
- return this.rpc(defs.ExchangeBind,
144
- Args.bindExchange(dest, source, pattern, argt),
145
- defs.ExchangeBindOk);
146
- };
147
-
148
- C.unbindExchange = function(dest, source, pattern, argt) {
149
- return this.rpc(defs.ExchangeUnbind,
150
- Args.unbindExchange(dest, source, pattern, argt),
151
- defs.ExchangeUnbindOk);
152
- };
153
-
154
- // Working with messages
155
-
156
- C.publish = function(exchange, routingKey, content, options) {
157
- var fieldsAndProps = Args.publish(exchange, routingKey, options);
158
- return this.sendMessage(fieldsAndProps, fieldsAndProps, content);
159
- };
160
-
161
- C.sendToQueue = function(queue, content, options) {
162
- return this.publish('', queue, content, options);
163
- };
164
-
165
- C.consume = function(queue, callback, options) {
166
- var self = this;
167
- // NB we want the callback to be run synchronously, so that we've
168
- // registered the consumerTag before any messages can arrive.
169
- var fields = Args.consume(queue, options);
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
- });
177
- };
178
-
179
- C.cancel = function(consumerTag) {
180
- var self = this;
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
- });
190
- };
191
-
192
- C.get = function(queue, options) {
193
- var self = this;
194
- var fields = Args.get(queue, options);
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) {
205
- self.handleMessage = acceptMessage(function(m) {
206
- m.fields = fields;
207
- resolve(m);
184
+ }
185
+
186
+ get(queue, options) {
187
+ const fields = Args.get(queue, options);
188
+ return Promise.fromCallback(cb => {
189
+ return this.sendOrEnqueue(defs.BasicGet, fields, cb);
190
+ })
191
+ .then(f => {
192
+ if (f.id === defs.BasicGetEmpty) {
193
+ return false;
194
+ }
195
+ else if (f.id === defs.BasicGetOk) {
196
+ const fields = f.fields;
197
+ return new Promise(resolve => {
198
+ this.handleMessage = acceptMessage(m => {
199
+ m.fields = fields;
200
+ resolve(m);
201
+ });
208
202
  });
209
- });
210
- }
211
- else {
212
- throw new Error("Unexpected response to BasicGet: " +
213
- inspect(f));
214
- }
215
- })
216
- };
217
-
218
- C.ack = function(message, allUpTo) {
219
- this.sendImmediately(
220
- defs.BasicAck,
221
- Args.ack(message.fields.deliveryTag, allUpTo));
222
- };
223
-
224
- C.ackAll = function() {
225
- this.sendImmediately(defs.BasicAck, Args.ack(0, true));
226
- };
227
-
228
- C.nack = function(message, allUpTo, requeue) {
229
- this.sendImmediately(
230
- defs.BasicNack,
231
- Args.nack(message.fields.deliveryTag, allUpTo, requeue));
232
- };
233
-
234
- C.nackAll = function(requeue) {
235
- this.sendImmediately(defs.BasicNack,
236
- Args.nack(0, true, requeue));
237
- };
238
-
239
- // `Basic.Nack` is not available in older RabbitMQ versions (or in the
240
- // AMQP specification), so you have to use the one-at-a-time
241
- // `Basic.Reject`. This is otherwise synonymous with
242
- // `#nack(message, false, requeue)`.
243
- C.reject = function(message, requeue) {
244
- this.sendImmediately(
245
- defs.BasicReject,
246
- Args.reject(message.fields.deliveryTag, requeue));
247
- };
203
+ }
204
+ else {
205
+ throw new Error(`Unexpected response to BasicGet: ${inspect(f)}`);
206
+ }
207
+ });
208
+ }
209
+
210
+ ack(message, allUpTo) {
211
+ this.sendImmediately(
212
+ defs.BasicAck,
213
+ Args.ack(message.fields.deliveryTag, allUpTo));
214
+ }
215
+
216
+ ackAll() {
217
+ this.sendImmediately(defs.BasicAck, Args.ack(0, true));
218
+ }
219
+
220
+ nack(message, allUpTo, requeue) {
221
+ this.sendImmediately(
222
+ defs.BasicNack,
223
+ Args.nack(message.fields.deliveryTag, allUpTo, requeue));
224
+ }
225
+
226
+ nackAll(requeue) {
227
+ this.sendImmediately(defs.BasicNack,
228
+ Args.nack(0, true, requeue));
229
+ }
230
+
231
+ // `Basic.Nack` is not available in older RabbitMQ versions (or in the
232
+ // AMQP specification), so you have to use the one-at-a-time
233
+ // `Basic.Reject`. This is otherwise synonymous with
234
+ // `#nack(message, false, requeue)`.
235
+ reject(message, requeue) {
236
+ this.sendImmediately(
237
+ defs.BasicReject,
238
+ Args.reject(message.fields.deliveryTag, requeue));
239
+ }
240
+
241
+ recover() {
242
+ return this.rpc(defs.BasicRecover,
243
+ Args.recover(),
244
+ defs.BasicRecoverOk);
245
+ }
246
+
247
+ qos(count, global) {
248
+ return this.rpc(defs.BasicQos,
249
+ Args.prefetch(count, global),
250
+ defs.BasicQosOk);
251
+ }
252
+ }
248
253
 
249
254
  // There are more options in AMQP than exposed here; RabbitMQ only
250
255
  // implements prefetch based on message count, and only for individual
251
256
  // channels or consumers. RabbitMQ v3.3.0 and after treat prefetch
252
257
  // (without `global` set) as per-consumer (for consumers following),
253
258
  // and prefetch with `global` set as per-channel.
254
- C.prefetch = C.qos = function(count, global) {
255
- return this.rpc(defs.BasicQos,
256
- Args.prefetch(count, global),
257
- defs.BasicQosOk);
258
- };
259
-
260
- C.recover = function() {
261
- return this.rpc(defs.BasicRecover,
262
- Args.recover(),
263
- defs.BasicRecoverOk);
264
- };
259
+ Channel.prototype.prefetch = Channel.prototype.qos
265
260
 
266
261
  // Confirm channel. This is a channel with confirms 'switched on',
267
262
  // meaning sent messages will provoke a responding 'ack' or 'nack'
@@ -270,49 +265,35 @@ C.recover = function() {
270
265
  // with `null` as its argument to signify 'ack', or an exception as
271
266
  // its argument to signify 'nack'.
272
267
 
273
- function ConfirmChannel(connection) {
274
- Channel.call(this, connection);
268
+ class ConfirmChannel extends Channel {
269
+ publish(exchange, routingKey, content, options, cb) {
270
+ this.pushConfirmCallback(cb);
271
+ return Channel.prototype.publish.call(this, exchange, routingKey, content, options);
272
+ }
273
+
274
+ sendToQueue(queue, content, options, cb) {
275
+ return this.publish('', queue, content, options, cb);
276
+ }
277
+
278
+ waitForConfirms() {
279
+ const awaiting = [];
280
+ const unconfirmed = this.unconfirmed;
281
+ unconfirmed.forEach((val, index) => {
282
+ if (val !== null) {
283
+ const confirmed = new Promise((resolve, reject) => {
284
+ unconfirmed[index] = err => {
285
+ if (val) val(err);
286
+ if (err === null) resolve();
287
+ else reject(err);
288
+ };
289
+ });
290
+ awaiting.push(confirmed);
291
+ }
292
+ });
293
+ return Promise.all(awaiting);
294
+ }
275
295
  }
276
- inherits(ConfirmChannel, Channel);
277
296
 
278
297
  module.exports.ConfirmChannel = ConfirmChannel;
279
-
280
- CM.createConfirmChannel = function() {
281
- var c = new ConfirmChannel(this.connection);
282
- return c.open()
283
- .then(function(openOk) {
284
- return c.rpc(defs.ConfirmSelect, {nowait: false},
285
- defs.ConfirmSelectOk)
286
- })
287
- .then(function() { return c; });
288
- };
289
-
290
- var CC = ConfirmChannel.prototype;
291
-
292
- CC.publish = function(exchange, routingKey, content, options, cb) {
293
- this.pushConfirmCallback(cb);
294
- return C.publish.call(this, exchange, routingKey, content, options);
295
- };
296
-
297
- CC.sendToQueue = function(queue, content, options, cb) {
298
- return this.publish('', queue, content, options, cb);
299
- };
300
-
301
- CC.waitForConfirms = function() {
302
- var awaiting = [];
303
- var unconfirmed = this.unconfirmed;
304
- unconfirmed.forEach(function(val, index) {
305
- if (val === null); // already confirmed
306
- else {
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);
315
- }
316
- });
317
- return Promise.all(awaiting);
318
- };
298
+ module.exports.Channel = Channel;
299
+ module.exports.ChannelModel = ChannelModel;
package/lib/connect.js CHANGED
@@ -106,6 +106,7 @@ function connect(url, socketOptions, openCallback) {
106
106
  if (typeof url === 'object') {
107
107
  protocol = (url.protocol || 'amqp') + ':';
108
108
  sockopts.host = url.hostname;
109
+ sockopts.servername = url.hostname;
109
110
  sockopts.port = url.port || ((protocol === 'amqp:') ? 5672 : 5671);
110
111
 
111
112
  var user, pass;
@@ -130,6 +131,7 @@ function connect(url, socketOptions, openCallback) {
130
131
  var parts = URL(url, true); // yes, parse the query string
131
132
  protocol = parts.protocol;
132
133
  sockopts.host = parts.hostname;
134
+ sockopts.servername = parts.hostname;
133
135
  sockopts.port = parseInt(parts.port) || ((protocol === 'amqp:') ? 5672 : 5671);
134
136
  var vhost = parts.pathname ? parts.pathname.substr(1) : null;
135
137
  fields = openFrames(vhost, parts.query, sockopts.credentials || credentialsFromUrl(parts), extraClientProperties);
@@ -150,8 +152,12 @@ function connect(url, socketOptions, openCallback) {
150
152
  if (timeout) sock.setTimeout(0);
151
153
  if (err === null) {
152
154
  openCallback(null, c);
155
+ } else {
156
+ // The connection isn't closed by the server on e.g. wrong password
157
+ sock.end();
158
+ sock.destroy();
159
+ openCallback(err);
153
160
  }
154
- else openCallback(err);
155
161
  });
156
162
  }
157
163
 
package/lib/connection.js CHANGED
@@ -9,7 +9,6 @@ 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
13
12
 
14
13
  var Duplex =
15
14
  require('stream').Duplex ||
@@ -179,8 +178,7 @@ C.open = function(allFields, openCallback0) {
179
178
  function send(Method) {
180
179
  // This can throw an exception if there's some problem with the
181
180
  // options; e.g., something is a string instead of a number.
182
- try { self.sendMethod(0, Method, tunedOptions); }
183
- catch (err) { bail(err); }
181
+ self.sendMethod(0, Method, tunedOptions);
184
182
  }
185
183
 
186
184
  function negotiate(server, desired) {
@@ -206,7 +204,12 @@ C.open = function(allFields, openCallback0) {
206
204
  return;
207
205
  }
208
206
  self.serverProperties = start.fields.serverProperties;
209
- send(defs.ConnectionStartOk);
207
+ try {
208
+ send(defs.ConnectionStartOk);
209
+ } catch (err) {
210
+ bail(err);
211
+ return;
212
+ }
210
213
  wait(afterStartOk);
211
214
  }
212
215
 
@@ -228,8 +231,13 @@ C.open = function(allFields, openCallback0) {
228
231
  negotiate(fields.channelMax, allFields.channelMax);
229
232
  tunedOptions.heartbeat =
230
233
  negotiate(fields.heartbeat, allFields.heartbeat);
231
- send(defs.ConnectionTuneOk);
232
- send(defs.ConnectionOpen);
234
+ try {
235
+ send(defs.ConnectionTuneOk);
236
+ send(defs.ConnectionOpen);
237
+ } catch (err) {
238
+ bail(err);
239
+ return;
240
+ }
233
241
  expect(defs.ConnectionOpenOk, onOpenOk);
234
242
  break;
235
243
  default:
@@ -8,7 +8,6 @@
8
8
  // * PLAIN (send username and password in the plain)
9
9
  // * EXTERNAL (assume the server will figure out who you are from
10
10
  // context, i.e., your SSL certificate)
11
- var Buffer = require('safe-buffer').Buffer
12
11
  var codec = require('./codec')
13
12
 
14
13
  module.exports.plain = function(user, passwd) {