Categories
Express JavaScript Nodejs

Use body-parser Express Middleware to Parse Text and URL-Encoded Requests

By default, Express 4.x or later doesn’t come with anything to parse request bodies. Therefore, we need to add something to do this.

In this article, we’ll look at how to use the body-parser middleware to do this with text and URL-encoded request bodies.

Parsing Text Bodies

We can parse text request bodies with the text method. It supports automatic inflation of gzip and deflate encodings.

The parsed string will be set as the value of req.body.

It takes an optional option object with the following properties:

  • defaultCharset — specifies the default character set for the text content if it’s not specified in the Content-Type header. Defaults to utf-8.
  • inflate — compressed request bodies will be inflated when this is set to true . Otherwise, they’ll be rejected.
  • limit — controls the maximum request body size. If it’s number, then it’s measured in bytes. If it’s a string then it can be parsed into a number of bytes.
  • type — this is used to determine what media type it’ll parse. It can be a string, array of strings or a function. If it’s not a function, then it’s directly passed into the type-is library. Otherwise, the request is parsed if the data type the function is called with returns a truthy value
  • verify — this is a function with signature (req, res, buf, encoding), where buf is a Buffer object of the raw request body. The parsing can be aborted by throwing an error in the function.

For example, we can use it as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const app = express();  
const options = {  
  inflate: true,  
  limit: 1000,  
  defaultCharset: 'utf-8'  
};  
app.use(bodyParser.text(options));
app.post('/', (req, res) => {  
  res.send(req.body);  
});
app.listen(3000);

Then when we make a POST request to / with the body foo, we get foo back.

Parsing URL Encoded Request Bodies

We can use the urlencoded method to pares URL encoded bodies. It supports automatic inflation of gzip and deflate encodings.

The parsed request body will be set as the value of req.body. The object will contain key-value pairs, where the value can be a string or an array when extended is set to false or anything otherwise.

It takes an optional option object with the following properties:

  • extended — the extended option allows us to choose between parsing the URL-encoded data with the querystring library when false or the qs library when this is set to true . The extended syntax lets us encode rich objects and arrays, allowing for a JSON-like experience with URL-encoded. The default value is true, but using the default value has been deprecated.
  • inflate — compressed request bodies will be inflated when this is set to true. Otherwise, they’ll be rejected.
  • limit — controls the maximum request body size. If it’s number, then it’s measured in bytes. If it’s a string then it can be parsed into a number of bytes.
  • parameterLimit — lets us control the maximum number that are allowed in the URL encoded data. If it’s more than the given value then a 413 response code will be returned. The default is 1000.
  • type — this is used to determine what media type it’ll parse. It can be a string, array of strings or a function. If it’s not a function, then it’s directly passed into the type-is library. Otherwise, the request is parsed if the data type the function is called with returns a truthy value
  • verify — this is a function with signature (req, res, buf, encoding), where buf is a Buffer object of the raw request body. The parsing can be aborted by throwing an error in the function.

For example, we can use it as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const app = express();  
const options = {  
  inflate: true,  
  limit: 1000,  
  extended: true  
};  
app.use(bodyParser.urlencoded(options));
app.post('/', (req, res) => {  
  res.send(req.body);  
});
app.listen(3000);

Then when we send a URL encoded POST body to the / route with the body name=Mary&age=10, then we get:

{"name":"Mary","age":"10"}

We can send an array by sending:

name=Mary&age=10&favoriteFood=apple&favoriteFood=orange

Then we get back:

{"name":"Mary","age":"10","favoriteFood":["apple","orange"]}

as the response. This assumes that extends is true.

If we set the parameterLimit to 1 as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const app = express();  
const options = {  
  inflate: true,  
  limit: 1000,  
  extended: true,  
  parameterLimit: 1,  
};  
app.use(bodyParser.urlencoded(options));
app.post('/', (req, res) => {  
  res.send(req.body);  
});
app.listen(3000);

then we get a 413 error back.

Conclusion

