Node.js Web Development: A Beginner's Guide

Node.js Web Development:  A Beginner's Guide

This post is a write-up of how I learnt more about server-side web development with Node.js, and a brief comparison of writing a simple HTTP server using 3 different frameworks, Express, Koa.js and Hapi.js.

For the bulk of my web career, I’ve worked exclusively on the client-side of things. Designing responsive layouts, creating visualisations from large amounts of data, building application dashboards etc. But I never really had to deal with routing or HTTP requests directly. Until recently.

This post is a write-up of how I learnt more about server-side web development with Node.js, and a brief comparison of writing a simple HTTP server using 3 different frameworks, Express, Koa.js and Hapi.js.

Some networking basics

When I was starting out in the web industry a couple years back, I stumbled upon a Computer Networks course by Professor David Wetherall on Coursera. Unfortunately, it is no longer available but the lectures are still available on the Pearson website.

I really liked this course because it explained what was happening under the hood in a digestible manner, so if you can get your hands on the textbook, Computer Networks, give it a read for all the in-depth details of the wonders of networking.

Over here though, I’m only going to cover a brief overview of things for context. HTTP (Hypertext Transfer Protocol) is a communications protocol used in computer networks. The internet has plenty of them, like SMTP (Simple Mail Transfer Protocol), FTP (File Transfer Protocol), POP3 (Post Office Protocol 3) and so on.

These protocols allow devices with vastly different hardware/software to communicate with each other because they provide well-defined message formats, rules, syntax and semantics etc. This means as long as the device supports a particular protocol, it can communicate with any other device on the network.

Operating systems usually come with support for networking protocols, like HTTP, out-of-the-box, which explains why we don’t have to explicitly install any additional software to access the web. Most networking protocols maintain an open connection between 2 devices, allowing them to transmit data back and forth.

HTTP, which is what the web runs on, is different. It is known as a connectionless protocol, because it is based on a request/response mode of operation. Web browsers make requests to the server for images, fonts, content etc. but once the request is fulfilled, the connection between the browser and server is severed.


Simplification of request/response

Servers and Clients

The term server may be slightly confusing to people new to the industry because it can refer to both the hardware (physical computers that house all the files and software required by websites) or the software (program that allows users to access those files on the web).

Today, we’ll be talking about the software side of things. But first, some definitions. URL stands for Universal Resource Locator, and consists of 3 parts: the protocol, the server and the requested file.


Anatomy of a URL

The HTTP protocol defines several methods that the browser can use to ask the server to perform a bunch of different actions, the most common being GET and POST. When a user clicks a link or enters a URL in the address bar, the browser sends a GET request to the server to retrieve the resource defined in the URL.

The server needs to know how to process this HTTP request in order to retrieve the correct file then send it back to the browser who asked for it. The most popular web server software that handles this are Apache and NGINX.


Web servers handle incoming requests and respond to them accordingly

Both are full suite open-source software packages that include features like authentication schemes, URL rewriting, logging and proxying, just to name a few. Both Apache and NGINX are written in C. Technically, you could write a web server in any language. Python, Go, Ruby, this list can go on for quite a bit. It’s just that some languages are better at doing certain things than others.

Creating an HTTP server with Node.js

Node.js is a Javascript run-time environment built on Chrome’s V8 Javascript engine. It comes with a http module that provides a set of functions and classes for building a HTTP server.

For this basic HTTP server, we will also be using file system, path and url, all of which are native Node.js modules.

Start off by importing the required modules.

const http = require('http') // To use the HTTP interfaces in Node.js
const fs = require('fs') // For interacting with the file system
const path = require('path') // For working with file and directory paths
const url = require('url') // For URL resolution and parsing

We will also create a dictionary of MIME types so we can assign the appropriate MIME type to the requested resource based on its extension. A full list of MIME types can be found at the Internet Assigned Numbers Authority.

const mimeTypes = {
  '.html': 'text/html',
  '.js': 'text/javascript',
  '.css': 'text/css',
  '.ico': 'image/x-icon',
  '.png': 'image/png',
  '.jpg': 'image/jpeg',
  '.gif': 'image/gif',
  '.svg': 'image/svg+xml',
  '.json': 'application/json',
  '.woff': 'font/woff',
  '.woff2': 'font/woff2'
}

Now we can create the HTTP server with http.createServer() function, which will return a new instance of http.Server.

const server = http.createServer()

We will pass a request handler function into createServer() with the request and response objects. This function gets called once every time an HTTP request is made against the server.

server.on('request', (req, res) => {
  // more stuff needs to be done here
})

The server is started by calling the listen method on the server object, with the port number we want the server to listen on, for example, 5000.

server.listen(5000)

The request object is an instance of IncomingMessage, and allows us to access all sorts of information about the request, like response status, headers and data.

The response object is an instance of ServerResponse, which is a writable stream, and provides numerous methods for sending data back to the client.

Within the request handler, we want to do the following things:

  • Parse the incoming request and handle those without extensions
const parsedUrl = new URL(req.url, 'https://node-http.glitch.me/')
let pathName = parsedUrl.pathname
let ext = path.extname(pathName)

// To handle URLs with trailing '/' by removing aforementioned '/'
// then redirecting the user to that URL using the 'Location' header
if (pathName !== '/' && pathName[pathName.length - 1] === '/') {
  res.writeHead(302, {'Location': pathName.slice(0, -1)})
  res.end()
  return
}

// If the request is for the root directory, return index.html
// Otherwise, append '.html' to any other request without an extension
if (pathName === '/') { 
  ext = '.html' 
  pathName = '/index.html'
} else if (!ext) { 
  ext = '.html' 
  pathName += ext
}
  • Do some rudimentary checks to determine if the requested resource exists and respond accordingly
// Construct a valid file path so the relevant assets can be accessed
const filePath = path.join(process.cwd(), '/public', pathName)
// Check if the requested asset exists on the server
fs.exists(filePath, function (exists, err) {
  // If the asset does not exist, respond with a 404 Not Found
  if (!exists || !mimeTypes[ext]) {
    console.log('File does not exist: ' + pathName)
    res.writeHead(404, {'Content-Type': 'text/plain'})
    res.write('404 Not Found')
    res.end()
    return
  }
  // Otherwise, respond with a 200 OK status, 
  // and add the correct content-type header
  res.writeHead(200, {'Content-Type': mimeTypes[ext]})
  // Read file from the computer and stream it to the response
  const fileStream = fs.createReadStream(filePath)
  fileStream.pipe(res)
})

All the code is hosted on Glitch and you are free to remix the project if you wish.

https://glitch.com/edit/#!/node-http

Creating a HTTP server with Node.js frameworks

Node.js frameworks like Express, Koa.js and Hapi.js come with various useful middleware functions, in addition to a host of other handy features that save developers the trouble of writing themselves.

Personally, I feel that it’s good to learn the basics without frameworks first, just for understanding what goes on under the hood, then after that, go nuts with whatever framework you like.

Express has its own in-built middleware for serving static files, so the code required for doing the same thing as in native Node.js is much shorter.

const express = require('express')
const app = express()
// Serve static files out of the 'public' folder
app.use(express.static('public'))
// Serve the index.html when users access the 
// root directory using res.sendFile()
app.get('/', (req, res) => {
  res.sendFile(__dirname + '/public/index.html')
})
app.listen(5000)

Koa.js does not bundle any middleware within its core, so any middleware required has to be installed separately. The latest version of Koa.js leverages async functions in favour of callbacks. To serve static files, you can use the koa-static middleware.

const serve = require('koa-static')
const koa = require('koa')
const app = new koa()
// Serve static files out of the 'public' folder
// By default, koa-static will serve the index.html file on the root directory
app.use(serve(__dirname + '/public'))
app.listen(5000)

