Skip to content

Instantly share code, notes, and snippets.

@giacchetta
Last active August 23, 2024 13:04
Show Gist options
  • Save giacchetta/8d32c1c164e6d881b8299f3c49857cbf to your computer and use it in GitHub Desktop.
Save giacchetta/8d32c1c164e6d881b8299f3c49857cbf to your computer and use it in GitHub Desktop.
Contact Form with RabbitMQ

Contact Form with RabbitMQ

  1. Let me first introduce about the solution that I'm implementing here and some requisites that you need to archive if you want to run this lab in your local environment.

    1. You need Docker Engine installed
    2. You need NodeJS installed
  2. All files used for this labs are public available in GitHub Gist clone this repository. Once cloned, access to this repository.

    • $ git clone https://gist.github.com/8d32c1c164e6d881b8299f3c49857cbf.git
  3. For Message Queue we are using RabbitMQ, let's install using the official docker image

    • $ sudo docker run -d --hostname rabbit -p 5672:5672 -p 15672:15672 --name rabbit -e RABBITMQ_DEFAULT_USER=user -e RABBITMQ_DEFAULT_PASS=password rabbitmq:3-management
  4. We have created a very simple HTML Contact Form where you can fill with your Name, Email and Phone. You don't need to run a web server, just open the HTML file in your browser.

    • $ firefox form.html
  5. Right now this Contact Form only collect data but no serverless function is listen to so we need to install and run it. If you already have NodeJS installed in your computer, please execute

    • $ npm install
    • $ npx functions-framework --target=contact-form
  6. Great! You have a serverless function working in your local environment or you can publish it to any, not limited to GCP, public cloud provider like AWS or Azure. I'm using Google Functions Framework to avoid extra NodeJS Server configurations that aren't important in this Lab.

  7. This serverless function is listen in your localhost and also your Contact Form is configured to POST new data to the same address.

  8. Let's create some posts and see what happened in RabbitMQ using user:password as credentials

    • $ firefox http://localhost:15672
  9. Excellent! There are some messages in the queue. Now, we need a worker that consume these messages.

    • $ node worker.js
  10. All messages in the queue are consumed by the worker.

<style>
form.form-example {
display: table;
}
div.form-example {
display: table-row;
}
label,input {
display: table-cell;
margin-bottom: 10px;
}
label {
padding-right: 10px;
}
</style>
<form action="http://localhost:8080" method="POST" class="form-example">
<div class="form-example">
<label for="name">Enter your name: </label>
<input type="text" name="name" id="name" required />
</div>
<div class="form-example">
<label for="email">Enter your email: </label>
<input type="email" name="email" id="email" required />
</div>
<div class="form-example">
<label for="phone">Enter your phone: </label>
<input type="phone" name="phone" id="phone" required />
</div>
<div class="form-example">
<input type="submit" value="Subscribe!" />
</div>
</form>
const functions = require('@google-cloud/functions-framework');
var amqp = require('amqplib/callback_api');
functions.http('contact-form', (req, res) => {
amqp.connect('amqp://user:password@localhost', function(error0, connection) {
if (error0) {
throw error0;
}
connection.createChannel(function(error1, channel) {
if (error1) {
throw error1;
}
var data = {
'name': req.body.name,
'email': req.body.email,
'phone': req.body.phone
};
const exchange = 'contact-form';
const queue = exchange + '-queue'
channel.assertExchange(exchange, 'fanout', { durable: true });
channel.assertQueue(queue, { durable: true });
channel.bindQueue(queue, exchange, '');
// Convert data to string before publish
channel.publish(exchange, '', Buffer.from(JSON.stringify(data)),{ persistent: true });
console.log(data);
});
});
res.sendStatus(200);
});
{
"dependencies": {
"@google-cloud/functions-framework": "^3.4.2",
"amqplib": "^0.10.4"
}
}
var amqp = require('amqplib/callback_api');
amqp.connect('amqp://user:password@localhost', function(error0, connection) {
if (error0) {
throw error0;
}
connection.createChannel(function(error1, channel) {
if (error1) {
throw error1;
}
const exchange = 'contact-form';
const queue = exchange + '-queue';
channel.consume(queue, function(msg) {
if(msg.content) {
data = JSON.parse(msg.content); // Convert back to an object
console.log('Your name:', data.name);
console.log('Your email:', data.email);
console.log('Your phone:', data.phone);
channel.ack(msg); // ack rabbit you finished your work
}
}, {
noAck: false
});
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment