@cloudamqp/amqp-client
Version:
AMQP 0-9-1 client, both for browsers (WebSocket) and node (TCP Socket)
117 lines • 4.96 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AMQPWebSocketClient = void 0;
const amqp_base_client_js_1 = require("./amqp-base-client.js");
const amqp_view_js_1 = require("./amqp-view.js");
const amqp_error_js_1 = require("./amqp-error.js");
class AMQPWebSocketClient extends amqp_base_client_js_1.AMQPBaseClient {
constructor(url, vhost = "/", username = "guest", password = "guest", name, frameMax = 8192, heartbeat = 0) {
if (typeof url === 'object') {
vhost = url.vhost ?? vhost;
username = url.username ?? username;
password = url.password ?? password;
name = url.name ?? name;
frameMax = url.frameMax ?? frameMax;
heartbeat = url.heartbeat ?? heartbeat;
url = url.url;
}
super(vhost, username, password, name, AMQPWebSocketClient.platform(), frameMax, heartbeat);
this.framePos = 0;
this.frameSize = 0;
this.url = url;
this.frameBuffer = new Uint8Array(frameMax);
}
connect() {
const socket = new WebSocket(this.url);
this.socket = socket;
socket.binaryType = "arraybuffer";
socket.onmessage = this.handleMessage.bind(this);
return new Promise((resolve, reject) => {
this.connectPromise = [resolve, reject];
socket.addEventListener('close', reject);
socket.addEventListener('error', reject);
socket.addEventListener('open', () => {
socket.addEventListener('error', (ev) => this.onerror(new amqp_error_js_1.AMQPError(ev.toString(), this)));
socket.addEventListener('close', (ev) => {
const clientClosed = this.closed;
this.closed = true;
if (!ev.wasClean && !clientClosed)
this.onerror(new amqp_error_js_1.AMQPError(`connection not cleanly closed (${ev.code})`, this));
});
socket.send(new Uint8Array([65, 77, 81, 80, 0, 0, 9, 1]));
});
});
}
send(bytes) {
return new Promise((resolve, reject) => {
if (this.socket) {
try {
this.socket.send(bytes);
resolve();
}
catch (err) {
this.closeSocket();
reject(err);
}
}
else {
reject(new amqp_error_js_1.AMQPError("Socket not connected", this));
}
});
}
closeSocket() {
this.closed = true;
if (this.socket)
this.socket.close();
this.socket = undefined;
}
handleMessage(event) {
const buf = event.data;
const bufView = new DataView(buf);
let bufPos = 0;
while (bufPos < buf.byteLength) {
if (this.frameSize === 0) {
if (this.framePos !== 0) {
const len = 7 - this.framePos;
this.frameBuffer.set(new Uint8Array(buf, bufPos, len), this.framePos);
this.frameSize = new DataView(this.frameBuffer.buffer).getInt32(bufPos + 3) + 8;
this.framePos += len;
bufPos += len;
continue;
}
if (bufPos + 3 + 4 > buf.byteLength) {
const len = buf.byteLength - bufPos;
this.frameBuffer.set(new Uint8Array(buf, bufPos), this.framePos);
this.framePos += len;
break;
}
this.frameSize = bufView.getInt32(bufPos + 3) + 8;
if (buf.byteLength - bufPos >= this.frameSize) {
const view = new amqp_view_js_1.AMQPView(buf, bufPos, this.frameSize);
this.parseFrames(view);
bufPos += this.frameSize;
this.frameSize = 0;
continue;
}
}
const leftOfFrame = this.frameSize - this.framePos;
const copyBytes = Math.min(leftOfFrame, buf.byteLength - bufPos);
this.frameBuffer.set(new Uint8Array(buf, bufPos, copyBytes), this.framePos);
this.framePos += copyBytes;
bufPos += copyBytes;
if (this.framePos === this.frameSize) {
const view = new amqp_view_js_1.AMQPView(this.frameBuffer.buffer, 0, this.frameSize);
this.parseFrames(view);
this.frameSize = this.framePos = 0;
}
}
}
static platform() {
if (typeof (navigator) !== 'undefined')
return navigator.userAgent;
else
return `${process.release.name} ${process.version} ${process.platform} ${process.arch}`;
}
}
exports.AMQPWebSocketClient = AMQPWebSocketClient;
//# sourceMappingURL=amqp-websocket-client.js.map