Hapi.js favours configuration, and revolves around configuring the server object. It utilises plugins for extending capabilities like routing, authentication and so on. To serve static files, we will need a plugin called inert.

const path = require('path')
const hapi = require('hapi')
const inert = require('inert')
// Routes can be configured on the server object
const server = new hapi.Server({
  port: 5000,
  routes: {
    files: {
      relativeTo: path.join(__dirname, 'public')
    }
  }
})
const init = async () => {
  // server.register() command adds the plugin to the application
  await server.register(inert)
  // inert adds a directory handler to 
  // specify a route for serving multiple files
  server.route({
    method: 'GET',
    path: '/{param*}',
    handler: {
      directory: {
        path: '.',
        redirectToSlash: true,
        index: true
      }
    }
  })
  await server.start()
}
init()

Each of these frameworks have their own pros and cons, and these will be more evident for larger applications rather than simply serving a single HTML page. The choice of framework will depend heavily on the actual requirements of the project you’re working on.

Wrapping up

If the network side of things has always been a black box to you, hopefully this article can serve as a helpful introduction to the protocol that powers the web. I also highly recommend reading the Node.js API documentation, which is very well-written and is a great help for anyone new to Node.js in general.

How to get started Internationalization in JavaScript with NodeJS

How to get started Internationalization in JavaScript with NodeJS

Tutorial showing how to use the Intl JS API in NodeJS (i18n). We'll install a module to unlock the Intl API languages for Node and test out RelativeTimeFormat to translate and localise relative times in JavaScript.

Tutorial showing how to use the Intl JS API in NodeJS (i18n). We'll install a module to unlock the Intl API languages for Node and test out RelativeTimeFormat to translate and localise relative times in JavaScript. I'll tell you how to get started with the built-in internationalization library in JS for Node 12 and higher. We'll change the locale to see how the translation works and test different BCP 47 language tags.

Internationalization is a difficult undertaking but using the Intl API is an easy way to get started, it's great to see this new API in the JS language and available for use. Soon, you'll be able to have confidence using it in the browser as modern browsers support the major Intl features. Have a look at the browser compatibility charts to see which browsers and versions of node are supported.

Use Intl.RelativeTimeFormat for language-sensitive relative time formatting.
#javascript #nodejs #webdevelopment

MDN Documentation:

https://developer.mozilla.org/en-US/d...

Full ICU NPM package:

https://www.npmjs.com/package/full-icu

JavaScript Tutorial: if-else Statement in JavaScript

JavaScript Tutorial: if-else Statement in JavaScript

This JavaScript tutorial is a step by step guide on JavaScript If Else Statements. Learn how to use If Else in javascript and also JavaScript If Else Statements. if-else Statement in JavaScript. JavaScript's conditional statements: if; if-else; nested-if; if-else-if. These statements allow you to control the flow of your program's execution based upon conditions known only during run time.

Decision Making in programming is similar to decision making in real life. In programming also we face some situations where we want a certain block of code to be executed when some condition is fulfilled.
A programming language uses control statements to control the flow of execution of the program based on certain conditions. These are used to cause the flow of execution to advance and branch based on changes to the state of a program.

JavaScript’s conditional statements:

  • if
  • if-else
  • nested-if
  • if-else-if

These statements allow you to control the flow of your program’s execution based upon conditions known only during run time.

  • if: if statement is the most simple decision making statement. It is used to decide whether a certain statement or block of statements will be executed or not i.e if a certain condition is true then a block of statement is executed otherwise not.
    Syntax:
if(condition) 
{
   // Statements to execute if
   // condition is true
}

Here, condition after evaluation will be either true or false. if statement accepts boolean values – if the value is true then it will execute the block of statements under it.
If we do not provide the curly braces ‘{‘ and ‘}’ after if( condition ) then by default if statement will consider the immediate one statement to be inside its block. For example,

if(condition)
   statement1;
   statement2;

// Here if the condition is true, if block 
// will consider only statement1 to be inside 
// its block.

Flow chart:

Example:

<script type = "text/javaScript"> 

// JavaScript program to illustrate If statement 

var i = 10; 

if (i > 15) 
document.write("10 is less than 15"); 

// This statement will be executed 
// as if considers one statement by default 
document.write("I am Not in if"); 

< /script> 

Output:

I am Not in if
  • if-else: The if statement alone tells us that if a condition is true it will execute a block of statements and if the condition is false it won’t. But what if we want to do something else if the condition is false. Here comes the else statement. We can use the else statement with if statement to execute a block of code when the condition is false.
    Syntax:
if (condition)
{
    // Executes this block if
    // condition is true
}
else
{
    // Executes this block if
    // condition is false
}


Example:

<script type = "text/javaScript"> 

// JavaScript program to illustrate If-else statement 

var i = 10; 

if (i < 15) 
document.write("10 is less than 15"); 
else
document.write("I am Not in if"); 

< /script> 

Output:

i is smaller than 15
  • nested-if A nested if is an if statement that is the target of another if or else. Nested if statements means an if statement inside an if statement. Yes, JavaScript allows us to nest if statements within if statements. i.e, we can place an if statement inside another if statement.
    Syntax:
if (condition1) 
{
   // Executes when condition1 is true
   if (condition2) 
   {
      // Executes when condition2 is true
   }
}

Example:

<script type = "text/javaScript"> 

// JavaScript program to illustrate nested-if statement 

var i = 10; 

if (i == 10) { 

// First if statement 
if (i < 15) 
	document.write("i is smaller than 15"); 

// Nested - if statement 
// Will only be executed if statement above 
// it is true 
if (i < 12) 
	document.write("i is smaller than 12 too"); 
else
	document.write("i is greater than 15"); 
} 
< /script> 

Output:

i is smaller than 15
i is smaller than 12 too
  • if-else-if ladder Here, a user can decide among multiple options.The if statements are executed from the top down. As soon as one of the conditions controlling the if is true, the statement associated with that if is executed, and the rest of the ladder is bypassed. If none of the conditions is true, then the final else statement will be executed.
if (condition)
    statement;
else if (condition)
    statement;
.
.
else
    statement;


Example:

<script type = "text/javaScript"> 
// JavaScript program to illustrate nested-if statement 

var i = 20; 

if (i == 10) 
document.wrte("i is 10"); 
else if (i == 15) 
document.wrte("i is 15"); 
else if (i == 20) 
document.wrte("i is 20"); 
else
document.wrte("i is not present"); 
< /script> 

Output:

i is 20

How to Retrieve full Profile of LinkedIn User using Javascript

How to Retrieve full Profile of LinkedIn User using Javascript

I am trying to retrieve the full profile (especially job history and educational qualifications) of a linkedin user via the Javascript (Fetch LinkedIn Data Using JavaScript)

Here we are fetching LinkedIn data like Username, Email and other fields using JavaScript SDK.

Here we have 2 workarounds.

  1. Configuration of linkedIn developer api
  2. Javascript Code to fetch records

Configuration of linkedIn developer api

In order to fetch records, first we need to create developer api in linkedin which will act as token/identity while fetching data from other linkedin accounts.

So to create api, navigate to https://linkedin.com/developer/apps and click on 'Create Application'.

After navigating, fill in details like name, description and other required fields and then submit.

As we submit, it will create Client ID and Client Secret shown below, which we will be using in our code while communicating to fetch records from other LinkedIn account.

Note: We need to provide localhost Url here under Oauth 2.0. I am using my localhost, but you can probably use other production URLs under Oauth 2.0 where your app is configured. It will make your api  consider the Url as trusted which fetching records.

Javascript Code to fetch records

For getting user details like first name, last name,User image can be written as,

<script type="text/javascript" src="https://platform.linkedin.com/in.js">  
    api_key: XXXXXXX //Client ID  
    onLoad: OnLinkedInFrameworkLoad //Method that will be called on page load  
    authorize: true  
</script>  
<script type="text/javascript">  
    function OnLinkedInFrameworkLoad() {  
        IN.Event.on(IN, "auth", OnLinkedInAuth);  
    }  
  
    function OnLinkedInAuth() {  
        IN.API.Profile("me").result(ShowProfileData);  
    }  
  
    function ShowProfileData(profiles) {  
        var member = profiles.values[0];  
        var id = member.id;  
        var firstName = member.firstName;  
        var lastName = member.lastName;  
        var photo = member.pictureUrl;  
        var headline = member.headline;  
        //use information captured above  
        var stringToBind = "<p>First Name: " + firstName + " <p/><p> Last Name: " + lastName + "<p/><p>User ID: " + id + " and Head Line Provided: " + headline + "<p/>"  
        document.getElementById('profiles').innerHTML = stringToBind;  
    }  
</script>    

Kindly note we need to include 'https://platform.linkedin.com/in.js' as src under script type as it will act on this Javascript SDK provided by Linkedin.

In the same way we can also fetch records of any organization with the companyid as keyword.

<head>  
    <script type="text/javascript" src="https://platform.linkedin.com/in.js">  
        api_key: XXXXXXX ////Client ID  
        onLoad: onLinkedInLoad  
        authorize: true  
    </script>  
</head>  
  
<body>  
    <div id="displayUpdates"></div>  
    <script type="text/javascript">  
        function onLinkedInLoad() {  
            IN.Event.on(IN, "auth", onLinkedInAuth);  
            console.log("On auth");  
        }  
  
        function onLinkedInAuth() {  
            var cpnyID = XXXXX; //the Company ID for which we want updates  
            IN.API.Raw("/companies/" + cpnyID + "/updates?event-type=status-update&start=0&count=10&format=json").result(displayCompanyUpdates);  
            console.log("After auth");  
        }  
  
        function displayCompanyUpdates(result) {  
            var div = document.getElementById("displayUpdates");  
            var el = "<ul>";  
            var resValues = result.values;  
            for (var i in resValues) {  
                var share = resValues[i].updateContent.companyStatusUpdate.share;  
                var isContent = share.content;  
                var isTitled = isContent,  
                    isLinked = isContent,  
                    isDescription = isContent,  
                    isThumbnail = isContent,  
                    isComment = isContent;  
                if (isTitled) {  
                    var title = isContent.title;  
                } else {  
                    var title = "News headline";  
                }  
                var comment = share.comment;  
                if (isLinked) {  
                    var link = isContent.shortenedUrl;  
                } else {  
                    var link = "#";  
                }  
                if (isDescription) {  
                    var description = isContent.description;  
                } else {  
                    var description = "No description";  
                }  
                /* 
                if (isThumbnailz) { 
                var thumbnailUrl = isContent.thumbnailUrl; 
                } else { 
                var thumbnailUrl = "http://placehold.it/60x60"; 
                } 
                */  
                if (share) {  
                    var content = "<a target='_blank' href=" + link + ">" + comment + "</a><br>";  
                    //el += "<li><img src='" + thumbnailUrl + "' alt=''>" + content + "</li>";  
                    el += "<li><div>" + content + "</div></li>";  
                }  
                console.log(share);  
            }  
            el += "</ul>";  
            document.getElementById("displayUpdates").innerHTML = el;  
        }  
    </script>  
</body>  

We can get multiple metadata while fetching records for any any organization. We can get company updates as shown below.

Conclusion

We can also fetch any company specific data like company job updates/post, total likes, comments, and number of views along with a lot of metadata we can fetch which I have shown below.

Thank you for reading !