Share
Explore

Building Web Sites with Microservices

Background and theory of microservices:
Considering the course learning outcome:
Develop web applications that follow a microservice architecture and leverage both internal and external APIs
Develop a simple REST API using express.js that supports the basic HTTP Verbs: ​GET, POST, PUT, and DELETE requests
3.3 Use industry standard API testing tool(s) to test the functionality of various API endpoints:
PostMan
Lab to make our own Postman : using Node.js

Lab Part 2: Building the Backend Data Store with MONGO DB:

Learning Outcomes:

How to Develop web applications that follow a microservice architecture and leverage both internal and external APIs:

Lab code examples using Node.js NPMJS packages

Lab Learning Workbook: Microservices Architecture Web Development

Part 1: Introduction

In this lab, we will cover the fundamentals of building a microservice-based architecture using Express.js, a popular Node.js framework. We will build a simple REST API, use it internally, and learn to leverage external APIs.
Activity A: A Simple Example of Nodejs Application Development
Step 1: npm init Makes package.json
Let’s setup a simple Express JS Server:
Step 1: install from
Express package

Part 2: Setting Up

Install Node.js and npm (Node Package Manager) if you have not done so:
Once Node.js is installed, npm will also be installed along with it.
Now, create a new directory for your project:

mkdir microservice-lab
cd microservice-lab

Initialize your Node.js application:
bashCopy code
npm init -y

Install Express:
bashCopy code
npm install express

Part 3: Building a Simple REST API with Express.js

We will start by creating a simple book management system.
Create a new file called server.js and include the following code:
const express = require('express');
const app = express();
app.use(express.json());

let books = [];

app.get('/books', (req, res) => {
res.json(books);
});

app.post('/books', (req, res) => {
const book = req.body;
books.push(book);
res.status(201).send();
});

app.put('/books/:id', (req, res) => {
const id = req.params.id;
const book = req.body;

let index = books.findIndex((book) => book.id === id);
if (index !== -1) {
books[index] = book;
res.send();
} else {
res.status(404).send();
}
});

app.delete('/books/:id', (req, res) => {
const id = req.params.id;

let index = books.findIndex((book) => book.id === id);
if (index !== -1) {
books.splice(index, 1);
res.send();
} else {
res.status(404).send();
}
});

app.listen(3000, () => console.log('Server running on port 3000'));

This server will start a server at localhost on port 3000. We have routes to GET, POST, PUT, and DELETE books.Nodemon is a utility that will monitor for any changes in your source code and automatically restart your server. Perfect for development. Here's how you can get it running with your server.
Nodemon will watch the files in the directory in which nodemon was started, and if any files change,
info

Nodemon is a utility that will monitor for any changes in your source code and automatically restart your server. Perfect for development. Here's how you can get it running with your server.

First, you'll need to install nodemon. If you haven't installed it yet, you can do so by using npm (node package manager):
bashCopy code
npm install -g nodemon

This command installs nodemon globally so you can use it in any Node.js project.
Then, instead of starting your server with node server1.js, you can start it with nodemon server1.js.
bashCopy code
nodemon server1.js

Nodemon will watch the files in the directory in which nodemon was started, and if any files change, nodemon will automatically restart your node application.
For using nodemon as a development dependency and adding a start script in your package.json:
Install nodemon as a development dependency:
bashCopy code
npm install --save-dev nodemon

Open package.json in your root directory and add a start script:
jsonCopy code
"scripts": {
"start": "nodemon server1.js"
}

Now you can start your server with the following npm command:
bashCopy code
npm start

Now, every time you save your file, nodemon will automatically restart your server, thus you won't need to stop and restart it manually every time you make a change.

megaphone

Write an HTML page with forms to interact with and allow user interaction with each of the routes to add and read the details of book objects

A basic HTML form that can interact with our Express.js server using JavaScript's built-in fetch function.
In this example, we'll only cover creating a form to add a book (POST /books) and display all books (GET /books).
<!DOCTYPE html>
<html>
<head>
<title>Book Management System</title>
<script>
// Function to add a new book
async function addBook() {
const title = document.getElementById('title').value;
const author = document.getElementById('author').value;
const id = document.getElementById('id').value;

const response = await fetch('http://localhost:3001/books', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
id,
title,
author
})
});

if (response.status === 201) {
document.getElementById('message').textContent = 'Book added successfully!';
loadBooks();
} else {
document.getElementById('message').textContent = 'Error occurred while adding the book.';
}
}

// Function to display all books
async function loadBooks() {
const response = await fetch('http://localhost:3001/books');
const books = await response.json();

const booksContainer = document.getElementById('books');
booksContainer.innerHTML = '';

books.forEach(book => {
const bookItem = document.createElement('div');
bookItem.textContent = `ID: ${book.id}, Title: ${book.title}, Author: ${book.author}`;
booksContainer.appendChild(bookItem);
});
}

window.onload = function() {
loadBooks();
};
</script>
</head>
<body>
<h1>Book Management System</h1>

<form onsubmit="event.preventDefault(); addBook();">
<label for="id">Book ID:</label><br>
<input type="text" id="id" name="id"><br>
<label for="title">Book Title:</label><br>
<input type="text" id="title" name="title"><br>
<label for="author">Author:</label><br>
<input type="text" id="author" name="author"><br>
<input type="submit" value="Add Book">
</form>
<p id="message"></p>

<h2>All Books</h2>
<div id="books"></div>
</body>
</html>

This HTML page contains a form that takes in a book ID, title, and author, and sends a POST request to the /books endpoint to add a new book. It also fetches and displays all books from the server when the page loads and after a new book is added.
Please remember to replace http://localhost:3001/books with the actual address of your books microservice if it's different.
Also, due to the security measures of the browser, you might need to enable CORS on your Express.js server or use a tool like cors-anywhere. CORS (Cross-Origin Resource Sharing) is a security feature that can restrict which domains are allowed to make requests to your server. It is beyond the scope of this lab but you can refer to for more information.
When you tried to call index.html you got an error message: Cannot GET /index.html
Here is how to fix it:
megaphone

How to fix problem Cannot GET /index.html

The error "Cannot GET /index.html" usually happens when you are trying to serve a static file, in this case, index.html, but your Express application does not have a route handler for it.
You can resolve this issue by telling Express to serve static files from a certain directory, usually named public or static. In your case, let's assume you want to serve index.html from a directory called public.
Here's how you can set it up:
Create a directory called public in your project root directory:
bashCopy code
mkdir public

Move or create the index.html file inside the public directory.
Then in your Express.js application, use the express.static middleware function to serve the static files:
const express = require('express');
const path = require('path');
const app = express();

app.use(express.json());

// Serve static files from the "public" directory
app.use(express.static(path.join(__dirname, 'public')));

// rest of your code...

The express.static function tells Express to serve static files from the directory that you provide as its argument. __dirname is a Node.js global variable that gets the directory of the currently running file, and path.join is used to create a path string that works across different operating systems.
Now, you should be able to visit http://localhost:3001/index.html in your web browser and see your index.html file being served. If index.html is directly under your public directory, you can simply use http://localhost:3001 to access it, since index.html is typically recognized as the default file to serve when accessing the root path of a directory.

megaphone

What node.js package must I install to use static middleware to serve images and html files

The Node.js package you need is express, which is a fast, unopinionated, and minimalist web framework for Node.js.
The static middleware handler is built into express.
The Express package comes with a middleware for serving static files, so you don't need to install an additional package.
If you haven't installed it yet, you can install express using npm (Node Package Manager) by running:
npm install express

Once you have express installed, you can use the static middleware to serve static files such as images, CSS files, and JavaScript files. Here's an example of how you can use it to serve files from a directory named public:
const express = require('express');
const app = express();

app.use(express.static('public'));

app.listen(3000, () => {
console.log('Server is listening on port 3000');
});

In this example, any files in the public directory are served by Express. For instance, if you have a file index.html in the public directory, you can access it at http://localhost:3000/index.html. Similarly, if you have an image file image.jpg in the public directory, you can access it at http://localhost:3000/image.jpg.
By default, Express will serve the index.html file in the root of the public directory when you access http://localhost:3000/. You can place other static files like CSS, JavaScript, images and other HTML files in the public directory or its subdirectories and they will be served on their respective paths.

How to specify a charset meta element
A charset (character set) meta element specifies the character encoding for the HTML document. This can help ensure that the content of your webpage is displayed correctly across different browsers and platforms.
To specify a charset meta element, you will need to add a <meta> tag in the <head> section of your HTML file. Here's the basic syntax:
htmlCopy code
<meta charset="UTF-8">

This specifies that the character encoding for the document is UTF-8, which includes almost all characters from all languages and is the most common character encoding.
Here's how you can include it in your HTML file:
htmlCopy code
<!DOCTYPE html>
<html>
<head>
<title>Book Management System</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="/styles.css">
<!-- rest of your head content -->
</head>
<!-- rest of your HTML content -->
</html>

In this HTML snippet, the <meta charset="UTF-8"> line indicates that the document will use UTF-8 encoding. It's generally a good idea to specify this as close to the top of your <head> section as possible, so that the browser knows what character set to use when parsing the rest of your HTML document.

<!DOCTYPE html> how to specify a viewport meta element
To specify a viewport meta element, you will need to add a <meta> tag in the <head> section of your HTML file. The viewport meta tag helps with responsive design by controlling the width and scaling of the page on different devices.
Here is the basic syntax of a viewport meta tag:
htmlCopy code
<meta name="viewport" content="width=device-width, initial-scale=1">

Let's break down what this does:
width=device-width : This means that the browser will (in CSS pixels) render the width of the page at the width of its own screen. So if that screen is 320px wide, the browser window will be 320px wide, rather than way zoomed out and showing 980px (which used to be the "default" for all mobile browsers).
initial-scale=1 : This establishes a 1:1 relationship between CSS pixels and device-independent pixels (DIPs), which defines the ratio between the CSS pixels and the physical pixels on the device. This means the web page uses the same proportions it does in the desktop browser, so nothing will be smaller, and users won’t need to scroll horizontally.
So your HTML with a viewport meta element might look something like this:
<!DOCTYPE html>
<html>
<head>
<title>Book Management System</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="/styles.css">
<!-- rest of your head content -->
</head>
<!-- rest of your HTML content -->
</html>

This will make your webpage scale correctly on various devices like desktops, tablets, and smartphones.
How that you have that going, try adding some images and css.

Now add some images and CSS:
megaphone

Add a CSS file using static middleware to make index.html look more dynamic

Let's say you have a CSS file named styles.css in the public directory.
Here is a basic example of how you can style the index.html:
cssCopy code
/* styles.css */
body {
background-color: #f9f9f9;
font-family: Arial, sans-serif;
}

h1 {
color: #333;
Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
CtrlP
) instead.