With the text method, body-parser can parse text request bodies. We’ll get a string with the parsed body with req.body.

To parse URL-encoded request bodies, we can use the urlencoded method. It can parse arrays and objects. URL-encoded bodies are sent as query strings, and we can send a query with the same key multiple times to make it parsed as an array.

Categories
JavaScript Nodejs

Node.js FS Module — Changing File Permissions and Ownership with File Descriptors

Manipulating files and directories are basic operations for any program. Since Node.js is a server side platform and can interact with the computer that it’s running on directly, being able to manipulate files is a basic feature. Fortunately, Node.js has a fs module built into its library. It has many functions that can help with manipulating files and folders. File and directory operation that are supported include basic ones like manipulating and opening files in directories. Likewise, it can do the same for files. It can do this both synchronously and asynchronously. It has an asynchronous API that have functions that support promises. Also it can show statistics for a file. Almost all the file operations that we can think of can be done with the built in fs module. In this article, we will get the file descriptor of a file and then use that to manipulate the permissions with the fchmod family of functions and change ownership of the file with the fchown family of functions.

Get the File Descriptor with the Open Function

A file descriptor of a file is an unique identifier of a file which we can use to do various operations to it. To get the file descriptor of a file, we can use the promise version of the open function and all its variants to do so. The promise version of the open function takes 2 arguments. The first is the file path, which can be a string, a Buffer object or an URL object. The second is the flag for what can our program do with the file after it’s opened. They can be one of the following strings:

  • 'a' – Opens a file for appending, which means adding data to the existing file. The file is created if it does not exist.
  • 'ax' – Like 'a' but exception thrown if the path exists.
  • 'a+' – Open file for reading and appending. The file is created if it doesn’t exist.
  • 'ax+' – Like 'a+' but exception thrown if the path exists.
  • 'as' – Opens a file for appending in synchronous mode. The file is created if it does not exist.
  • 'as+' – Opens a file for reading and appending in synchronous mode. The file is created if it does not exist.
  • 'r' – Opens a file for reading. An exception is thrown if the file doesn’t exist.
  • 'r+' – Opens a file for reading and writing. An exception is thrown if the file doesn’t exist.
  • 'rs+' – Opens a file for reading and writing in synchronous mode.
  • 'w' – Opens a file for writing. The file is created (if it does not exist) or overwritten (if it exists).
  • 'wx' – Like 'w' but fails if the path exists.
  • 'w+' – Opens a file for reading and writing. The file is created (if it does not exist) or overwritten (if it exists).
  • 'wx+' – Like 'w+' but exception thrown if the path exists.

The promise version of the open function resolves to a file handle, which has the fd property with the file descriptor.

Changing File Permission of File Referenced by the File Descriptor with the fs.fchmod Function

After we got the file descriptor, we can use it to change the permission of the file that’s identified by the file descriptor. To do so, we use the fchmod function. The function takes 3 arguments. The first is the file descriptor, which is an integer. The second is the mode, which is the permission and sticky bits we want to change for the file. The mode consists of 3 octal digits, like with Unix or Linux file permissions. The leftmost digit is the permission for the owner. The middle digit is the permission of the group, and the rightmost digit is the permission for others. Valid number include the following:

  • 7 — read, write, and execute
  • 6 — read and write
  • 5 — read and execute
  • 4 — read only
  • 3 — write and execute
  • 2 — write only
  • 1 — execute only
  • 0 — no permission

The final argument is a callback which is called when the file permission change operation ends. It has an err parameter which is null when the operation succeeds and has an object with the error information when the operation fails.

We can use the fchmod function to change the file permission asynchronously like in the following code:

const fsPromises = require("fs").promises;  
const fs = require("fs");(async () => {  
  try {  
    const { fd } = await fsPromises.open("./files/file.txt", "r");  
    fs.fchmod(fd, 0o777, err => {  
      if (err) throw err;  
      console.log("File permission change succcessful");  
    });  
  } catch (error) {  
    console.log(error);  
  }  
})();

