Package detail

@cloudamqp/amqp-client

cloudamqp145.3kApache-2.03.2.1

AMQP 0-9-1 client, both for browsers (WebSocket) and node (TCP Socket)

amqp, rabbitmq, amqplib

readme

amqp-client.js

AMQP 0-9-1 TypeScript client both for Node.js and browsers (using WebSocket). This library is intended to replace all other Node.js AMQP libraries.

API documentation.

This library is Promise-based and hence works very well with async/await. It's secure by default, for instance, publishes aren't fulfilled until either the data has been sent on the wire (so that back propagation is respected), or if the channel has Publish Confirms enabled, it isn't fulfilled until the server has acknowledged that the message has been enqueued.

The library was developed so to make it easy for developers who already are familiar with AMQP to write browser apps that communicates directly with an AMQP server over WebSocket.

Support

The library is developed and supported by CloudAMQP, the largest hosted RabbitMQ provider in the world.

Install

npm install @cloudamqp/amqp-client --save

Start node with --enable-source-maps to get proper stacktraces as the library is transpiled from TypeScript.

Example usage

Using AMQP in Node.js:

import { AMQPClient } from '@cloudamqp/amqp-client'

async function run() {
  try {
    const amqp = new AMQPClient("amqp://localhost")
    const conn = await amqp.connect()
    const ch = await conn.channel()
    const q = await ch.queue()
    const consumer = await q.subscribe({noAck: true}, async (msg) => {
      console.log(msg.bodyToString())
      await consumer.cancel()
    })
    await q.publish("Hello World", {deliveryMode: 2})
    await consumer.wait() // will block until consumer is canceled or throw an error if server closed channel/connection
    await conn.close()
  } catch (e) {
    console.error("ERROR", e)
    e.connection.close()
    setTimeout(run, 1000) // will try to reconnect in 1s
  }
}

run()

WebSockets

This library can be used in the browser to access an AMQP server over WebSockets. For servers such as RabbitMQ that doesn't (yet?) support WebSockets natively a WebSocket TCP relay have to be used as a proxy. More information can be found in this blog post.

For web browsers a compiled and rolled up version is available at https://github.com/cloudamqp/amqp-client.js/releases.

Using AMQP over WebSockets in a browser:

<!DOCTYPE html>
<html>
  <head>
    <script type=module>
      import { AMQPWebSocketClient } from './js/amqp-websocket-client.mjs'

      const textarea = document.getElementById("textarea")
      const input = document.getElementById("message")

      const tls = window.location.protocol === "https:"
      const url = `${tls ? "wss" : "ws"}://${window.location.host}`
      const amqp = new AMQPWebSocketClient(url, "/", "guest", "guest")

      async function start() {
        try {
          const conn = await amqp.connect()
          const ch = await conn.channel()
          attachPublish(ch)
          const q = await ch.queue("")
          await q.bind("amq.fanout")
          const consumer = await q.subscribe({noAck: false}, (msg) => {
            console.log(msg)
            textarea.value += msg.bodyToString() + "\n"
            msg.ack()
          })
        } catch (err) {
          console.error("Error", err, "reconnecting in 1s")
          disablePublish()
          setTimeout(start, 1000)
        }
      }

      function attachPublish(ch) {
        document.forms[0].onsubmit = async (e) => {
          e.preventDefault()
          try {
            await ch.basicPublish("amq.fanout", "", input.value, { contentType: "text/plain" })
          } catch (err) {
            console.error("Error", err, "reconnecting in 1s")
            disablePublish()
            setTimeout(start, 1000)
          }
          input.value = ""
        }
      }

      function disablePublish() {
        document.forms[0].onsubmit = (e) => { alert("Disconnected, waiting to be reconnected") }
      }

      start()
    </script>
  </head>
  <body>
    <form>
      <textarea id="textarea" rows=10></textarea>
      <br/>
      <input id="message"/>
      <button type="submit">Send</button>
    </form>
  </body>
</html>

Performance

Messages with a 1-byte body, no properties:

Client Publish rate Consume rate
amqp-client.js 300.000 msgs/s 512.000 msgs/s
amqplib 172.000 msgs/s 519.000 msgs/s

Messages with a 1-byte body, and all properties, except headers:

Client Publish rate Consume rate
amqp-client.js 144.000 msgs/s 202.000 msgs/s
amqplib 110.000 msgs/s 251.000 msgs/s

Messages with a 1-byte body, and all properties, including headers:

Client Publish rate Consume rate
amqp-client.js 70.000 msgs/s 89.000 msgs/s
amqplib 60.000 msgs/s 99.000 msgs/s

The reason amqp-client is somewhat slower to consume is that to maintain browser compatibility for the websocket client, DataView are used for parsing the binary protocol instead of Buffer.

