RabbitMQ is an open source middleware message solution that natively uses AMQP communications but it has a good selection of plug-ins to support features like: MQTT, MQTT Web Sockets, HTTP REST API and server-to-server communications.
RabbitMQ has a very good selection of interfacing clients for most of the major programming languages. For applications where there is no custom programming library the REST API can be used.
Applications where the REST API could be used might include:
- Arduino IoT projects
- Web Clients (not using NodeJS)
- For simple reading and writing of messages
- For monitoring of RabbitMQ loading
- AppInventor Android apps
Unfortunately I didn’t find the RabbitMQ REST API to be 100% straightforward, so in this blog I would like to document some of my notes and testing.
What is REST API
Representational State Transfer (REST) is a software style for creating Web services. A client issues an HTTP request to a server with a GET/POST/PUT or DELETE method and the server responds with a JSON (Javascript Object Notation) formatted message.
The most common tool to test REST API is curl. Curl is supported on all major OS’s. The curl syntax will vary slightly between Windows and Linux, especially in how the systems handle strings.
RabbitMQ Setup
RabbitMQ can be installed on Window, Linux, MacOS systems and there are also some cloud based offerings. For small systems lower end hardware like a Raspberry Pi can be used. For complete RabbitMQ installation instructions see: https://www.rabbitmq.com/download.html . To install and run RabbitMQ on a Ubuntu system enter:
sudo apt-get update sudo apt-get install rabbitmq-server sudo service rabbitmq-server start
The next step is to add some plug-ins. For the Web Administration and REST API plug-ins:
sudo rabbitmq-plugins enable rabbitmq-management
The rabbitmqctl command line tool allows you to configure and review the RabbitMQ server. To add a user pete, with password pete, that has config, write and read rights for management and administrator access, enter:
sudo rabbitmqctl add_user pete pete sudo rabbitmqctl set_permissions -p / pete ".*" ".*" ".*" sudo rabbitmqctl set_user_tags pete management administrator
After you’ve defined an administrative user the RabbitMQ web management plug-in can be accessed by: http://ip_address:15672 .
Once the Web Management component is installed it is much easier to test and play with REST API calls.
REST API Calls Using CURL
For a complete set of RabbitMQ REST API calls see: https://pulse.mozilla.org/api/ .
Typically you would use the RabbitMQ tools to create and exchanges and queues but it is possible to do this via the REST API interface.
Below are some examples using user: pete and a password of pete . Note: %2f is used for default (blank name) virtual host.
Create an exchange: webex
curl -i -u pete:pete -H “content-type:application/json” -X PUT http://192.168.0.116:15672/api/exchanges/%2f/webex -d”{“”type””:””direct””,””auto_delete””:false,””durable””:true,””internal””:false,””arguments””:{}}”
Create a Queue: webq1
curl -i -u pete:pete -H “content-type:application/json” -X PUT http://192.168.0.116:15672/api/queues/%2f/webq1 -d”{“”auto_delete””:false,””durable””:true,””arguments””:{}}”
Create Binding: Bind queue webq1 to exchange webex with a routing key of webq1
curl -i -u pete:pete -H “content-type:application/json” -X POST http://192.168.0.116:15672/api/bindings/%2f/e/webex/q/webq1 -d”{“”routing_key””:””webq1“”,””arguments””:{}}”
Comments: you need to bind a queue to an exchange if you wish to write to it. The routing key does the binding. The key can be any name but using the queue name makes it simple. A queue can also have binding to multiple exchanges.
Get a message: from queue webq1
curl -i -u pete:pete -H “content-type:application/json” -X POST http://192.168.0.116:15672/api/queues/%2f/webq1/get -d”{“”count””:5,””requeue””:true,””encoding””:””auto””,””truncate””:50000}”
Comments: A queue can have multiple messages. A requeue=false, will remove messages that are already read.
Post a message (44.4) : to exchange webex with routing key webq1
curl -i -u pete:pete -H “content-type:application/json” -X POST http://192.168.0.116:15672/api/exchanges/%2f/webex/publish -d”{“”properties””:{},””routing_key””:””webq1“”,””payload””:””44.4“”,””payload_encoding””:””string””}”
Javascript REST API Client
I had some Web browser issues when my test PC and my RabbitMQ server were in different domains. Web Browsers like Chrome and Firefox will complain about a CORS policy problem.
Cross-origin resource sharing (CORS) is a mechanism that allows restricted resources on a web page to be requested from another domain outside the domain from which the first resource was served.
If you are crossing domains and you want to do some quick testing Microsoft Explorer will work.
Javascript GET a Queue Message
I used the AJAX XMLHttpRequest object to do my GET and POST requests.
<!DOCTYPE html> <html> <body> <h2>RabbitMQ REST API - Get Queue Message</h2> URL/API Call: <input type="text" id="theurl" value="http://192.168.0.116:15672/api/queues/%2f/" size = "50" /> <br><br> Queue Name: <input type="text" id="qname" value="webex"/> <br><br> Requeue: <input type="text" id="rq" value="true" /> (false = remove old values)<br><br> Message Count: <input type="text" id="mcount" value="5"/> <br><br> <button type="button" onclick="sendoutput()">Get Message(s)</button> <br> <hr> <p id="demo"></p> <script> function sendoutput() { // RabbitMQ username and password var username = "pete"; var password = "pete"; var xhttp = new XMLHttpRequest(); var fullurl = document.getElementById("theurl").value + document.getElementById("qname").value + "//get"; xhttp.open("POST", fullurl, true,username,password); // change to your Auth username and password xhttp.setRequestHeader("Content-Type","application/jsonp"); var rq = document.getElementById("rq").value; var mcount = document.getElementById("mcount").value; var params = JSON.stringify({"count":mcount,"requeue":rq,"encoding":"auto","truncate":"50000"}); // Define a handler function when the response comes back xhttp.onreadystatechange = function() { // Get the response and put on it the screen if (this.readyState == 4 ) { document.getElementById("demo").innerHTML = "Result=" +xhttp.responseText; } } xhttp.send(params); } </script> </body> </html>
Javascript POST an Exchange Message
Unfortunately you can not send a message directly to a queue, instead you need to send a message to an exchange with routing key. This routing key is linked to the queue that you wish to connect to.
<!DOCTYPE html> <html> <body> <h2>RabbitMQ REST API - An Exchange Message</h2> URL/API Call: <input type="text" id="theurl" value="http://192.168.0.116:15672/api/exchanges/%2f/" size = "50" /> <br><br> Exchange Name: <input type="text" id="exname" value="webex"/> <br><br> Routing Key: <input type="text" id="rkey" value="webq1"/> <br><br> Value to Send: <input type="text" id="theval" value="11.1"/> <br><br> <button type="button" onclick="sendoutput()">Send Output</button> <br> <hr> <p id="demo"></p> <script> function sendoutput() { // RabbitMQ username and password var username = "pete"; var password = "pete"; var xhttp = new XMLHttpRequest(); var fullurl = document.getElementById("theurl").value + document.getElementById("exname").value + "//publish"; xhttp.open("POST", fullurl, true,username,password); xhttp.setRequestHeader("Content-Type","application/jsonp"); var rkey = document.getElementById("r").value var theval = document.getElementById("theval").value var params = JSON.stringify({"properties":{},"routing_key":rkey,"payload":theval,"payload_encoding":"string"}); // Define a handler function when the response comes back xhttp.onreadystatechange = function() { // Get the response and put on it the screen if (this.readyState == 4 ) { document.getElementById("demo").innerHTML = "Result=" +xhttp.responseText; } } xhttp.send(params); } </script> </body> </html>
Python – get message(s) from a queue
The requests library is extremely simple to use for REST interfacing. It is installed by:
pip install requests
# importing the requests library import requests # defining the api-endpoint API_ENDPOINT = "http://192.168.0.116:15672/api/queues/%2f/webq1/get" headers = {'content-type': 'application/json'} # data to be sent to api pdata = {'count':'5','requeue':'true','encoding':'auto','truncate':'50000'} # sending post request and saving response as response object r = requests.post(url = API_ENDPOINT ,auth=('pete', 'pete'), json = pdata, headers=headers) # extracting response text pastebin_url = r.text print("Response :%s"%pastebin_url)
Python – Write a message to an exchange
# importing the requests library import requests import json # defining the api-endpoint API_ENDPOINT = "http://192.168.0.116:15672/api/exchanges/%2f/webex/publish" # your source code here headers = {'content-type': 'application/json'} # data to be sent to api pdata = {'properties':{},'routing_key':'webq1','payload':'90.4','payload_encoding':'string'} # sending post request and saving response as response object r = requests.post(url = API_ENDPOINT ,auth=('pete', 'pete'), json = pdata, headers=headers) # extracting response text pastebin_url = r.text print("Response :%s"%pastebin_url)
Final Comments
The RabbitMQ REST interface is not designed for high throughput, but it is an excellent way to connect devices that have no native API support.
For my next round of testing I’d like to work on an Arduino and a AppInventor Android app.
I can’t really make it work using the RabbitMQ REST API example? Is there something missing in the example code for the scripting as no result is display?
LikeLike
Hi, I found that using CURL was very solid. Can you get cURL to work? Try a super simple call like:
curl -i -u youruser:yourpassword -H “content-type:application/json” -X http://your_ip:15672/api/overview
Once I got cURL to work I moved on to Python then Javascript.
The most common issues that I’ve found are in network/OS security, then the browser adds another layer of security.
Good luck.
LikeLike
Pete, do you have an API with the List of all connections?
LikeLike
Hi Jean Carlos,
To find the list of all connections, it would be based on which client API you are using (Python vs Golang etc.).
If you use the RabbitMQ Management HTTP API you can get the results in any programming language. See:
https://pulse.mozilla.org/api/index.html
You’ll then probably want to use:
/api/connections
I tried to document some of my notes at:
https://funprojects.blog/2019/11/08/rabbitmq-rest-api/
I hope that this helps.
LikeLike
Hi Pete! excellent project idea. i will follow your blog
LikeLike