To confirm that the fchmod function worked as we expected, we can do the run the following commands in Linux systems. One way is to run ls -l , like in the command below:

ls -l ./files/file.txt

When we run that, we get some output like:

-rwxrwxrwx 1 hauyeung hauyeung 16 Nov  2 12:26 ./files/file.txt

The leftmost column has the permissions. rwxrwxrwx is the same as 777 which means that the fchmod function call worked correctly.

We can also use the stat command.

File: './files/file.txt'  
  Size: 16              Blocks: 0          IO Block: 512    regular file  
Device: eh/14d  Inode: 22799473115106242  Links: 1  
Access: (0777/-rwxrwxrwx)  Uid: ( 1000/hauyeung)   Gid: ( 1000/hauyeung)  
Access: 2019-11-02 12:26:47.996290200 -0700  
Modify: 2019-11-02 12:26:47.996290200 -0700  
Change: 2019-11-03 10:34:58.342785500 -0800  
 Birth: -

We can see from the Access field that we have 0777 as the permission, which means that the fchmod operation worked correctly.

There’s also a synchronous version of the fchmod function called the fchmodSync function. The function takes 2 arguments. The first is the file descriptor, which is an integer. The second is the mode, which is the permission and sticky bits we want to change for the file. The mode should be the same as the ones we have above. It returns undefined .

We can use it along with the openSync function, which is the synchronous version of the open function to get the file descriptor, and then use the file descriptor returned from the openSync function as an argument for the fchmodSync function, like in the following code:

const fs = require("fs");try {  
  const fd = fs.openSync("./files/file.txt", "r");  
  fs.fchmodSync(fd, 0o777);  
  console.log("File permission change succcessful");  
} catch (error) {  
  console.log(error);  
}

The openSync function takes the same arguments as the open function but without the callback function as the third argument. When we run the code above, we should get the same output as the asynchronous version that we have previously.

Changing File Ownership of File Referenced by the File Descriptor with the fs.fchown Function

The fchown function let us change the ownership of a file asynchronously. It takes 4 arguments. The first argument is the file descriptor which is an integer. The second argument is the UID, which is the user ID of the user. The third argument is the GID, which is the group ID, and the fourth argument is a callback function which has an err parameter which is null is the chown operation is successful, otherwise err will be an error object. The callback function is called when the chown operation is finished whether it’s successful or not.

To use the fchown function, we can write something like the following code:

const fsPromises = require("fs").promises;  
const fs = require("fs");(async () => {  
  try {  
    const { fd } = await fsPromises.open("./files/file.txt", "r");  
    fs.fchown(fd, 1000, 1000, err => {  
      if (err) throw err;  
      console.log("File permission change succcessful");  
    });  
  } catch (error) {  
    console.log(error);  
  }  
})();

with UID 1000 and group with GID 1000. To find out the UID and GID of the user and group of the current user in Linux systems, we can use the id command.

The fchown function has a synchronous version called fchownSync . It takes 3 arguments. The first argument is the file descriptor which is an integer. The second argument is the UID, which is the user ID of the user. The third argument is the GID, which is the group ID. It returns undefined . We can use it along with the openSync function to get the file descriptor like in the following code:

const fs = require("fs");try {  
  const fd = fs.openSync("./files/file.txt", "r");  
  fs.fchownSync(fd, 1000, 1000);  
  console.log("File permission change succcessful");  
} catch (error) {  
  console.log(error);  
}

To confirm that the fchown or fchownSync worked as we expected, we can do the run the following commands in Linux systems. One way is to run ls -l , like in the command below:

ls -l ./files/file.txt

We can also use the stat command. For example, we can run stat ./files/file.txt to get the ownership information of ./files/file.txt from the Uid and Gid output. With the stat command, we should get output that looks something like:

File: './files/file.txt'  
  Size: 16              Blocks: 0          IO Block: 512    regular file  
Device: eh/14d  Inode: 22799473115106242  Links: 1  
Access: (0555/-r-xr-xr-x)  Uid: ( 1000/hauyeung)   Gid: ( 1000/hauyeung)  
Access: 2019-11-02 12:26:47.996290200 -0700  
Modify: 2019-11-02 12:26:47.996290200 -0700  
Change: 2019-11-02 12:44:45.037581600 -0700  
 Birth: -

Also, we can filter out the information we don’t need and just get the UID and GID with the "%U %G" format sequence. For example, we can run stat -c “%U %G” ./files/file.txt to get the UID and GID only for file.txt .

With the fchown function, we can change the ownership of a file given the file descriptor of the file. There are 2 asynchronous versions of the function, one is the regular asynchronous version and one is the promise version. There’s also one synchronous version of the chown function, which is the chownSync function. They both change the owner by passing in the UID and GID of the user of your choice. UID is the user ID and GID is the group ID. We can change the permission of the file identified with the file descriptor with the fchown function. . There are 2 asynchronous versions of the fchown function, one is the regular asynchronous version and one is the promise version. There’s also a synchronous version of the fchown function called the fchownSync function. We can confirm that the operations worked with the ls -l or stat commands on POSIX systems.

Categories
JavaScript Nodejs

Using the Node.js OS Module — Part 3

The Node.js OS module has many useful utility functions for getting information about the computer system that the OS module’s program is running on. It can get us information about hardware like CPUs, endianness, the home directory, IP address, hostname, the platform the program is running on, system uptime, information about the currently logged in user and more.

We can use the OS module by writing const os = require('os'); at the top of a JS file. There are many useful properties in the OS module. Below are more useful properties in the OS module:

os.release

The os.release function returns a string that identifies the operating system release. On Unix and Linux systems, the function identifies the operating system with the uname command. On Windows, the GetVersionExW() function from the Win32 API is used. For example, if we run:

console.log(os.release());

Then we may get something like:

'4.15.0-1036-gcp'

os.setPriority

The os.setPriority function lets us set the scheduling priority of a process specified by the process ID. It takes 2 arguments. The first is the process ID, which is a whole number that identifies the running process to set the priority to. The default value to 0.

The second argument is the priority, which is a whole number which indicates the scheduling of the process priority we want to set. It ranges from -20 for the highest priority to the lowest which is 19.

Because of the differences between priority levels between Windows and POSIX systems, Node.js provides us with constants that have the levels of priorities for processes.

They’re in the os.constants.priority constant. On Windows, setting the process priority to the PRIORITY_HIGHEST setting requires elevated privileges. If the user that’s running the program doesn’t have elevated privileges, then it will be silently reduced to PRIORITY_HIGH.

The following priority constants are provided by Node.js:

  • PRIORITY_LOW — The lowest process scheduling priority. This corresponds to IDLE_PRIORITY_CLASS on Windows and a nice value of 19 on all other platforms.
  • PRIORITY_BELOW_NORMAL — This corresponds to BELOW_NORMAL_PRIORITY_CLASS on Windows and a nice value of 10 on all other platforms.
  • PRIORITY_NORMAL — The default process scheduling priority. This corresponds to NORMAL_PRIORITY_CLASS on Windows and a nice value of 0 on all other platforms.
  • PRIORITY_ABOVE_NORMAL — This corresponds to ABOVE_NORMAL_PRIORITY_CLASS on Windows and a nice value of -7 on all other platforms.
  • PRIORITY_HIGH — This corresponds to HIGH_PRIORITY_CLASS on Windows and a nice value of -14 on all other platforms.
  • PRIORITY_HIGHEST — The highest process scheduling priority. This corresponds to REALTIME_PRIORITY_CLASS on Windows and a nice value of -20 on all other platforms.

For example, we can use it as in the following code:

os.setPriority(0, os.constants.priority.PRIORITY_LOW)

os.tmpdir

The os.tmpdir function returns a string that specifies the operating system’s default directory for storing temporary files. For example, if we write:

console.log(os.tmpdir());

Then we may get:

'/tmp'

on Linux systems.

os.totalmem

The os.totalmem function returns the total amount of system memory as a number of bytes in integer form. For example, if we run:

console.log(os.totalmem());

Then we may get something like:

27389460480

os.type

The os.type function returns a string that identifies the operating system as returned by the uname command. For example, it may be 'Linux' on Linux, 'Darwin' on macOS, and 'Windows_NT' on Windows. For example, if we run the following:

console.log(os.type());

on a Linux system, then we get ‘Linux’ .

os.uptime

The os.uptime function returns an integer that has the system uptime in number of seconds. For example, if we run:

console.log(os.uptime());

Then we may get something like:

4928

os.userInfo

The os.userInfo function returns an object with information about the currently effective user, which is the user identity that the user is assumed.

This may be different from the currently logged in user since a user can run programs as a different user in multiuser operating systems. On POSIX systems, this is typically a subset of the password file.

The returned object includes the username , uid , gid , shell , and homedir properties. On Windows, the uid and gid are -1, and shell is null .

A SystemError will be thrown if a user has no username or homedir . The value of homedir returned by the os.userInfo function is provided by the operating system.

This is different from the os.homedir function which returns a string of the path o the home directory of the user from various environment variables. On Unix and Linux systems, it will use the $HOME variable if it’s defined.

Otherwise, it will look up the home directory path by the effective UID, which is the user ID of the user identity that you’re currently assuming. For example, if you used sudo to use the computer as a root user then the effective user ID would be the user ID of the root user.

On Windows, the value of the USERPROFILE will be used if it’s defined. Otherwise, it will be the path of the profile directory of the current user.

It takes one argument, which is an object that lets us set the options for calling the function. It can have one property, which is the encoding property, which is a string that indicates the character encoding used to interpret the resulting strings.

The default value is 'utf8' , but it can also be 'buffer' , which will set the change the values of the properties of the returned object to Buffer objects. The argument is optional.

For example, if we run the following code:

console.log(os.userInfo({ option: 'utf8' }));

We may get something like the following:

{ uid: 1000,  
  gid: 1000,  
  username: 'runner',  
  homedir: '/home/runner',  
  shell: '/bin/bash' }

In the output above, the uid is the user identifier, which identifies the user identity that the currently logged in user has assumed, which may be the currently logged in user if it’s running programs as itself, or it can be a different user like the root user if the Node.js program is currently run as root. This is also called the currently effective user.

The gid is the group ID. It’s the identifier that associates a user with other users that share something in common. A user can be a member of one or more groups and may have more than one GID.

The username is the username of the currently effective user. The homedir is the home directory of the currently effective user. The shell is the command-line interpreter that’s currently being used by the currently effective user.

The Node.js OS module has many useful utility functions for getting information about the computer system that the OS module’s program is running on.

The modules have many more properties containing useful information like CPUs, endianness, home directory, IP address, hostname, the platform the program is running on, system uptime, information about the currently logged in user and more. It also lets us set the priority of running processes.

Categories
Express JavaScript Nodejs

Security Best Practices for Using Express Apps in Production

When we use an Express app for production, i.e. it’s used by external users, we have to be careful about security since it’s available to the outside world.

In this article, we’ll look at some security best practices when running Express apps in a production environment.

Don’t Use Outdated Versions of Express

Outdated versions of Express are no longer maintained and may have unpatched security vulnerabilities, leaving our apps at risk for all sorts of attacks.

Use TLS

If we’re transporting data that needs to be secured, we should use TLS so that users’ data is protected. This means that we avoid man-in-the-middle attacks and packet sniffing.

Even our apps don’t transport secure data, it still gives users more confidence that our website is secure.

We can get free TLS certificates with Let’s Encrypt. It’s an automated service that generates new certificates that are trusted by browsers,

Use Helmet

Helmet is a series of Express middlewares to protect our apps with some well-known security vulnerabilities on the web by setting HTTP headers.

The middlewares included with Helment includes:

  • csp — sets the Content-Security-Policy header to help prevent cross-site scripting attacks and other cross-site injections.
  • hidePoweredBy — removes the X-Powered-By header
  • hpkp — adds public key pinning header to prevent man-in-the-middle attacks with forged certificates
  • hsts — sets Strict-Transport-Security header that enforces HTTPS connects to the server.
  • ieNoOpen 0 sets X-Download-Options for IE 8 or later
  • noCache — sets Cache-Control and Pragma header to disable client-side caching
  • noSniff — sets X-Content-Type-Options header to prevent browsers from MIME-sniffing a response away from the declared content type
  • frameguard — sets the X-Frame-Options header to provide clickjacking protection
  • xssFilter — sets X-XSS-Protection to enable cross-site scripting filter in most recent web browsers

It’s a good idea to at least disable the x-powered-by response header so that attackers won’t know that our app is an Express app and launch specific attacks for it.

Use Cookies Securely

We can use the express-session or cookie-session middleware to use cookies securely.

express-session stores session data on the server. It only saves the session ID on the cookie itself.

We can set up a session store for production use since it uses an in-memory store by default.

cookie-session stores the whole cookie on the client-side. We shouldn’t exceed 4093 bytes when we set our cookies.

The cookie data will be visible to the client, so secret data shouldn’t be sent to the client with cookie-session .

Don’t Use Default Session Cookie Name

The default session cookie name set by Express shouldn’t be used since it can identify that an app is running on Express.

We can do this by passing in an object to session as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const session = require('express-session');  
const app = express();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.set('trust proxy', 1);  
app.use(session({  
  secret: 'secret',  
  name: 'sessionId'  
}))
app.listen(3000);

Set Cookie Security Options

To enhance security, we can set various cookie options. The following options are available:

  • secure — ensures browsers only send cookie over HTTPS
  • httpOnly — ensures cookie is sent only over HTTP(S) and not client-side JavaScript. This helps us prevent XSS attacks
  • domain — indicates the domain of the cookie, which can be used to compare against the domain of the server in the URL that’s requesting the cookie.
  • path — indicates the path to compare against the requested path, then send the cookie in the request
  • expires — set the expiration date for persistent cookies.

For example, we can use it as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const session = require('express-session');  
const app = express();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));  
const expiryDate = new Date(Date.now() + 60 * 60 * 1000)  
app.use(session({  
  name: 'session',  
  secret: 'secret',  
  keys: ['foo', 'bar'],  
  cookie: {  
    secure: true,  
    httpOnly: true,  
    domain: 'EnormousBeneficialScript--five-nine.repl.co',  
    path: '/',  
    expires: expiryDate,  
  }  
}));
app.get('/', (req, res) => {  
  req.session.foo = 'foo';  
  res.send(req.session.foo);  
})
app.listen(3000);

Prevent Brute-Force Attacks

We can rate limit our authorization routes so that attackers can’t use brute-force attacks to guess the credentials stored in our app’s database.

For example, we can limit by IP address by limiting the number of failed attempts that people can make if they have the same user name and IP address.

Then we lock out the user for some time if the number of failed attempts what we can tolerate.

If more than 100 failed attempts in a day are made then we block the IP address.

We can use the rate-limiter-flexible package to do rate-limiting of our routes.

Conclusion

To keep our Express app secure in a production environment, we should take a few precautions.

First, we should use TLS for transporting data to keep them from being sniffed and prevent man-in-the-middle attacks.

Next, we should set headers in ways that prevent users from finding information about our app and to enforce secure communication.

Also, we should use cookies securely by signing it with a secret and set the security options for them.

Finally, to prevent brute-force attacks, we should set a rate limit for our API calls so that attackers can’t guess our users’ credentials by repeated login attempts.

Categories
JavaScript Nodejs

Using the Node.js OS Module — Part 2

The Node.js OS module has many useful utility functions for getting information about the computer system that the OS module’s program it is running on. It can provide information about hardware like CPUs, endianness, the home directory, IP address, hostname, the platform the program is running on, system uptime, information about the currently logged in user and more.

We can use the OS module by writing const os = require('os'); at the top of our code. There are many useful properties in the OS module. Below are more useful properties in the OS module:

os.cpus

The os.cpus() function returns an array of objects that has various information about each logical core of the host computer’s CPU. Each entry has a few properties. There’s the model property, which is a string that indicates the model of the computer’s CPU. The speed property is a numeric property that is measured in megahertz. The times property is an object with the following properties:

  • user — a numeric property that indicates the number of milliseconds the CPU has spent in user mode.
  • nice — a numeric property that indicates the number of milliseconds the CPU has spent in nice mode. Nice mode is where the CPU is running processes that have a positive nice value, which means a process that’s a lower priority.
  • sys — a numeric property that indicates the number of milliseconds the CPU has spent in sys mode.
  • idle — a numeric property that indicates the number of milliseconds the CPU has spent in idle mode. A CPU is idle when it’s not used by any program.
  • irq— a number property the number of milliseconds the CPU has spent in IRQ mode. IRQ is a hardware signal that makes the CPU temporarily stop a running program and allow an interrupt handler program to run instead.

For example, we can use the function like the following:

console.log(os.cpus());

We can get the output that resembles the following:

[ { model: 'Intel(R) Xeon(R) CPU @ 2.30GHz',  
    speed: 2300,  
    times:  
     { user: 3367100, nice: 0, sys: 757800, idle: 9833900, irq: 0 } },  
  { model: 'Intel(R) Xeon(R) CPU @ 2.30GHz',  
    speed: 2300,  
    times:  
     { user: 3387000, nice: 0, sys: 730100, idle: 10054300, irq: 0 } },  
  { model: 'Intel(R) Xeon(R) CPU @ 2.30GHz',  
    speed: 2300,  
    times:  
     { user: 3259600, nice: 0, sys: 748300, idle: 10168800, irq: 0 } },  
  { model: 'Intel(R) Xeon(R) CPU @ 2.30GHz',  
    speed: 2300,  
    times:  
     { user: 3229700, nice: 0, sys: 755800, idle: 10195600, irq: 0 } } ]

os.endianness

The os.endianness() function returns a string identifying the endianness of the CPU for which the Node.js run-time binary is compiled from. The 2 possible values are:

  • 'BE' — big-endian. A big-endian CPU order places with the most significant byte first and the least significant byte last.
  • 'LE' — little-endian, the opposite of big-endian.

If we run console.log on the return value of os.endianness() we may get something like the following:

'LE'

os.freemem

The os.freemem() function returns an integer that indicates the amount of free memory in the number of bytes. If we run console.log of the output of os.freemem() , we get something like:

15338930176

os.getPriority

The os.getPriority function returns an integer indicating the scheduling priority of the process which is specified by the PID. It takes one argument, which is the process ID passed in as an integer. If the PID isn’t provided or it’s 0, then the priority of the current process is returned. For example, if we write:

os.getPriority()

Then we get a number. 19 indicates the lowest CPU priority and -20 indicates the highest. Processor priority levels in Node.js are defined by the following constants:

  • PRIORITY_LOW — The lowest process scheduling priority. This corresponds to IDLE_PRIORITY_CLASS on Windows and a nice value of 19 on all other platforms.
  • PRIORITY_BELOW_NORMAL — This corresponds to BELOW_NORMAL_PRIORITY_CLASS on Windows and a nice value of 10 on all other platforms.
  • PRIORITY_NORMAL — The default process scheduling priority. This corresponds to NORMAL_PRIORITY_CLASS on Windows and a nice value of 0 on all other platforms.
  • PRIORITY_ABOVE_NORMAL — This corresponds to ABOVE_NORMAL_PRIORITY_CLASS on Windows and a nice value of -7 on all other platforms.
  • PRIORITY_HIGH — . This corresponds to HIGH_PRIORITY_CLASS on Windows and a nice value of -14 on all other platforms.
  • PRIORITY_HIGHEST — The highest process scheduling priority. This corresponds to REALTIME_PRIORITY_CLASS on Windows and a nice value of -20 on all other platforms.