Module comparison

Client Runtime dependencies Lines of code
amqp-client.js 0 1743
amqplib 14 6720 (w/o dependencies)

changelog

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[3.2.1] - 2025-04-06

  • Increase min frameMax to 8192 (8KB) for compatibility with RabbitMQ 4.1 and large JWT tokens (#134)

[3.2.0] - 2025-03-07

  • Buffer all publish frames into a single huge buffer and send together
  • Properly reject failed connection attempt
  • TypeScript 5.7 fixes
  • Web Worker compatibility

[3.1.1] - 2023-08-25

  • Correct version number in src/amqp-base-client.ts

[3.1.0] - 2023-08-23

The version number was not updated in src/amqp-base-client.ts for this release.

Added

  • Support for clients to negotiate channel-max (#86)
  • Raise when WebSocket is not cleanly closed (#80)
  • Make logging configurable (#79)
  • Support for connection.update-secret (#77)

Fixed

  • Channel max 0 should be treated as "unlimited" not 0 (#86)
  • Close sockets not supporting amqp protocol (#78)

Changed

  • Throws and rejects with Error as per best practice (#81)
  • Clean ups (#88, #85)
  • Package improvements for bundling and tree-shaking (#75)

[3.0.0] - 2023-07-24

Added

  • New overload for AMQPWebSocketClient constructor to allow setting optional parameters through an init object (#71)

Fixed

  • Call socket.destroy() when closing socket to fix intermitent condition where onerror is called when conn is closed by client (#72)
  • Pass the correct array buffer to dataview when reading framesize (related to #55)
  • Raise AMQPError when channelMax is reached (fixes #43)
  • Add Channel#onerror callback (fixes #40)
  • Correctly handle frame headers split across reads in the WebSocket client (#68, fixes #55)

Changed

  • Breaking change: Removed support for end-of-life versions of Node.js. A minimum of Node.js 16 is now required. (#70)

[2.1.1] - 2022-12-13

Added

  • Custom TlsOptions can be passed to the constructor, like: new AMQPClient(url, { cert, "", key: "", ca: "" })

[2.1.0] - 2022-03-07

Added

  • AMQPClient#onerror, will be called whenever ther connection is closed, override it to create reconnect logic.
  • Export types for queue, exchange and consume parameters

Fixed

  • Only skip TLS certificate validation if the insecure query parameter is included in the URL
  • Use a pool of buffers so that multiple microtasks can publish simultaneously
  • Don't set an IP as SNI hostname, only proper hostnames
  • Decode username/password in URL properly

Changed

  • Allow publishing of null and let AMQPMessage#body be null when a body is missing

[2.0.3] - 2022-03-07

Fixed

  • Heartbeat support
  • Channel#closed is now a public property

[2.0.2] - 2022-03-04

Fixed

  • Frame errors because frame buffer was reused

[2.0.1] - 2022-03-04

Fixed

  • Frame errors because frame buffer was reused

Changed

  • Don't depend on TextEncoder in AMQPMessage

Added

  • Explicit return types on all methods for faster typescript compilation

[2.0.0] - 2022-02-02

Changed

  • No default exports, only named: import { AMQPClient } from "@cloudamqp/amqp-client"
  • Much improved browser bundling support (webpack)

Added

  • Support basicCancel send from server, AMQPConsumer#wait() will throw an Error if it happens.
  • Support custom frameMax values, by URL: amqp://localhost/vhost?frameMax=8192

[1.3.2] - 2022-01-12

Fixed

  • Websocket client now supports parsing AMQP frames split over multiple WebSocket frames (could happen with high throughput via websocket-tcp-relay).

Changed

  • 67% increased publish rate, by reusing frame buffer

[1.3.1] - 2022-01-03

Changed

  • Use Buffer for string encoding/decoding for >100% performance boost
  • Use 4096 frameMax for smaller and faster allocations (down from 16KB)
  • Reraise RangeErrors with more debug information

[1.3.0] - 2021-12-23

Changed

  • Rewrite in TypeScript

Fixed

  • Queue purged never resolved

Added

  • Logging when connection is blocked/unblocked by server

[1.2.2] - 2021-12-21

Fixed

  • tls/net.socket onread is buggy in nodejs 16, revert to 'data' event for parsing frames

Changed

  • nodejs version expanded to 12

[1.2.1] - 2021-12-20

Changed

  • 128KB read buffer
  • Avoid copying frame when whole frame is included in one read
  • Static textdecoder for faster string decoding in frames

Fixed

  • Error if a frame was split before the first 7 bytes between two reads

[1.2.0] - 2021-12-16

Changed

  • tls connections require node 14 due to tls.connect({ onread })

Added

  • Typescript defintions through jsdoc comments