Winner's Excogitations

A chronicle of the thoughts, learning experiences, ideas and actions of a tech junkie, .NET, JS and Mobile dev, aspiring entrepreneur, devout Christian and travel enthusiast.

[HOW TO] Add CORS Support to your Fastify app
3 years ago · 1 minute read

bolorundurowb_com/production/article/qstzevws88huol6nt49d

Introduction

I have been developing web APIs with ExpressJS running on Node for a few years and while I had heard about Fastify, I hadn't ever felt the need to use it until I decided to create a mini language and framework benchmark and decided to take a look and its performance blew me away.

Since then, I decided to develop a new project using the Fastify framework and one of the first things that need to be added to a new API is support for Cross-Origin Resource Sharing (CORS). For those who may not know what CORS is, Mozilla defines CORS as " an HTTP-header based mechanism that allows a server to indicate any origins (domain, scheme, or port) other than its own from which a browser should permit loading resources". Which, when simplified is a system that allows your API to handle requests from any source based on the CORS policy you create.

For this guide, the assumption is made that you already have your Fastify project set with at least basic API initialization logic set.

Usage

To start, you would need the fastify-cors package from NPM. Depending on your package manager, you can run any of the following commands:

npm i fastify-cors

or

yarn add fastify-cors

In the file that holds your API initialization logic, some may name theirs main.js, server.js or index.js, import the cors package you just installed:

const fastify = require('fastify');
...
const cors = require('fastify-cors');

With that done, we register it with Fastify as middleware as follows:

fastify.register(cors, { });

If you want to customize the functions of the middleware, you can change those parameters by adding the updated fields to the second parameter passed to the fastify.register() call.

fastify.register(cors, { 
  // make customizations here
});

Some of the properties that can be seen on the official documentation page

Conclusion

I generally feel excited to share the things I learn with anyone who'll listen and if this has been helpful, feel free to let me know!

Cheers!

Clustering in NodeJS
6 years ago · 3 minutes read

ocbqfgrgpiliepukqome

image credit: slideshare

The problem

I got started with NodeJS about three years ago. As I learnt to build enterprise-grade applications using the runtime, a major drawback I kept coming across in my research was the fact that NodeJS is aggressively single-threaded. What this meant was that no matter how many threads and cores your computer or server had, the NodeJS process was limited to the one thread on which it was running. This major limitation meant a NodeJS web application could not fully utilize the hardware on which it was running.

The solution

Enter the cluster module. The cluster module is one of the native (it comes bundled with the NodeJS runtime and doesn't require installing from NPM and what not) modules and it gives developers the ability to utilize the hardware available to their applications by allowing a single NodeJS web application utilize worker processes to help handle requests as well.

How to use

After coming across the cluster module, I felt integrating it into my application would require quite a number of changes to make the logic "process-aware" and "process-safe", that turned out to be a wrong assumption as the integration into an existing project was as painless as it could possibly be.

To get started, first require the cluster module as well as the os module (would explain why in a bit) in your server.js file or whatever JavaScript file your HTTP server creation logic is in like so:

...
const cluster = require('cluster');
const os = require('os');
...

Next, we want to add logic to determine what process our code is currently running in, i.e whether or not it is a master or worker process. We can do that by checking the isMaster boolean field on the cluster object.

...
if (cluster.isMaster) {
  // this is the master process
} else {
  // this is a worker process
}
...

Next, when the master process starts, we want to create worker processes based on the number of cores the current machine has. This is where the os module comes into play, the os module gives access to operating system level information and logic. We create worker/child process like so:

if (cluster.isMaster) {
  // this is the master process
  const cpuCount = os.cpus().length;

  for (let i = 0; i < cpuCount; i += 1) {
    cluster.fork();
  }
} else {
  // this is a worker process
}
...

Now we have successfully created our worker processes, next, we want to give the worker processes the logic they should execute when they are up. For this, we copy the logic we used to set up our web server into the else block. The logic to set up your web server would be different from mine but I'll use mine as an example. I am setting up an express web server which would provide a bunch of RESTful endpoints as well as serve some static files. This is what my web server logic looks like:

...
} else {
  const app = express();
  const router = express.Router();
  const port = process.env.PORT || 3000;

  app.use(morgan('dev'));
  app.use(cors());
  app.use(bodyParser.json());
  app.use(bodyParser.urlencoded({
    extended: true
  }));

  routes.route(router);
  app.use('/v1/', router);

  app.use('/', express.static('public'), (req, res) => {
    res.status(200).sendFile(path.join(__dirname, '/public/index.html'));
  });

  app.listen(port, () => console.log(`Server started on ${port}`));
}
...

One last step, we need to know when one or more worker processes die or a killed off and replace them. To do that, we listen for the exit event on the cluster and carry out our revival efforts there.

...
cluster.on('exit', function (worker) {
  console.log('Worker %d died :(', worker.id);
  cluster.fork();
});

With that last step, we are good to go. Your web server should be ready to handle a bunch more requests right off the bat. The final, complete server.js file can be found here

Cheers.