os.homedir

The os.homedir function returns a string of the path o the home directory of the user. On Unix and Linux systems, it will use the $HOME variable if it’s defined. Otherwise, it will look up the home directory path by the effective UID, which is the user ID of the user identity that you’re currently assuming. For example, if you used sudo to use the computer as a root user then the effective user ID would be the user ID of the root user. On Windows, the value of the USERPROFILE will be used if it’s defined. Otherwise, it will be the path of the profile directory of the current user. For example, if we run console.log on the output of os.homedir() , then we may get something like:

'/home/runner'

if you’re on a Linux system.

os.hostname

The os.hostname function returns the hostname of the operating system as a string. For example, if we call console.log on the return value of os.hostname() , then we may get something like ‘5b84600c80eb’ .

os.loadavg

The os.loadavg function returns a number array containing 1, 5, and 15-minute load averages. The load average measures system activity, which is calculated by the operating system and expressed as a decimal number. The ideal load average should be less than the number of logical CPUs in the system. This function only works on Unix and Linux system. On Windows, it always returns [0,0,0] . For example, if we run this function on the Linux system, like in the following code:

console.log(os.loadavg())

We may get something like:

[ 12.60791015625, 13.3916015625, 9.8798828125 ]

os.networkInterfaces

The os.networkInterfaces function returns an object that has the network interfaces that have been assigned a network address. The keys on the returned object identify a network interface. The corresponding value of the keys is an array of objects that describe an assigned network address. Properties of an assigned network address object include:

  • address — a string that has the assigned IPv4 or IPv6 address
  • netmask — a string that has the IPv4 or IPv6 network mask
  • family — a string that has 2 possible values: IPv4 or IPv6
  • mac — a string that has the MAC address of the network interface
  • internal — a boolean value that is true if the network interface is a loopback or similar interface that is not remotely accessible. Otherwise, it’s false
  • scopeid — a number that has the IPv6 scope ID, applicable only when family is IPv6
  • cidr — a string that has the assigned IPv4 or IPv6 address with the routing prefix in CIDR notation. CIDR notation has 2 groups of numbers. The first is the group of bits, which is the network address. The first group is followed by a slash. The second group is the number of bits that are considered significant for network routing. For example, if we have an IP address 192.168.0.15/24, then 192.168.0.15 is the network address and 24 is the number of significant bits for network routing purposes. If the netmask is invalid, this property is set to null.

For example, if we run:

console.log(os.networkInterfaces());

Then we may get something like:

{ lo:  
   [ { address: '127.0.0.1',  
       netmask: '255.0.0.0',  
       family: 'IPv4',  
       mac: '00:00:00:00:00:00',  
       internal: true,  
       cidr: '127.0.0.1/8' } ],  
  eth0:  
   [ { address: '172.18.0.103',  
       netmask: '255.255.0.0',  
       family: 'IPv4',  
       mac: '02:42:ac:12:00:67',  
       internal: false,  
       cidr: '172.18.0.103/16' } ] }

We have lo for the loopback address and eth0 for the Ethernet interface.

os.platform

The os.platform function returns a string that identifies that operating system platform of the computer that compiled the Node.js binary. The current possible values are 'aix', 'darwin', 'freebsd', 'linux', 'openbsd', 'sunos', or 'win32' . It’s the same as the process.platform property. The value 'android' maybe returned if the Node.js binary is built on an Android device. However, Android support in Node.js is in the experimental phase. For example, if we run:

console.log(os.platform());

Then we may get something like:

'linux'

The Node.js OS module has many useful utility functions for getting information about the computer system that the OS module’s program is running on. The modules have many more properties containing useful information like CPUs, endianness, home directory, IP address, hostname, the platform the program is running on, system uptime, information about the currently logged in user and more.