Server-side web programming What is a Web-Server A web-based system is a software system where a client accesses a web application hosted on the internet via the HTTP protocol. Generally, the client is a web browser with which a user interacts. The web application is hosted on a server, which is another computer connected to the internet. The internet is the largest network of computers. This is an abstract representation of a web-based system. Figure 1 - Abstract representation of a web-based system What is a Web Server? A web server is a dedicated computer responsible for running websites sitting out on those computers somewhere on the Internet. A web server displays website content through storing, processing, and delivering web pages to users. When you search for a web page on the browser, the request goes to the server somewhere on the internet. There will be a root directory. Inside the root directory, the resources such as images and videos are stored. Also, the HTML files are stored inside the directory. For example, the page you will receive when logging in to Facebook is also stored on a Facebook server similar to as shown in figure. It's important to know that where is your web server is located. Figure 2 - Retrieving webpages from web server Where is My Web Server? When you try to access a web site, you don't really need to know where the web server is located. The web server may be located in another city or country, but all you need to do is type the URL of the web site you want to access in a web browser. Then the web browser will send this information to the internet and find the web server. Once the web server is located, it will request the specific web page from the web server program running in the server. The web server program will process your request and send the resulting web page to your browser. It is the responsibility of your browser to format and display the web page to you. To understand the behaviour of the clients and the servers it's important to know about the client-server architecture. Client-Server Architecture Client-server architecture is an architecture of a computer network in which many clients (remote processors) request and receive service from a centralized server (host computer). Client computers provide an interface to allow a computer user to request services of the server and to display the results the server returns. Figure 3 - Client-server architecture The web is a collection of files that reside on computers, called Web servers, that are located all over the world and are connected to each other through the Internet. When you use your Internet connection to become part of the Web, your computer becomes a Web client in a worldwide client/server network. A Web browser is the software that you run on your computer to make it work as a web client. Web Server Uses Web servers often come as part of a larger package of internet- and intranet-related programs that are used for: o Sending and receiving emails. o Downloading requests for File Transfer Protocol (FTP) files. o Building and publishing web pages. o Support server-side scripting. Web Server Software These are some web server software in today's market. o Apache HTTP Server is developed by the Apache Software Foundation. This is an opensource software and can be installed on almost all operating systems including Linux, UNIX, Windows, FreeBSD, Mac OS X and more. o Microsoft Internet Information Services (IIS). Developed by Microsoft for Microsoft platforms; it is not open sourced, but widely used. o Nginx Web Server is a popular open-source web server for administrators. It can handle many concurrent sessions. o Sun Java System Web Server is a free web server from Sun Microsystems that can run on Windows, Linux and Unix. It is well-equipped to handle medium to large websites. o Lighttpd is a free web server that comes with the FreeBSD operating system. It is seen as fast and secure, while consuming less CPU power. Activity o List down the uses of client-server architecture. o Compare and contrast different types of web server software. Resources - 6/10 What is a web server? Static Files Vs Dynamic Files Overview A web application is composed of several web pages. A web page includes multimedia content requested by the client, such as a home page, user profile page, contact page, etc. On the client-side, these web pages do not have much difference. However, these web pages are categorized into two types depending on how the server generates them. The two types are static and dynamic files. What is a Static file? The static web page is delivered exactly as stored, as web content in the web server's file system. It displays the same content for all users. A file is stored in the file directory at the server. The first web page ever published is World Wide Web which went live on August 6, 1991. It was dedicated to information on the World Wide Web project and was made by Tim Berners-Lee, who is known as the father of the World Wide Web. This website contains only static content. How to retrieve a Static file? When the user requests the “contact us” web page, the server retrieves the contactus.html file from the database. For static web pages when a server receives a request for a web page, then the server sends the response to the client without doing any additional process and these web pages are seen through a web browser. In this process, both the web server and the web browser use Hypertext Transfer Protocol (HTTP) for sending requests and responses. Figure 1 - How to create a static file What is a Dynamic file? The Dynamic file's content changes depending on the client who made the request or depending on some other factors change over time or likewise. To achieve this, the server has to process the content or even generate it on the fly from a database. A dynamic web page is generated by a web application, usually driven by server-side software. The most common example are Facebook and Google. How to retrieve a Dynamic file? When the user needs to access the “my account” web page, the user has to type the URL of the website in the web browser. Then the web browser sends an HTTP request to the webserver. In a dynamic web page, the server has to retrieve user-specific information from the database. A dynamic page displays different content for different users while retaining the same layout and design. The database allows the page creator to separate the web site’s design from the content to be displayed to users. Once they upload content into the database, it is retrieved by the website in response to a user request. Figure 2 - How to create a dynamic file Table 1 - The difference between static webpages and dynamic webpages Table 2 - The difference between static websites and dynamic websites Activity o List five different types of web-based applications that you use. o Identify the web pages that are dynamic files or static files in those web-based applications. o If a web page is a dynamic file, then identify which data items are dynamic. (e.g., Facebook is a social networking web application. The profile page, news feed page are dynamic files, help center pages are static files) Resources - Static vs. dynamic content 6/10 Server-side web programming Overview Python was used by many industries for server-side programming and development. Although many developers are moving away from python language for server-side programming, many modern server-side development technologies are based on the core concept of Python. Since you experience the Python language through Course 1 and Course 3, it is an advantage to understand the basic core features of a server by developing a simple server with python. When you are experimenting with the developed server with your browser you write the port number along with the URL. If you already have something running on port 8000, you can choose another port by running the server command followed by an alternative port number, e.g. python3 -m http.server 7800 (Python 3.x) or python -m SimpleHTTPServer 7800 (Python 2.x). You can then access your content at localhost:7800. BaseHTTPRequestHandler We used the BaseHTTPRequestHandler class during the session. By using that we could easily implement our server. Not only path and wfile but there are also many instance variables available with this class. By using them we can include more functionalities to our server as well. Instance Variable Purpose wfile Contains the output stream for writing a response back to the user's device. rfile To read from the start of the optional input data. headers Holds an instance of the class specified by the MessageClass class variable. This instance parses and manages the headers in the HTTP request. path Contains the request type. It can be a GET request or a post request. server Contains the server instance. Boolean that should be set before handle_one_request() returns, indicating close_connection if another request may be expected, or if the connection should be shut down. Activity o List down the advantages and disadvantages of the Python programming language for server-side development Resources Documentation by Python - socketserver — A framework for network servers Documentation by Python - http.server — HTTP servers Learn more about Python - Course 01 Learn more about Python - Course 03 Demo Now we can code our python server. Open the myServer.py source file. Previously we used the HTTPServer module to enable the inbuilt server. We can use classes and methods in the HTTPServer module to create our own server. From the http.server we are importing two classes. We have to define the server address. To do so we use the HTTPServer class. To show web pages and to handle user inputs we need to import the BaseHTTPRequestHandler class as well. Now we are going to create a class to hold our server. In this class, we have to give outputs according to user inputs. So we have to use methods in the BaseHTTPRequestHandler class. That is the reason for including that class name inside brackets in our new class declaration. We are using the def do_GET (self): method from the BaseHTTPRequestHandler class so we can handle user requests. Follow my lead and let's complete the code. self.path will check for possible files that can be displayed in the browser. We can set the path for our index HTML page as well. In here - By using file_to_open = open(self.path[1:]).read() – We can read (display) the content which is inside the file which is going to open by the user. self.send_response(200) – This line is to notify that the user has accessed the web page successfully. Now we successfully accessed the files through our server. Next, we have to read the files and display the content on the screen. To do that we have to use self.wfile.write(bytes(file_to_open, 'utf-8')). self.end_headers() – will end the accessing process At the final stage, we have to create an HTTP variable by calling the HTTPServer class to host our servers. Let's define that variable as httpd. Let's set the server address and pass this data to our MyServer class.Localhost is our computer and 8000 is the port that is considered as our server address. Now is the time to run our server and see our index HTML page. Open the browser and type the server address. The server address is http://localhost:8000 10/10 browser-server communication - URLs Overview The server and browser communicate through several steps. Throughout the initial phase,delivering the website to theuser is done mainly through the URL.. What is the difference between domain name and URL? The major difference between both is that the URL is a complete address used to find a particular web page while the domain is the name of the website. URL tells about the method through which information should be exchanged, and the path after reaching that website. Whereas the domain name is part of a URL. Let’s compare these two examples. o https://www.google.com o https://open.uom.lk The part that follows immediately after the last (visible) "dot" symbol is known as the top-level domain. Short-form is TLD. TLDs can be classified into two categories: generic TLDs and country-specific TLDs. Generic Top-Level Domains (gTLD) Some of the most popular types of TDLs are ".edu" for educational sites and ."com" for commercial sites. These types of TLDs are available for registration. Country-Code Top-Level Domains (ccTLD) Every ccTLD recognizes a specific country and is generally two letters long. For example, the ccTLD for Sri Lanka is ".lk". Some of the TLDs and their original explanations are as follows: o .com — Commercial businesses. o .org — Organizations (generally charitable). o .net — Network organizations. o .gov —government agencies. o .mil — Military. o .edu — educational facilities, like universities. o .lk – Sri Lanka o .ca — Canada. o .au — Australia. To match the correct IP address with the corresponding URL, DNS provides enormous support. The DNS Hierarchy The above illustration shows the complete and complex DNS procedure when a user is trying to reach google.com. Let’s break it down. We know at the start it checks in the computer for a match and it is considered the local DNS. Next, it goes to the root DNS server. These servers contain the global list of the top-level domains (TLD). Then it identifies the .com top-level domain. As the next step, it checks in the TLD DNS server. According to our figure, it is the com DNS server. The TLD DNS server points the request towards the correct authoritative DNS server. Last, the user’s request checks the IP address in the authoritative DNS server. The Authoritative DNS server is the google.com DNS server which holds a broad range of IP address information Activity o Two versions of the Internet Protocol (IP Address) are in common use on the Internet today. They are IPv4 and IPv6. Search and describe the difference between them. Resources Learn more about the DNS Hierarchy. Learn more about DNS servers 10/10 browser-server communication - HTTP Overview The server and browser communication involves several rules. These rules are known as protocols. Protocols provide us with a medium and set of rules to establish communication between different devices for the exchange of data and other services. Protocols also make sure the message gets to its destination properly, in its entirety, and without distortion. TCP/IP Protocol TCP Stands for Transmission Control Protocol and IP is for Internet Protocol, TCP and Ip come together so developers consider them as TCP/IP. This is the standard communication protocol suite used for client-server communication over a network. TCP is the transport protocol that manages the exchange of data between the user’s device and server. IP is the protocol used for device addresses within the network or internet. During the session, we discussed the HTTP protocol. But if we take our moodle as an example it has something else. HTTPS HTTPS stands for Hypertext Transfer Protocol Secure. This is an extended version of HTTP and because of that, some developers state this as HTTP over SSL. SSL stands for Secure Sockets Layer. SSL stores authentication data, such as certificates and private keys. When we type https:// in your address bar in front of the domain, it tells the browser to connect over HTTPS. Generally, sites running over HTTPS will have a redirect in place so even if we type in http:// it will redirect to deliver over a secured connection. HTTPS also uses TCP to establish communication. If we use HTTPS, the data will be encrypted before sending and receiving. You will learn more about server-side security under topic 5, including a deep look into how HTTPS works. Let’s see this small conversation between “Sama” and “Amara”. Amara wants to get some information from Sama. First Amara has to open a conversation or else a connection with Sama. So he says “Hi”. After hearing that Sama replies “Hi”. Now the conversation or the connection is opened between Amara and Sama. Amara wants to know about Sama's location. So he asks where are you from? As the response Sama says I am from Moratuwa. In this example, Amara is the Client and Sama is the Server. Before requesting information Amara had to open a connection with Sama. Keep that in mind and let’s move forward. Like in the previous example TCP connection should be opened between the browser and the server. TCP stands for Transmission Control Protocol. After establishing the connection between server and browser now we can get and give information to the server. This giving and receiving communication process happens through the HTTP protocol. There are two main types of requests. Here you may see an HTTP GET request. Let’s discuss HTTP requests. In this example, you can see that the user wants to visit the “open.uom” home page. According to the user’s request, the browser sends an HTTP GET request. Index.html means the home page. Then the server responds to the requests by sending the index.html document. GET requests are sent when a URL is submitted in the browser location bar or a user clicks a link. GET requests can be bookmarked. It means we can save it in the browser. We can use GET requests and responses for read-only operations. That means we cannot change anything.In view operations, search functions, sort functions, and filter functions we use GET requests and responses. An HTTP POST request is made when you submit a web form containing information to be saved on the server.According to the example, Amal is trying to log into his open uom account. So he is sending his username and password along with the request. If he sends matching credentials the server will mark it as a successful login attempt and issues a token as the response. POST is for POSTING information to the server. When we are changing our username and password, POST requests are made. When we are downloading stuff POST responses will happen. POST requests cannot be bookmarked. And most of the POST operations are based on writing content. Create update delete data functions are based on POST requests. Another important fact is that data will be changed after POST requests. Activity o Compare the advantages and disadvantages of both HTTP and HTTPS protocols. Resources Learn more about TCP/IP Learn more about HTTPs 10/10 Client-side versus Server-side Application Development Overview Although we divided the client-side and server-side web development the final web application functions as one unit. To function as one unit we have to link the front end and back end and host the application on the server. The linking process is managed by the API and API endpoints. We discuss the role of API and API endpoints but we did not discuss the hosting process. Web Hosting When we are creating the front end of a web application we have to create HTML pages, CSS scripts, images and videos, and many more resources. When we are developing the back-end part of the application we have to create a database, and need to develop the code to send and receive data from the database to the front end. We have our server as well. In the final stage, we have to link all those components and give the output to the user as one complete system. Web hosting is the process of publishing our web application on the World Wide Web using a server space so users shall be able to visit the website using the internet. Furthermore we can create email accounts and integrate security at the hosting stage. Different types of web hosting There are few major types of web hosting techniques. We can host our website on a server that contains multiple websites. All Shared hosting websites share the same server resources such as Random Access Memory (RAM) and Central Processing Unit (CPU) Sometimes web applications need more space on the server. Due to this Virtual private issue shared hosting has to be upgraded. With a virtual private server, our server (VPS) website will still be sharing a single server with other websites. However, the hosting number of websites we will be sharing it with is significantly lower. The main server is split into multiple editable virtual servers. Dedicated hosting The server is exclusively for our website and our website is the only one stored on it. We can get maximum benefits with this technique. In simple terms, a Cloud means many computers with server functionalities working together, running applications using combined computing resources. The resources that are being used are spread across several Cloud Hosting servers, reducing the chance of any downtime due to a server malfunction. This can be identified as a new trend. Cloud-based hosting is scalable, meaning our website can grow over time, using as many resources as it requires. In addition to these, there are other several technologies such as WordPress hosting and reseller hosting. Client-Server model If we take the “open uom” platform as an example we can visit there by using our laptop computers, desktop computers, smartphones, and tablets. Also, there are users from different locations as well.Therefore, the “open uom” server has to provide information and resources like video content and lecture slides to many users in different locations. So this arrangement is known as the Client-Server Model. The Client-server model describes how a server provides resources and services to one or more clients. Examples of servers include web servers, mail servers, and file servers. Each of these servers provides resources to client devices, such as desktop computers, laptops, tablets, and smartphones. Client-side In web application development, we refer to the end-user and the device as the client. In web development, 'client-side' refers to everything in a web application that is displayed or takes place on the end user’s device. This includes what the user sees, such as text, images, and the rest of the UI. Also, any actions that an application performs within the user's browser. In web application development, the client is the browser or what we called as the user agent. The developed client-side code is rendered by the browser’s rendering engines and displayed to the user on the browser window. Client-side development is a type of development that involves programs that run on a client. So, client-side developers focus on creating the part of a website that the user can interact with. Sometimes, client-side development is also referred to as front-end development, as it focuses on the "front" part of an application that users can see. These are some major client-side development examples. Creating website layouts Designing user interfaces Adding form validation Adding visual elements like colours and fonts You are familiar with HTML, CSS, and JavaScript. These are a few major languages used to develop the client-side of the application. If you want to revise your memory you can go through courses 2 and 4 again Server-side Now we are familiar with the client-side. Let’s discuss the server-side. We cannot execute everything on the client device. Examples: interacting with databases, user authentication, rendering dynamic web pages. These processes have to be executed on the server. Therefore 'server side' means everything that happens on the server. One major difference between client-side and server-side development is where code runs. In client-side development, the code runs on the client or user's device. However, in server-side development, the code runs through a server. This is why client-side development is also called a front end and server-side development is also called back end development. Server-side development is a type of development that involves programs that run on a server. Server-side developers focus on behind-the-scenes development, and server-side development is also referred to as "back-end" development. This type of programming is important because web browsers, or clients, interact with web servers to retrieve information. Some major server-side development tasks are, 1. Coding dynamic websites 2. Developing and hosting web applications 3. Connecting websites to databases API During course 4 you learned about APIs. Let's discuss the purpose of API during client-side and server-side development. The client uses an API provided by the webserver to send requests to access the web server resources and functionalities. The server responds to these API requests with relevant information and services. The server side that receives the API requests and provides the requested information, or resources, is the API endpoint. We can simply say endpoints are the locations of the resources, and the API uses endpoint URLs to retrieve the requested resources. Let’s discuss this further using this example. The user wants to download an image file from google images. Therefore the user makes a GET request. So the API endpoint will make an internal request according to the server location which contains the image file. An internal response will come from the server through the API endpoint. In the end, the user gets the image file as a downloadable link. This process helps developers to connect server-side programs with client-side programs in an efficient way. Activity o List down the advantages and disadvantages of using dedicated hosting over shared hosting. Resources Learn more about web hosting Learn more about web hosting techniques 10/10 Building an HTTP server with Node JS and Express-Installing Node and Express Overview In this module we will be looking at setting a server with NodeJS similar to what we did with python in one of the previous modules. Installing Node and Express In the first section of this module we will look at how to set up Node and Express in our own computers. Here you will see Node and Express used interchangeably this is because in the industry too we use these two terms interchangeably. So whenever you see Node and NodeJS or Express or ExpressJS please be mindful that they are talking about the same term. Installing NodeJS NodeJS is a runtime which supports the writing of JavaScript code outside of the browser and on any computer. To install NodeJS you can follow the following step. 1. Go to the official website for NodeJS https://nodejs.org/ 2. Click on the Downloads menu on the top. 3. Select LTS and select the relevant OS that you use 4. Once downloaded run the installer 5. After installation verify that the installation ran properly by running the command node -v in a command prompt (windows) or terminal (macos/linux) An alternate method to install NodeJS (Optional) The NodeJS platform releases upgrades quite frequently. So having an easier way to upgrade nodejs will be important. Node Version Manager is one such convenient tool. MacOS or Linux : https://github.com/nvm-sh/nvm Windows : https://github.com/coreybutler/nvm-windows Installation instructions are available on the github page. Once you have this tool installed. Installing the latest version is as easy as running the command nvm install --lts. (For the exact commands to be run for each version above, please refer the documentation) What is NPM? NPM is a package manager for NodeJS. This is where an open source project writes code and hosts it in a public place so that others can use that code for their own projects. Please read up on the following link to understand more about NPM packages and modules. More Info : https://docs.npmjs.com/about-packages-and-modules Express is one such open source project built by a community of developers and shared with the entire world via the NPM repository. You can also host your own project on NPM as long as the code is Open source. More Info : https://docs.npmjs.com/about-public-packages Examples of NPM packages and their hosted pages on NPM Express (Looked at in next module) : https://www.npmjs.com/package/express Ascii Art Generator (Used in practical) : https://www.npmjs.com/package/ascii-text-generator Runnable Code Samples Below you can play around with all the code examples provided in this lecture. Demo Let's try out our first lines of code with Node js, open one of your favorite IDs and follow along with me. It will be easier for you to follow me with the same ID that I am using VS code, but you can use your favorite text editor. Let's first try to lock the text Hello World using Node js. Simply add in the following code. And type in the following command and press enter. Even though we will be looking deeper into Express days, it will be interesting to explore how to set up a server without using web framework. Node js already contains an inbuilt module called HTTP, which makes it easy to set up as the server. Let's move to the command prompt for small demo. At the mentioned code in the slide to the J's file, run the code using the given command. Now tries to bring the relevant URL on a browser. You can see that HelloWorld is visible on your browser. As you can see, it is quite simple to set up a server. But we need something more easy to use to develop modern complex back end web code. This is where ExpressJS comes in, which is basically a wrapper around the HTTP module. Before we dive into Express, you need to be familiar with the package manager NPM. NPM or node package manager is an archive of modules of code that can be simply installed using a few commands. Let's create an NPM project and then use an existing library from the NPM repository to do something cool. For this part, I'll be using an interesting library which generates a schema based text messages called ASCII text generator. First, create a directory for your project so that you can have the files related to the project contained inside this folder. Next, let's do a simple Google search for how to create an NPM project. Min scan into the results always go into official docs minimum possible at times, though, some love may be more read differently to. But the most accurate information most accurate and up to date information can only be found in the official docs. This is the option that I will be choosing. First, let's go into the relevant folder now let's paste in the command that we copied. So you can see when we use the dash Y parameter, the object will be created with a set of default values. This is enough for us for now. If you go into the package. Jason, you can see the structure of the project. Now, let's take a look at the AES key code generator library that I talked about, just Google the library. And here you will see that library and its user manual displayed in the NPM official repository. And the step you need to take to install beloved command is shown here. we can just copy it and then paste it here. As you can see, when you install the package, there will be two changes to the directory that will be visible at a glance. And that is the creation of the node modules folder. And this package-lock.JSON you can ignore this package dot JSON. For now, it is not that important. but the node_modules folder if you will go inside, you will see that there is a folder with the name ASCII text generator, the module install, creator. And inside it, we have all all the source code related to the ASCII text generator. library loaded here. So this is the code that we'll be using as a third party library to do a small demo right now. Now with the package installed, let's create a source file for us to run the code. In this file, let's try to add some code related to this library, which we can take from the official page of that library. If you look at this code, this is the universal syntax to require a code into our own code. So if you're using a third-party module, and you are to use that bit of source code in your code, this is the syntax that we use require and the name of the library and we import the whole library into a variable. Next, we'll look at the repository page to see whether there is some other code that we can use here to look at some changes . so as you can see, we are using the important library and we are going to call it with some input Tex. Let's also try and let's change it to node Express beginner Laavanjan. Now lets change this parameter to something that looks cool. Yes, as you can see, the ASCII generator sends out a beautiful ASCII representation of the text that you get. Building upon the knowledge so far, we can look at how to set up the ExpressJS web framework. You can follow along with me as I go through this demo in my code editor. Let's set up a brand new directory and create an NPN project like before. Like the ASCII library Express is also a library that is available on the NPM repository. Similarly, you had to just Google to find out how to install this . library then go to the official NPM site and use the command provided to install the library in your project directory. Let's now require the Express code into our code file as before. Next, let's initialize an instance of the Express court. now we define a simple web browser for our web server. This just means that when you go to the web address with a forward slash Hello, we will send a response as HelloWorld. Now we start the web server using the app dot listen to the command. As you can see, this code is a bit more intuitive than using the native HTTP library. 10/10 Building apps with NodeJS/Express Overview After setting up nodejs and express successfully in the previous module, we are now going to dive deep into the concepts surrounding Express and web application frameworks. Understanding Runtime Environments In relation to progamming language a runtime environment ( referred to as programming environment for simplicity ) is a layer between the operating system and the programming language which utilises underlying operating system calls. Simply it creates a layer where we are able to write instructions to an operating system using a given programming language. Some examples include. o Python3 or Python2 Interpreter (Language - Python) o JRE[Java Runtime Environment] (Language - Java) o PHP 7 Interpreter - (Language - PHP) o NodeJS interpreter - (Language - JavaScript) NodeJS therefore allows us to write JavaScript code that a typical computer/server node might understand. Optional - What is an interpreted language. An interpreted language is a programming language which are generally interpreted, without compiling a program into machine instructions. It is one where the instructions are not directly executed by the target machine, but instead read and executed by some other program. Source - https://www.geeksforgeeks.org/difference-between-compiled-and-interpreted-language/ The evolving role of JavaScript in web development For many years JavScript's role in web development was confined to the client side as a simple scripting language that provided some utility to make web pages interactive. Next with the advent of NodeJS and software like angular and React, javascript was at the forefront developing responsive, fluid web applications. But NodeJS allowed for the backend to also be developed in JavaScript. This meant that JavaScript could be used both as a server side and a client side language reducing any requirement to involve another language for the development of a given website. Isomorphic JavaScript is its next evolution where client side JavaScript is also redered in the server making the codebase singular both for client side and server side development. You can read about this concept more deeply at the following link --> Why Isomorphic JavaScript? Why we use web application frameworks? A language like NodeJS and its primitives can easily be used to develop a simple web server without any other 3rd party libraries like Express. However, people have already attempted this throughout the industry and identified repeatable ways to make developing web applications much easier than using bare metal language features like the node HTTP module. These are called (backend) web application frameworks. In the industry these are commonly known as backend web frameworks. ExpressJS is one such framework that is built to work on top of the NodeJS runtime. Our server-side code is written leveraging the useful tools provided to us by ExpressJS. Some similar application frameworks for other languages include are Django for the Python runtime and The Spring framework for the Java runtime. Deeply Exploring the ExpressJS Hello World code from the last module In that bit of code what we simply did was send a reply called “Hello World” when a browser visited the /hello location ( localhost:3000/hello) on the app. Let’s go line by line to understand this code. Example Hello World Code In the first line, we can see that we are extracting the code related to the express framework from the express module. You will learn about modules more deeply in the section “Deeper look at Node and Express”. Next, we will be initializing an express instance, this is a necessary step required to start using express js where some internal configuration takes place. After that, We define the route paths where the application will be accessible. Another important thing to note on line number 5, is the response object (the parameter res). Here we call the response object's send function, which then sends a response back to the requester. Finally, we listen and wait for any incoming requests on port 3000 of this computer. Routing in web applications If you can remember in section 1.4 we learned what a URL is. And this is where we will be building on that foundation to understand one of the core concepts of server-side web applications. When we talk about a route we are talking about everything beyond the host(Domain name) and port elements of the URL. Let me take an example to explain to you this concept. You can think of a web server as an intelligent thinker from whom you can ask a set of pre-defined questions. For example, in an eCommerce site like Daraz or Keells, their servers contain sophisticated code to answer various questions. For example, some questions maybe o What are the products available on your site. o Can you place an order for a given product. o Where is my product currently. o Can I raise a complaint. Routes are a convenient way to organize these questions into readable identifiable paths. Defining Routes in ExpressJS Defining routes is done using the following syntax. app.METHOD(PATH, HANDLER) The route function has clear syntax and we provide the relevant path and the function that needs to run when that path is accessed. HTTP methods will be looked into later but just know that there are several methods and GET and POST are the most popular ones. For this section, we will only be looking at GET requests. The Request and Response Object in NodeJS. When you provide a callback (handler) to the route definition. The callback will be called by express with 2 parameters req, res as shown. - The (req) request is a representation of the request that came in. - The (res) response is an object which has some functions that will help us send a reply “send” is one such function You can get a clear view of this by going into the documentation API reference linked below. Activity o Try displaying an HTML page with the current knowledge you have. (Hint: Remember browsers understand any string which contains HTML and you can return any string using Express) o Setup a route in express where you can send a reply based on the query parameters. (Hint: refer to the Express documentation / Or google how to read query parameters from the request object.) Resources Basic Routing API reference for Request object API reference for Response object DEMO When building any application on a server, or any other computer, we normally rely on a programming environment which is often called a runtime. NodeJS is one such runtime and it is a key piece of software that helps us write JavaScript code that can be run on a server. There are several other programming environments that allow you to write code in a particular language. The Python Interpreter is one such environment that you are already familiar with and allow you to write python code. Several other important programming environments are the PHP Interpreter for the PHP programming language, and the Java Runtime Environment which can run compiled Java code. And of course, as we explained before, the all-important NodeJS Interpreter facilitates the writing of JavaScript on your server environment. You might notice the unfamiliar Jargon word Interpreter. This is a concept related to programming languages that you can ignore. If you are curious, I have included a small note and some resources in the lecture notes related to this concept. Even though, there are many programming environments to choose from, NodeJS stands out from the crowd. There is a reason for this. For many years, as the internet grew, the fundamental programming language for client-side programming has been JavaScript and for the server-side, we have to choose a different language like Java or PHP. NodeJS created the opportunity for JavaScript to be used as a server-side language. Consequently, for the first time in the industry, one language could be used for both server-side and client-side development. This means a typical software developer could develop and end-to-end web application using only JavaScript. This phenomenon is commonly known in the industry as Isomorphic JavaScript. Now let’s understand how expressJS fits into this picture. As I explained in the previous section pure NodeJS can easily be used to develop a simple web server without any other third-party libraries like express. However, people have already attempted this throughout the industry and identified repeatable ways to make developing web applications much easier than using bare metal language features like the node HTTP module. These are called web application frameworks. In the industry, these are commonly known as back-end web frameworks. ExpressJS is one such framework that is built to work with the NodeJS programming environment. Our server-side code is written leveraging the useful tools provided to us by expressJS. Some similar application frameworks for other languages included are Django for the Python runtime and the Spring framework for the Java runtime. Now let’s dive into the code example from the previous module to understand the few basic concepts of expressJS. In this bit of code, what we simply did was, send a reply called “Hello World”, when a browser visited the /hello location on the app. Let’s go line by line to understand this bit of code. In the first line, we can see that we are extracting the code related to the express framework from the express module. You will learn about modules more deeply in the section deeper look at nodes and express. Next, we will be initializing an express instant. This is a necessary step required to start using expressJS where some internal configuration takes place. After that, we define the route paths where the application will be accessible. We will be diving a bit deeper into the route concept in the next slide. Another important thing to note on line no.5 is a response object, the parameter ‘res’. Here we called the response object “send” function which then sends the response back to the request. Finally, we listen and wait for any incoming requests on port 3000 of this computer. If you can remember in section 1.4, we learned what a URL is. And this is where we will be building on that foundation to understand another core concept of the server-side web applications understanding routes. When we talk about the route, we are talking about everything beyond the host and the port elements of the URL. Let me take an example to explain to you these concepts.You can think of a web server as an intelligent thinker from whom you can ask a set of pre-defined questions. For example, in an e-commerce site like Daraz or keels, their servers contain sophisticated code to answer various questions. For example, some questions may be, what are the products available on your site, can you place an order for a given product, where is my product currently, can I raise a complaint. Routes are convenient way to organize these questions into readable identifiable parts. Let’s now try to implement some routes in nodeJS and express. I will only be looking at GET requests for now and you will dive deeper into other types of requests later. Let’s now try to implement some routes in a code. I will only be looking at GET request for now, but you will dive deeper into other types of requests later. Let’s start where we left off in the last section where we created an NPM project and added the express library and did a simple “Hello World” on to the browser. Let’s create a brand-new file. So that we can leave the previous code intact. Let’s borrow some from our previous file. So that we don’t have to type it in again. And let’s remove the route section for now. Now, let’s look up the documentation on how to set up routes. am going to do some basic routing. So, let’s follow this link from the official documentation As you can see the route function has clear syntax it provides the relevant path and the function that needs to be run when the path is accessed. HTTP METHODs will be looked into later but just know that there are several methods and GET and POST are the most frequently used ones. For this section, we will only be looking at GET requests. Let’s take a look at a quick example for this. Just copying the syntax, so that it’s easy for us to understand. If the method, we want is GET, we use app.get. If we want to use post, we do app.post. Once we type in app.get this needs to be called a function. And in the function, the parameters are first the relevant path("a/cool/route/path") and a callback function( function(req , res) ) which will be executed when this route is accessed. Express provides us with two parameters when express calls this function for us one is requested and the other is the response. Let’s see whether this works. To test whether it works, let’s set a small log expression and let’s logging. Now let’s try running this bit of code. Here you are going to try and execute this function, route_demo.js And let’s try accessing this route. Let’s copy this. Yes, the log was printed out into the console which proves that this function will be called whenever someone visits this path. Now to avoid the browser from this stuff waiting for a reply. Let’s send it back a reply when this route is accessed. This is done by typing in res.send. Let’s rerun this. Let’s see if everything works. Yes, as you can see, we get a reply that we defined. Although not covered deeply in this section, the request and response are two important parameters that may come to this route called back. The req request is a representation of the request that came in and what data you can access from that request. The response is an object which provides functionalities and certain constant data that you can send back as a response to your client. The documentation provides extensive details about these two parameters. If you go to the API reference, these two objects the request and response are what is being returned to us when we provide a callback. The request has many properties and methods that help us identify the request that came in and the response has some properties and many methods that allow us to send a certain type of response back to the user. If you would like to dig in a bit further into this concept, I will provide these resources in the lecture notes for you to explore. Thank you for sitting through this module with me. I hope, you are now confident to set up a simple webserver with NodeJS and express. Introduction to Asynchronous Programming Overview In computer programming, the two main code execution methods used are synchronous and asynchronous. These execution methods define how the tasks are performed. The synchronous model is suitable for simple applications, but not for complex web applications. In this lesson, we learn about the importance of the asynchronous method for server-side web programming, and how it is achieved in JavaScript using Promises. Asynchronous Vs. Synchronous In synchronous operations, tasks are performed one at a time, and only when one is completed, the following is unblocked. In other words, you need to wait for a task to finish to move to the next one, and the code executes in the same order as you write. Most of the code falls under this category. In asynchronous operations, you can move to another task before the previous one finishes. Some special use cases fall under this category. A simple analogy to understand this concept shows in Figure 1. When you communicate with your friend over the telephone, you have to wait until your friend speaks, and vice versa. This is similar to how tasks are performed in the synchronous approach. However, when you send a message to your friend using your computer, both of you can type and send messages at the same time. That is similar to how tasks are performed in the asynchronous approach. Figure 1: Asynchronous Vs. Synchronous (Source) Standard web applications process interactions between web visitors and the server synchronously. This means that one thing happens after another; the server does not multitask. If you click a button, the message is sent to the server, and the response is returned. You cannot interact with any other page elements until the response is received and the page is updated. Obviously, this kind of delay can negatively affect a web visitor's experience, hence we can use asynchronous programming as a solution. Why Asynchronous? Asynchronous programming is a technique that enables your program to start a potentially longrunning task, and then rather than having to wait until that task has finished, to be able to continue to be responsive to other events while the task runs. The asynchronous concept is used for complex applications with many components, a large number of API calls, and many calculations. We have to make API calls in the application to get the required data or pass data to the database. In some cases, we might need to load two components at the same time. If you have a long list of items and need to load them in groups of 10, then you will need this asynchronous concept. With asynchronous programming, the user can move to another screen while the function continues to execute. Usage of Asynchronous coding This concept is useful for applications of any scale, from simple CRUD operation samples to complex enterprise-grade applications. Usages of asynchronous are as follows, o Parallel component event handling o API call or other AJAX requests o Time consuming calculations or queries o List or component loading in the background What are promises? A code can give a promise when it’s certain that it can provide a result. A result can be either a success or an error depending on the outcome. Promise can have two results, o Resolve: Code executed successfully and outputs the result o Reject: An error occurred and the code failed to execute For example, when we request data from the server by using a Promise, it will be in pending mode until we receive our data. If we manage to get the information from the server, the Promise will be resolved successfully. But if we don’t get the information, then the Promise will be in the rejected state. Example Create a html file and a js file. Include the following two functions to the js file and bind two buttons and span elements with ids ‘sync-output’ and ‘async-output’. Synchronous Code function syncCode() { var outputText = ""; outputText += "Going to kitchen\n"; outputText += "Put water to the kettle\n"; outputText += "Plug the kettle\n"; outputText += "Water boils for 5mins. I'm waiting till it's boiled.\n"; outputText += "Water is boiled. Now I put sugar and tea leaves to a cup\n"; outputText += "Pour water into the cup and stir\n"; document.getElementById('sync-output').innerText = outputText; } Asynchronous Code function asyncCode() { var outputText = ""; outputText += "Going to kitchen\n"; outputText += "Put water to the kettle\n"; outputText += "Plug the kettle\n"; outputText += "Water will boil for 5mins. I'll do some other stuff\n"; setTimeout(function() { // Water is boiling for 5 mins and then this code will execute (5 seconds) outputText += "WATER IS BOILED NOW\n"; outputText += "Pour water into the cup and stir\n"; document.getElementById('async-output').innerText = outputText; },5000) outputText += "Water is still boiling, until then I put sugar and tea leaves to a cup\n"; document.getElementById('async-output').innerText = outputText; } Activity o Run the code in the above example to see the printing order of texts in both functions. o Assume that you need to wash the cup before adding the sugar and tea leaves. It takes 1min to wash the cup. Update the above code to add the task "Cleaning the cup before adding the sugar and tea leaves", while maintaining the correct order of execution.. Resources Synchronous Vs Asynchronous Programming Demo There are two different types of code execution methods. They are, Asynchronous and Synchronous. You have experienced Synchronous codes so far. It executes in the same order as you write which is why it’s called sequential. In Asynchronous code, you can let a code execute and move on to the next line without waiting for the previous code to finish executing. Let’s take this well-known example of making a cup of tea. First, you do a bunch of sequential tasks such as going to the kitchen, putting water into the kettle, plug the kettle. Now the water starts to heat up. You can choose to be Synchronous which means to wait and watch until the water boil or you can be Asynchronous to let it boil and do some other work such as putting sugar and tea leaves in the cup. Let’s see why people need this Asynchronous concept. It’s a must-have for complex applications with many components, a large number of API calls, and huge calculations. You may have the question, are we making complex applications here? The answer is NO but there are reasons why we need this concept. We have to make API calls in the application to get the required data or pass data to the database. In some cases, we might need to load two components at the same time. If you have a long list of items and need to load them in groups of 10, then you will need this Asynchronous concept. What are promises? A code can give a promise when it’s certain that it can provide a result. A result can be either a resolution or an error. Resolve means that the code ran as expected and we get the result of that code. When there’s an error occurred while executing the code, the promise will give a reject which indicates that the code didn’t execute as expected. For your knowledge, there are two other terms you can refer to. Producing code and consuming code. Producing code is the code that we want to run inside the promise. Consuming code is where that promise is used and waiting for the result. Let’s see Asynchronous coding in action. Let’s have two functions to change the text inside a span element. syncCode function is executed in the normal way. We do the tea-making steps in an ordered way. We wait for the water to boil and then only we are putting sugar and tea leaves into the cup. For the asyncCode part, we are not waiting for water to boil which takes 5 seconds to complete here. We will continue with the other part of the code while the water boiling part is being done. That’s how Asynchronous and Synchronous code works. Thank you! Introduction to JSON Overview The client and the server communicate by exchanging messages. One of the ways to format the exchanged message such that both the client and server understand is to use JSON data format. It is a lightweight, text-based, and language-independent data exchange format. In this lesson, we learn about the JSON data structure. What is JSON? JSON stands for JavaScript Object Notation. It is used to transport data between applications universally. It can be used even if the applications are written in two different languages or frameworks. There are other methods we can use such as XML or Plain Text but they have several drawbacks compared to JSON. JSON is the widely used industry standard for this purpose Usage and the importance of JSON JSON can be used to accomplish the following, o Client and server bi-directional communication. o Handle multiple structured data types in communication. o Can be used as a universally understood data format. Rules and characteristics of JSON JSON data structures should comply with the following set of rules. o Each element is enclosed in a curly bracket. o o Different keys are separated by commas o o { “This is the key”: “This is the value of that key” } Value can be String, Array, Object, Number, or Boolean o o { “OneKey”:” value of oneKey”, “secondKey”:” value of secondKey” } Each data is in key-value pairs o o { JSON data goes inside this } { “keyString” : “I am string”, “keyNumber” : 119, “keyBoolean” : true, “keyArray” : [100,20,30,40], “keyObject”:{“someOtherKey”:”hello”}} JSON elements inside objects can be accessed by, o keyObject.someOtherKey o keyObject[“someOtherKey”] o keyArray[0] Activity o List the key differences between AJAX (Asynchronous JavaScript And XML) and JSON.. Resources Introducing JSON ECMA-404 The JSON data interchange syntax Demo Let’s see what JSON stands for. It stands for JavaScript object notation. It is used to transport data between different applications even if the applications are written in two different languages or frameworks. There are other methods we can use such as XML or Plain Text, but JSON is the widely used industry standard for this purpose. The major reason we need JSON is to unify all the platforms into an understanding of data format. JSON can represent Strings, Arrays, Numbers etc. in a format which is universally understood. Let’s see how to include data in JSON. Each JSON element is enclosed in curly braces. Everything is represented as key value pairs in JSON where key is in the left hand side and the value is in right hand side. Key and value is separated by a colon. Values can be String, Array, Object, Number or Boolean. If it’s a String then the value should be enclosed in quotation marks. Numbers can be integer or double values. Boolean can be true or false. Arrays can be enclosed in square brackets and values inside are separated by commas. Value types can be anything. Objects are basically another JSON object within a JSON object. So, the same set of rules apply. We will take this example to include user information with name, age, telephone, the isMarried flag and address with street name, city and postal code. This will cover all the data types. Let’s see how we can write this using JSON. This is the answer for the example we discussed earlier. Please note the data types we used and how the key value pairs are working here. Creating REST APIs Overview We can create client-server applications in different ways and there are already established architectural styles and communication methods to help us do this. Creating a RESTful client-server application and using REST APIs to communicate between them is one of them. This lesson will discuss REST APIs and how clients can consume them to communicate with an independent server. What are REST APIs? REST stands for REpresentational State Transfer. It is an architectural style that provides standards to denote how computer systems should be maintained on the web. Systems that follow the REST style are also called RESTful systems. According to REST when we create client-server applications, we can maintain the client and the server independently as to how we have been learning over the past few courses. API stands for Application Programming Interface. It is an interface that allows two computers or computer systems to communicate with each other. REST APIs are APIs that adhere to the standards set by the REST architectural style. In RESTful client-server applications, we can use REST APIs to communicate between the client and the server to send and receive data. According to REST, the client should initiate the communication by making a request to the server. This communication happens over HTTP (HyperText Transfer Protocol) and we use different HTTP Methods such as GET, POST, PUT, PATCH, and DELETE to define what kind of operation the client is requesting from the server in the request. These will be taught in more detail during a later lesson. Consuming REST API When a client application accesses and uses the API endpoints maintained by a server, the client is ‘consuming’ the API. We can consume REST APIs using frontend applications like a jQuery client or testing tools like Postman that simulate a client-side implementation. For a client to successfully consume a REST API, it must know the following information about the API. 1. The domain name / IP address of the REST API service (E.g.: localhost, google.com). 2. The port number (E.g.: localhost:8080, 127.0.0.1:3000) 3. The resource path (E.g.: localhost:8080/users/1) 4. The request method (E.g.: GET localhost:8080/users/1, PUT localhost:8080/users/1) 5. The arrangement of the data that is being passed or received. Consuming REST API using Postman Postman is an API testing environment that can simulate client requests (Figure 1 and Figure 2). Postman can be used to test different types of client requests such as GET, POST, PUT, PATCH, and DELETE. By sending a request using Postman, the client-side interaction is simulated and we can view the response of the server for that type of request. Postman can be used for other purposes such as creating mock servers and generating standard documentation for APIs as well. Note: The actual placement of windows such as the server response area of the Postman interface of your application may differ slightly from the figures provided (Figure 2). Figure 1: Postman interface Figure 2: Simulating a client request using Postman Let’s do some activities now to make sure you have understood the lesson. Activity 1 Open up Postman and create a new request. Explore the interface that you get. Identify the different HTTP request types, request specifications like parameters and request body, and server response views you can simulate using the tool. Hint: If you have not yet installed Postman, you can do so using the link provided at the end of this lesson. Activity 2 Simulate a POST request to send data to the database using the mock API we used during the lesson. The resource path is, https://61631622c483380017300818.mockapi.io/v1/users Hint: Refer to the following link if you have difficulty navigating the Postman interface to send POST requests. https://www.tutorialspoint.com/postman/postman_post_requests.htm Consuming REST API using jQuery We can also consume REST API using frontend applications such as those implemented with jQuery or Angular. jQuery is a JavaScript library that can handle AJAX requests. Here, the frontend application will be the client who generates the relevant client request that accesses the API endpoints maintained by the server. With jQuery, we must specifically program the client requests using JavaScript as shown in Figure 3. Figure 3: Consuming sample GET and POST requests using jQuery Resources Installing Postman Consuming REST API using Postman Demo Open the postman interface and test a REST API like this. Creating an API using mockapi.io My example is adding a user to the database. To do that my resource path is /v1/users and the request method is POST because I am sending data from the frontend side. The request body is JSON type and contains the fields of the object. Send the request and try to view your database to check if the record is added. Try other methods as well like GET, PUT, PATCH, and DELETE. We are going to get all datas in database back. Change the method to get consume REST APIs using jQuery We are going to use a small HTML application like this, to demonstrate how to consume REST APIs using jQuery. First, let’s create a new HTML file called index.html. In this file, please type this bit of code to add two buttons that we will use to demonstrate a GET and POST request. In the header section, make sure you add the script to access jQuery and in the body add these two buttons and the title in this way. Make sure that you use the correct IDs for the HTML components since we will be using them to bind the data responses that we are receiving. Once you are done until this point, let’s try to implement a GET request. Inside the script tag, define a function that will activate when we click on the button for the GET request. We will use an already existing API endpoint that we talked about earlier to test our application. You can copy this from the Video Script given in your lesson. GET request URL: https://644bf3324bdbc0cc3a9ebf94.mockapi.io/v1/users/1 If the request is successful, the API should return a JSON object as the response. We will append this JSON response object to the get-response section of our webpage to observe what happens. If you are done writing the code until this point, let’s try testing out this example. Refresh your browser and click on the button. See how the JSON response is appearing? Since we haven’t applied any styling to our webpage it will appear like this, but in larger applications, we can style and organize how to display this response data as we want. Now, let’s try the POST request. This is how we implement a POST request using jQuery. Please use this URL given here for your request. POST request URL: https://644bf3324bdbc0cc3a9ebf94.mockapi.io/v1/users Next, create some dummy data like this to be sent as part of the client request inside the POST method. Please make sure that you indicate the properties of the JSON request object like this. These properties should be listed correctly as these are what the API is expecting to consume. Once you are done, append the result to the post-response section to see the relevant output. Refresh your browser and click on the POST button to test your implementation. As you can see both requests are working fine. We can also use jQuery to consume PUT, PATCH, DELETE, and other HTTP requests in a similar manner. HTTP Methods - Node and the HTTP Module Overview This lesson will cover the in-built HTTP Module in Node and how it can be used to create web servers, establish HTTP connections, and communicate with client applications via HTTP methods. Client applications can communicate with backend webservers using HTTP. During these communications, client applications send different types of requests to the webserver. Based on the type of request that is received, the webserver has to craft the appropriate response. That is why there is something called the ‘HTTP Module’ in Node JS to help webserver applications handle these kinds of HTTP communications. What is an HTTP Module in Node? The HTTP Module in Node is an in-built module that can be used to create networking applications such as web servers using Node JS. It allows the client application to communicate with the backend services and transfer data using HTTP. These are the basic steps that need to be followed to implement a simple web server application using the HTTP Module in Node JS. You can see the code implementation of this in Figure 1 below. 1. Require the HTTP Module into the application. 2. Create a server instance using the createServer() method in the HTTP module. 3. Make the server listen for an HTTP connection using the listen() method. Figure 1: Implementing a simple web server using the HTTP Module The HTTP Module and Express The Express framework is built on top of the HTTP module like a wrapper. The capabilities of the HTTP module can be accessed through Express to create backend services for client applications using Node JS. The HTTP Module itself is not used due to the complexity of the implementation. One way of implementing a web server using Express is given in Figure 2. Figure 2: Implementing a simple web server using Express What are HTTP Methods? HTTP methods indicate the type of action that the client application wants the webserver to complete when it sends a particular client request. Since there can be many types of actions, these HTTP methods help to differentiate the different types of requests and the operations that need to be taken for each type. The most common types of HTTP methods and their expected actions are indicated in Table 1 below. Table 1: Commonly used HTTP Methods HTTP Method Expected Action Description HTTP POST Creating data Data is sent from the client to the web server as part of the client request. HTTP Method Expected Action Description A POST request indicates that this is new data that must be saved by the webserver. For example, form data is usually submitted through HTTP POST methods. HTTP GET Retrieving data Data is sent from the webserver to the client as part of the server response. No data manipulation except retrieving the relevant data should be done inside an HTTP GET method. Like the POST method, data is sent from the client to the web server as part of the client request. HTTP PUT HTTP DELETE Updating data A PUT request indicates that this data is usually a new version of an existing record and that the webserver should replace the old data. An HTTP PUT method will also create a new record if the data does not already exist, but this is usually not used for this purpose. Data has to be removed from the data storage as indicated in the client request by the client application. Deleting data An HTTP DELETE request indicates that the web server’s implementation should delete that relevant data from storage. Now, let’s do some quick activities to make sure that we have understood the lesson properly. Activity 1 Do an internet search on HTTP methods. Identify 3 HTTP methods that we did not learn about during the lesson and their functions. How do you implement the HTTP methods you identified in a Node JS application? For Activity 2 and Activity 3, please use the coding playground that is available at the bottom of the page. Activity 2 In your application, there is a new HTTP POST method implemented with the endpoint ‘/post’. Go to the adjoined web browser of the coding playground and add “/post” to the end of the given URL. Observe what happens. Do you see an error? What do you think is the reason for this? Note: Make sure to restart the Node server each time you make any changes and save your code. Activity 3 Now, change the same HTTP POST method to an HTTP GET request and repeat what you did in Activity 2. What is the observation this time? What do you think is the reason for this? Note: Make sure to restart the Node server each time you make any changes and save your code. Resources The Node JS HTTP Module HTTP Methods Using HTTP Methods with Express Demo For today’s lesson, I have created a new Node JS application and installed Node and Express in it. If you want, you can use one of your existing demo applications or you can create a new one like me. The starting point of my application is this server.js file. In this file, I have used Express and HTTP to create a web server and have it listen for an HTTP connection. As you can see here I have defined the port that my server is using as port 8000. If our server is working properly it prints this statement in the console. After you have created the server run your application using the node server.js command in your terminal and make sure that everything is working properly. If everything is fine now we can try out some HTTP methods. First, let’s try an HTTP GET method. This part here [“/”] , is the request URI or the Uniform Resource Indicator. In other words, this is the API endpoint that your client must call if they want to retrieve this particular data. As you already know these two variables [(req,res) ] in the call-back function refer to the client request and the server response. If this were a proper application we could write the logic to retrieve some data from the database here and then send it back to the client application as part of the response. Since we don’t have any actual data to work with at the moment, I will just have the response print the statement ‘Getting some data’ instead. Do you remember how we used Postman to test APIs during the previous lesson? Let’s use Postman to test this HTTP GET request. Open up Postman and type the correct API endpopint here.From here, select the request type as ‘GET’ and test your API. See I am getting the statement, ‘Getting some data’ as the response. If you are getting any kind of error, don't forget to save the work you did in your application and then rerun your node server. Now, let’s do the same for our POST, PUT and DELETE methods. You will notice that I am using the same URI for each request. But, since the HTTP method is different, our application will understand that these are different API endpoints. Once you are done creating your endpoints go back to your Postman application and test them out one by one. First, let’s try the GET request again. Now, let’s try the POST request. Next, do the PUT request. Finally, test the DELETE request. It seems like all our endpoints are working fine. If we had some actual data, we would have to write the code needed to retrieve, save, update and delete that data inside these HTTP methods. But for now, we have proven that our web server is running properly and that we were able to communicate with this server using HTTP. Creating a Database Connection Overview In this lesson, we are going to discuss how client-server applications store data for their applications and how they initiate communication with databases to access and manipulate this data. So far, we have only talked about the client-side and the server-side of web applications, but there is actually another component that exists in these applications. That is the database, where all the data required by the application is stored and handled. When users use client applications they generate large amounts of data and while the user continues to use the application there can be many instances where the application needs to access, modify, or even delete this data. However, the data that these operations must be done on is not available on the server itself. The data will be kept in a database that the server will access to perform actions on the required data. Client-Server-Database Communication The basic steps that are followed by the application to access data These steps are shown in Figure 1. 1. The user triggers an event on the client application that needs to access or manipulate some data. E.g., Submitting a form, Editing profile information, etc. 2. The client application sends a request to the server containing the details of the operations that need to be performed (the communication will happen over HTTP). 3. If some data manipulation is required, the server will send a communication to the database specifying the relevant operations. 4. The database will perform the required operations and send the designated response back to the server. E.g., If the operation was to retrieve some data, the database will send the relevant data to the server. 5. The server will then process the database response, and send a relevant response back to the client application. 6. The client application will receive the response and update the views and interfaces if it is required. Figure 1: Client-Server-Database Communication What is a Database? A database is an organized collection of data that can be managed, accessed, and analyzed based on various requirements. What is a Database Management System (DBMS)? A Database Management System is software that we can use to support the activities needed to handle data in a database. Some examples of popular DBMSs include, o Microsoft Access o SQL Server o MySQL o Oracle Let’s do a quick activity now to make sure we have understood the lesson so far. Activity 1 Do an internet search about databases and Database Management Systems. Find out the main differences between any three DBMSs that you like and what they are used for. Now, let’s get back to the lesson. Types of Databases There are different types of databases that store data in different formats. Some common database types include, 1. Relational Databases These databases store data according to the ‘Relational Data Model’ or Tables. The table stores data as rows (tuples) and columns (attributes) to make up the overall data model. These databases use a special language called Structured Query Language (SQL) to handle their data. Some DBMSs that handle relational databases are Microsoft SQL Server, MySQL, and Oracle. 2. NoSQL Databases These databases store data in different formats that do not belong to the relational data model. They include storing data as key-value pairs, graph objects, and documents. NoSQL databases do not use SQL to handle data. MongoDB is a popular document-based database that falls under this category. There are many other types of databases such as Cloud databases, Hierarchical databases, Object-oriented databases, etc. Let’s do another quick activity to find out more about them. Activity 2 Do an internet search about the different types of databases. List down 5 database types except for Relational Databases and NoSQL databases and the format they use to store data. Now, let’s get back to the lesson. What is SQL? SQL stands for Structured Query Language. It is a standard language that we can use to write commands (queries) that can be used to handle data in some database types like Relational databases. Even though SQL is the standard language, different DBMSs use some variations of SQL. SQLite and SQLite Queries SQLite is a database engine that stores the database within a single file. It stores data in a relational database model (table) and supports queries written in SQL to handle data. The following are some of the most common SQL queries that can be used in SQLite. 1. Creating a table CREATE TABLE table_name ( column_1 data_type PRIMARY KEY, column_2 data_type NOT NULL, column_3 data_type, ); 2. Deleting (dropping) a table DROP TABLE table_name; 3. Select all data in a table SELECT * FROM table_name; 4. Select only some columns from a table SELECT column_1, column_2, column_3 FROM table_name; 5. Select data based on defined conditions SELECT * FROM table_name WHERE search_condition; 6. Insert data into a table (1 row at a time) INSERT INTO table_name (column_1, column_2,...) VALUES (value_1, value_2,...); 7. Update data in a table UPDATE table_name SET column = value WHERE search_condition; 8. Delete data in a table DELETE FROM table_name WHERE search_condition; Resources SQLite Tutorial Demo Create a new Node project, and implement an HTTP server in it. If you like you can use the same application we built during our previous lesson on HTTP methods. This is what I will be using. In this application, let’s create a new file called database.js. We are going to use this file to configure our connection with an SQLite database. There is an NPM package called ‘sqlite3’ that is specially built to help us handle SQLite database connections with Node. Next, install this package into your project. Now, let’s create our database connection. Unlike DBMSs like MSSQL and MySQL, which store data in external servers, we can use SQLite to store our data with our web server itself. For this, we have to specify where to keep our data. I will use a file with the name ‘db.sqlite’ for this. Now, let’s create a new SQLite database in this location. Please follow me and type this code in your file. We will first check if there is an error in accessing the database and if there is, we will print that error in the console. If not, we will display that the database connection has been established. Now, export your database object using module.exports statement and import it into our server.js file like this. As I mentioned before, how you create the database connection depends on what database you are using, so what you learn during this lesson will not be applicable to every type of database that you may have to use in the future. If you are not running your application right now, let’s try doing that. You will see that the database connection has been established and that the success message is being printed on the console. Now, we can use our server to run SQL commands to create tables, insert, retrieve, update and delete data in our database based on client requests. We will learn more about how to run SQL queries with this SQLite database during our next lessons. 8/10 Handling Form Data Overview During previous lessons, we discussed how client applications communicate with server-side applications over HTTP to perform user-driven actions. In this lesson, we will go into more detail on how an Angular client application can communicate with a Node server. The Angular Client Angular applications use ‘Services’ to initiate communication over HTTP with web servers. An Angular Service is a class that Angular uses to handle operations such as fetching data from a backend server, that the Angular component itself should not handle. To learn more about Angular Services, please revisit the relevant lessons in our course on Front-end Web Development. As seen in Figure 1, the Angular client will use a service to establish a connection with specific API endpoints. These endpoints need to be implemented by the accessed web server. Figure 1: The base URL as indicated in the Angular Service The Node Server The Node server is the backend application that will implement the necessary endpoints that the client needs to access. The server must run on the same port and address that the client is accessing and must implement each API endpoint required (Figure 2). When a client makes a request, it will look for the matching endpoint and HTTP method in the server and carry out the relevant actions. Figure 2: The port number and API endpoints as indicated in the Node server Cross-origin Resource Sharing (CORS) Cross-origin Resource Sharing is a mechanism that allows controlled access to resources located outside of its own domain. Client applications and Server applications are separate applications that need to access each other when communicating. The server application contains resources that handle the application data (in the database) that need to be accessed by the client. It is not possible to allow any application to access these resources due to security concerns. Therefore, there are restrictions that define which client applications can access each server application. If an unauthorized client application tries to communicate with a server, it will encounter a CORS error. To fix such errors we should enable CORS on our server application. One way of how this can be done is shown in Figure 3. Figure 3: Enabling CORS on the Node server Now, let’s do some activities to make sure that we have understood this lesson correctly. Activity 1 Below are two snapshots (Figure 4 and Figure 5) of the service class of an Angular client and the serverside implementation of a Node web server that the Angular client is trying to communicate with. Will this communication be successful? Give reasons for your answer and if there is an issue, identify how you can fix it. Hint: Assume that CORS errors have already been handled. Figure 4: The Service class of the Angular client Figure 5: Node server implementation Activity 2 Below are 2 more snapshots (Figure 6 and Figure 7) of the Service class of the Angular client and the associated Node server. Identify whether the shown API calls from the client will be successful. Give reasons for your answer. Figure 6: The Service class of the Angular client Figure 7: Node server implementation Resources Download Links for Example Project Angular Client Implementation Node Server Implementation Demo First, let me explain what we are going to do today. We are going to implement a web server that can act as the backend for this application that you can see on my screen. This interface might look somewhat familiar to you already. That’s because we implemented a very similar interface to the Smart Grocery App that we created as part of our previous course on Front-end Web Development. Here, I have a simple form that we can use to add a product to a list of products that we already have. When a product is added using this form, the product name has to be added to the Products List that we see here on the left side of the screen. In our web server we have to implement two HTTP methods; one to retrieve the product list and send it to our Angular client and another to store the data that is submitted with this form. But first, let’s set up our client and web applications. We are not going to create this client application from scratch right now. Instead, the code needed for the Angular client and the initial version of the backend server has been provided to you as part of the course content. You can use this to set up the two applications on your machine. Or else, if you are using the embedded code editor they will be set up as 2 different projects for you. In your course, head over to your ‘Lecture Notes’ section and scroll down to the very end. There will you see the download links for the example project. This is the project for the frontend implementation. You can get the code from here and set up the project on your machine. Similarly, you can use the other link to get the backend implementation. After you have cloned the two projects, you can set them up on 2 different windows of Visual Studio Code. You can get a new window using File->New Window here, and open the relevant code. I am not going to do this again because I already have my two projects set up in two different windows here. First, let’s set up the angular client application. Open up the code in Visual Studio Code and in the terminal move into the ‘Form-Application’ folder. Then, give the usual command npm install –save(but I used npm install) to install the NPM packages needed for the application. Then use ng serve to run the application. Next, open another new window in Visual Studio code and use it to set up your backend application. Use npm install –save to install the NPM packages and use node server.js to run your application. This server.js file will be the starting point for our backend application. At the moment, we have only implemented the server creation, so we need to work on the HTTP methods next. But before we do that, let me quickly explain a bit more about our two applications. The Angular client has a single component called Products. The Products component contains a form that will allow us to add a new product to an already existing list of Products just like how we did in our previous course. When a new product is successfully added the name of the product will be displayed on the left side of the screen. I will not explain this code in detail since we have already learned how to build reactive forms with validations in the previous course. If you have any doubts, please visit the lesson on Reactive Forms in the course on Front-end Web development. The Products component will communicate with the backend application using the Product Service. Here, we are using this URL to communicate with our backend application and as I mentioned before, this is the address that the server we create should also be running on. We have defined two routes, one to retrieve the list of Products from the backend server, and another to submit the data in the form to add a new product. You will notice that we are using several models to map the request and response data that we are communicating with the backend. When we are creating our backend implementation, we have to be mindful about these models too because the data that we program our routes to take in or send out must match what the Angular client is communicating. Otherwise, we will run into errors or lose the data that is being communicated. First, open up both your Node and Angular applications in two separate windows in Visual Studio code and run them. If you are using the code editor in Stackblitz, you can open them as two separate projects. After you run your applications go to your Node application. As you can see a basic server has already been created. You might remember that this port number and all the routes that we have written have to match the routes that we used in our Angular application, just like what is indicated here. Back in our backend application, a database connection has also already been created for you. Like we learned during our previous lesson, we will use a SQLite database with our server. Here in the database.js file you can see that we have created a connection to the database. Here, I have first set up a new database in the source db.sqlite as we discussed in the previous lesson. If the server is unable to access this database it will log an error. Or else, it will log this message “Connected to the SQLite database” in our console as you can see here. Next, we will have the database run this query for creating a table. You will notice that the fields or columns of this table are the same as the fields that are in our Add-Product form that are in our client application. If we are able to create the table without any issue, the next step is to insert a set of dummy data into the database. We are doing this here. We are inserting one row of data using this query where the data, ”White Basmathi Rice”, this description and a unit price of two hundred is inserted into the table. All right. Now it’s time to start implementing our HTTP methods. First, we will implement the GET request that will retrieve the data items from the Products table and send it to the Angular client. Using the data received, our client will display the names of the products that are currently available in our database. Let’s do this now. You already know that these refer to the client request object and the server response. You will also learn more about these call-back functions in later lessons. Inside this function, we are going to write our code inside a try-catch block. We do this, so that we will be able to handle any errors that our server generates without crashing the application. The code that might cause an error is written in the ‘try’ portion. In our case this is going to include querying our database and sending the server response. Please follow me, and write down this code now. First, we will write down the query to select all the data from the Products table. We do not have any extra parameters that we are using with this query at the moment, so, we will define an empty array for these parameters. The reason why we need parameters is when we are running our SQL query using our server. it will look for first the query and then any parameters that we are passing in. So, we can use this command to run this particular SQL query. If there is an error, we will send a response with a 400 error status and print the error message as part of the JSON response. If there is no error then we can send a success status and our JSON object will include the message property with the message “success”. And also the data property which will carry the rows that were returned by running this particular SQL query. The structure of the response object is not something that I thought up by myself. It is the structure that we defined in our client application as the ‘product-response’ model. See? This model is what the client is expecting as part of the server response to the ‘getProducts’ method. Because of this, we have to map the response from the server side to match this model. Otherwise, the data will not be properly received. Back in our server, we can use the catch block to handle any error that happens when the server is trying to send the response. We will use this way to catch any of the errors that might occur. In that case, we can have it return the error instead and we can also assign a status to the response to once again indicate that the communication was not successful. If you have completed the code up to this point, we can now test our API. We usually use a testing tool like Postman to test APIs before testing it with the client application. That way if there is an error it is easier to identify whether it is caused by a wrong implementation on the server side or in the communication from the client side. Let’s also use Postman to test our API first. It looks like our API is working fine. Let’s see if this data is appearing now in our Angular client. Even when I refresh my application it looks like the data has not been received. To see what the issue is, let’s right click and inspect our application. If you move to the console tab here, you might notice that there is an error coming like this. It says that our request has been blocked by CORS policy. This is caused by Cross-origin resource sharing or CORS as we usually call it. You see, for security reasons we can’t always let our server be accessed by any kind of client application. If we don’t have any kind of security policy then any client that knows the API endpoints that we are using will be able to access the server and all the data stored in it. Because of this, there are policies to restrict API calls from clients that are not authorised by the server and if you try to access a server using an unauthorised client you might get this kind of CORS error. Since this is a bit of an advanced topic I will not go into detail here, but you can use the bit of code that I am about to add to our backend implementation to solve the issue. You can solve the issue by adding this bit of code. What I am basically doing here is giving permission to any client application to access our server. After adding this code, now let’s test our client application again. Refresh your browser and you can see that the data is appearing now. There are no errors logged to the console either. Next, let’s try to implement an HTTP POST method to submit this form. First, let’s take another quick look at the Products model on our client side. This is the data that is being submitted in the form. The product name, description and unit price are sent in the client request to the backend. The first thing we have to do from the server side is to capture this data after it is received. This data will be sent in as part of the request body so let’s access them now. Inside the implementation of your POST method, add this bit of code. Make sure, that these names are exactly the same as what you have defined in the Products model. But here, we might run into a small problem Node can’t understand the data sent inside a client request by itself. So we use a middleware called ‘body-parser’ to help our server parse the incoming requests before handling it. First, install ‘body-parser’ as an NPM package. Then require the middleware like this and use it to parse URL encoded data and JSON objects using this bit of code. We can then use the data in the request body to populate our database. We will do this next. Follow me, and add this bit of code to the implementation of your HTTP POST method. First, move the request body item inside a try block like we did with our HTTP GET request. Next, we will use this SQL query to insert data into our table. We are inserting values into the columns Product Name, Description, and Unit Price only. You might remember when we first created our table, the first column ‘id’ was given a constraint ‘AUTOINCREMENT’. This means that our database will automatically assign the next integer value to this column whenever data is inserted into this table. So, we don’t need to specifically send in any data for this particular column. In this query, we are not specifying the values that we need to insert because they are coming from the request body. Instead, we will use these placeholders to assign these values from our parameters which will be processed when the query is run. When this query is run, the system will automatically replace these placeholders with the values in the product name, description, and unit price. Similar to how we ran the query for the GET request, we will run this SQL command with these parameters and if there is an error, we will send an error status response with the error message. Or else, we will send a similar success response with the same structure. We will also use this catch block to capture any server errors. If you have completed the code up to this point, we can then test our API using Postman once again. From here, select the body and we can simulate the request body here. I am going to select ‘raw’ data and JSON here and type this dummy request body with this data to be sent as part of the client request. You can also use the form-view too from here directly. Once this is done, send this request and see what happens. It seems like we are getting a success message. Just to be sure, let’s go back to our HTTP GET request and use it to see if the new product has been added. Looks like it is working fine. Now, let’s check the same using our client application. Let’s input a new product using our Add-product form like this. If the product list gets updated that means we have successfully initiated the communication between the Angular client and our Node backend. Let’s submit the form and test this out. Our product list has got updated with the new product, so it seems that we have been successful in initiating the communication between the Angular client and the Node backend. 8/10 Deeper look at Node and Express Overview We learnt about the Node.js Modules in this topic. As Node.js developers, you can classify these Node.js Modules into 3 types. 1. Core Modules Core modules are coming in-built with Node.js source code and there are some essential modules such as, o http - gives ability to transfer data over http to the Node.js application. o https - gives ability to transfer data over https to the Node.js application. o path - handles file paths. There are many more modules available, you may find those by visiting the below link. Click here to visit Node.js Core Module list 2. Local Modules 3. Third-party Modules There are thousands of pre-designed Node.js modules avilable as third-party modules so other developers can re-use those to speedup their developments. Node Package Manager (NPM) allows the infrastructure for this and you can check below URL to see the available third-party modules. Activity o List down 5 most popular Third-party modules for Node.js. You may refer the official NPM website for this activity. Click here to visit www.npmjs.com You will learn about Node Package Manager in-detail in next lesson. Resources The below extra reading material contains more details about Node.js Modules. Different types of Node.js modules, there usages and also examples. Node.js Modules Explained Further Divide and Conquer method Suppose, you have a big computational problem! Remember, in course 1 you learnt about computational problems and computational thinking. So, if you have an idea to design a computer program to solve a real-world problem, it is recommended to use an approach called, “Divide and Conquer Method.” If you are using this method, what you are doing is, you try to divide/ or decompose a big computational problem into smaller problems. For example, if you find the manual calculations like addition, substraction, multiplication and divition as time consuming tasks, this is your large computational problem. So you may come up such as, addition of multiple numbers as one small problem. Multiplying numbers is another problem. Such as you break-down your large problem into smaller ones. But why you are doing this? It makes your coding lot more easier. Once you have smaller problems to solve, you can code to solve that specific problem. You can consider each part as a module of your big program. Advantages of Node.js Modules Now, this is exaclty what Node.js modules do. When you code in Node.js, you can adapt the divide and conquer approach and use modules to nicely organize your codes. There are many advantages you can get by following this practice. Those are, You can easily share your modularized code with others, or even you can re-use them in other projects. When your Node.js project has modules, it is easy to scale-up feature. You can continuously improve the project without affecting the entire code base. The other advantage is, it is easy to maintain and debug. If there is a bug to fix, it is quick way to fix the relavent module, rather than going here and there through the full source code. Node Package Manager (NPM) Overview In this lesson, we used a Third-party NPM package to send emails. You can find the sample code we used during the lecture below. Feel free to use it and do configuration chages accordingly. Also, you can refer to the official documentation (link added below) to learn how to send Emails using Gmail as Email Provider to Send Emails using NodeMailer Additional Content Even though Gmail is the fastest way to get started with sending emails, it is by no means a preferable solution unless you are using OAuth2 authentication. Gmail expects the user to be an actual user not a robot so it runs a lot of heuristics for every login attempt and blocks anything that looks suspicious to defend the user from account hijacking attempts. For example you might run into trouble if your server is in another geographical location – everything works in your dev machine but messages are blocked in production. (read more from the below link) Sending Emails Using Gmail as Provider - Official Documentation 5 Best Practices to Choosing Third-Party NPM Packages What you should consider when choosing a third-party NPM library for your project. Installing an NPM package is a straightforward task but choosing the right package is a lot harder than you think since there are over 1.3 million NPM packages out there. Therefore, you need to consider the below aspects when you are selecting a NPM package for your project. 1. Check the Package License 2. Check Contribution Frequency and Downloads 3. Look for Smaller Bundle Sizes 4. Look for the Packages Backed by Larger Developer Communities 5. Assess the Security According to a study by the University of Darmstadt, a significant percentage (up to 40%) of all packages depend on code with at least one publicly known vulnerability. Activity Read further about best practices of choosing NPM packages by visiting below URL. https://readclub.me/5-best-practices-to-choosing-third-party-npm-packages/ Resources The world's largest third-party module collection. The NPM is a great software package registry for developers. You can read more about NPM using the below resource to get an advanced understanding of NPM package usage, how to manage multiple NPM packages in a single application, and more. What is NPM and How to use NPM packages Demo Imagine you are developing a web application for a school to manage student details. Teachers and Principals can create an account using their email address and register first. Upon registration, the user gets an email confirming their new account creation. So this is our task. First, we need to send our users an email from the Node.js Server-side code. Now, to send emails with Node.js, there are multiple ways. But the easiest way is to use an NPM Module, which is already built third-party code. So as a developer, you don’t need to re-write the email sending code. If you search on Google, you will find a lot of NPM packages for sending emails. I will pick the NodeMailer package out of them because it has a huge number of downloads and a good community around it. And it gives clear guidelines to use the package as well. You also need to consider these things when choosing an NPM package.Now we picked an NPM package. How to add it to our project? I recommend you to check their guide, so it gives clear instructions. We’ll use the command npm i nodemailer to install it to our project. You need an internet connection to download this package. Next, follow the steps to use it in your code. You can refer to the Lecture Note section to refer to the code as well. Now lets create a new folder npm-mail and inside it create a new file mail.js. Now this is our node js file now we are going to create email sending functioning We need to install our third-party package. For this I am going to open my terminal and in this new terminal I am already in this folder npm-mail that I created so I am good to go. Now I am going to install node mailer package Now I am going to install Nodemailer package. So the command is npm i nodemailer. I copy this I paste it in the terminal and click enter. Now you see that it is downloaded. You see it in the explorer there is a new folder called npm_modules and inside it there is another folder called nodemailer Now it’s all about using this third party node_module in our code. For any third party node modules refer to their documentation and you can find this specification for that. For this we see this docmentation can be founded they are giving a web address. So open it In there is an example code. You can simply copy the code using the copy icon. Just copy this code and paste it in your IDE. This code contains all the functionalities and implementation required to send an email. Go through the and try to understand it there are comments added. I will do a couple of changes in the code. One thing is email sender address. So instead of this default address I will use my name and senders emailaddress And then receivers email address. You can have multiple receivers . in this example I will add receivers email address and delete one. And the subject and text you can add whatever you want. You know the email subject or the header. Then text that is the body section . you can input the email description. Then if you need you can add html type of section also under html tag . One thing to remember now.To send an email you need an email account but for testing purposes this nodemailer will provide you with a test account. So this is a test account you are not actually sending an email account Now we are going to test this. For that go to the terminal and type mail.js . Now you have beengiven a message sent and a URL When u click the URL. A webpage will and sows email has been successfully sent. It wil show you the structure and body 10/10 Async Programming Part 1: Callbacks in Node.js Overview In synchronous operations, tasks are performed one at a time, and only when one is completed, the following is unblocked. In other words, you need to wait for a task to finish to move to the next one. In asynchronous operations, on the other hand, you can move to another task before the previous one finishes. Refer to Lesson 3.1 Introduction to Asynchronous Programming o Callback function is called at the 100% completion of a specific task. o This makes Node.js highly scalable. o Refer to the below code snippet for an example of the Callback Function. Callbacks Callbacks are the most basic way of delivering an error asynchronously. It passes a callback function as a parameter to the calling function, which is later invoked when the asynchronous function completes executing. The purpose of a callback function is to check the errors before the result of the primary function is used. Activity For example, there is a notepad file containing customer data, and you want to read that one by one and process them. The below code shows how you can use a callback function to read the external text file. Resources Read more on nodejs.org Official Documentation A callback function is called at the completion of a given task. It is obvious that Node.js makes lot of use of callback functions. All of it's APIs are written in a way of callback function as well. Read the below article for more details on Callbacks in Node.js. It helps you to understand what are blocking and non-blocking functions, how to write a callback function and usage of it in detail. Callback Functions in Node.js Demo Now, to explain callback functions, let's consider an example. Suppose you want to read an external text file from Node.js server-side program. Assume, for example, there is a notepad file containing customer data, and you want to read those one by one and process them. Maybe you want to display those data, maybe you want to build a report out of those data, or for any purposes, first, you need to read this external file. Now there are two ways of coding this particular expected feature. I can categorize them into two. One is blocking another one is non-blocking way. you can write code as a blocking way or in another term non blocking way. Remember you have learned these blocking and non-blocking ways in your previous lessons. So I will explain it using an example using visual studio code now. We are going to look to how to use call back function in Node.js . In this simple example my plan is to read an external text file from Node.js code in an asynchronous way. That is why we are using call backs to make it asynchronous or non-blocking way. To read an external file I need a module. Remember we learned Node.js module in our previous lesson . In this example I am going to use file system module to read this external file. For the I declare a variable and I require a module called fs. Now I am going to use this module and read this file. Now I utilize this file as fs.readFile. readFile is an already existing implementation we are getting form this fs module. Use it and if you hover your mouse you can see the description also. This readFile asynchronously read the entire content of a file. But we need to implement our function. For that we need to declared the file name we are going to read for this example I will use a file called external.txt . The I write my function it has error and data. First thing I use if condition. if there is an error probably I will return console. Error so I can see what the error is and I will pass the error with this It there is no error then I can pass console.log and I will log the content of this external file. S o the content of the external file will be read from this function and it will assign to data and the will be printed here but the data I am converting into Tostring() so we want to see the data as string characters. Then I will add another console.log here just to add another asynchronous program here just to explain the asynchronous flow.I will put something like another node.js line after file read . Now in normal way if you forget about this asynchronous programming usually what should happen. If there is a file like this and there are no errors we should first see the content of the file. Then only we should see the output of the log. That’s the ideal happy scenario But lets execute this program and see what is the noun. Before that created an external file and add some content to it. Now lets execute this code and see the output. Interestingly the first line we see is that “program”. The program executed this line first. But ideally the program should execute the first line. That is because this is a callback function or an asynchronous programming. By using this asynchronous function callback this function conclusion will only happen after 100% completion of task. But it takes some time because external file reading is time consuming task. It will happen but your program will not wait until its conclusion. So it will execute this line first . Then after the completion of this task it output the console.log Now I hope you got a basic idea of its application. So to summarise, a callback function is called at the 100% completion of a specific task, so you execute the entire function, and then only you mark it as 100% completion. but it will not block the execution of other functions or other code lines of Node.js application, so this is another example of a callback function. We actually looked into this specific example using Visual Studio code. there are two console logs here, but the second console log appeared first before appearing the second log because this is a non-blocking call. that means the function should execute 100% to mark its completion. while it's happening, the other parts of your code can execute, so it will resume. Usually reading a text file, the external file is kind of time-consuming, so it will take some time meanwhile the rest of the code can be executed, and that is exactly why you noticed the second console log appearing first. Promises and Async/Await Overview Promises in Node.js make the applications written in Node.js more scalable and it is one of the essential coding syntax that every backend developer should be familiar with. This lesson is focused on explaining the initial usages of Promises and Async/Await usages. Promises Promises, it’s a familiar word in day to day work. We promise to delivery something. It is a commitment in another way. In Node.js, promises are the same. Node.js promises assures that a specific function will be executed. It helps asynchronous execution of the program. Activity 01 The below code shows the basic coding structure of Promises. To explain promises this example shows the very basic usage of promises. According to the above example, you can observe the fact that depending on the success or error status when resolving the promise, the output will vary. Activity 2 Promises can be used with multiple "then" blocks, which provides much cleaner coding. Check the example code below. Activity 3 The below code block shows how to throw errors within the promise. (note that you will learn more about "Error Handling in Node.js" in the next lesson. Activity 4 The syntax of declaring promises can vary. The below example shows the usage of Promise. resolve(null), and how to make the code more simplified. Activity 5 You can see the below code to understand the level of code readability that you can get by using Promises, instead of conventional callback function usage. Aync/Await To further improve Node.js code, you can use Async/Await as a wrapper to restructure asynchronous code. Activity 6 The below code snippets show how to use Async and Await keywords in Node.js Applications. Resources In this lesson, we learned the basic usage of Promises and Async/ Await in Node.js. However, the asynchronous programming concept is a much more advanced topic, which needs more coding experience to understand fully. The below resource is a good tutorial on further aspects of Asynchronous programming in Node.js. It brings some examples and code snippets to explain Promises and Async/Await. Click Here to View FreeCodeCamp Resource Click Here to View Modern Asynchronous Programming Practices with Node.js Demo Activity1 Promises, it’s a familiar word in day to day work. We promise to delivery something. It is a commitment in another way. In Node.js, promises are the same. Node.js promises assures that a specific function will be executed. It helps asynchronous execution of the program. Let me show you Node.js promises using Visual Studio code. This example shows very basic usage of promises. Here I have used a constant the name is promise and to create a promise you can use new promise keyword .And for each promise. You can have two functions, one is resolved the other one. I have used the reject function. Now if the promise is getting resolved or if it is success, then you can have one particular output. If not, if it is a failure, you can have another output. To show you the usage of promise first I have commented out the reject. That means I don't call the reject function but I use resolve function and I pass a value called success. So according to the promises if the resolve function is getting called.It did execute this (.then) block. So the success this value will be passed into this value variable and there you will get the output success. Let me run this code and explain further.So the file name is promise.js so I use node.Promise.js .Now here you can see the success is getting printed in our terminal. That means we are using the resolve function and passing this value. So this then block is going to be executed if there's an error or if you are using reject function.This promise will not execute this then block but we will go into error block and find the output. To show that I will comment out the resolve section. And let's use the reject function.And if I run this code now you can see we are getting the failure output. So in promise we have then block and catch block. So one of these blocks is going to be executed according to the function execution.You don't get both then block execution and catch block execution at prompts.This is the basic promise implementation that you can observe. Activity2 In this example only difference is you can see there are multiple then blocks. It's also possible to have. There are multiple then blocks but one single catch block . Now here also our familiar promise declaration is here. And we have two methods. Now in this case I'm only using success call. So what should happen? So in the previous example we executed the first then block. We had only one then block. But here we have multiple then blocks. Actually we have four then locks. So here if I execute this example you can see the output is showing the execution of all of these then blocks .Let me run this.Node.Promise2.js .You can see we are getting output as success One Two and three. Now we are getting this. First we are resolving this success. This is the first value so it will come into this line number four. This value will be success so we are printing that. So the output of this is going to be success .Then From this then block we are returning a value returning a string or a text value called one. So this value is going to pass into the second then block. There we are printing the value. What is the value now? From line number six? We are returning one, so that value is the one coming into second in block. So the output here is going to be One. Then we are returning another value too .These two value is going to the line number 12 this third thin block. So we are printing that value. So the value is Two .And we are returning 3.Same as above, we are printing here the previously returned value Three and we are returning 4 but we don't have any place to print that so four value is not going to be printed. And we heard a catch block but we are not executing the catch block because we are not throwing any errors here. So that is why we are getting the output as success.One Two and Three.I have added these exercises to lecture note section. So I invite you to try this.Code these examples in your computer and try to change some of these values and experiment further.And we are going one step further. Activity3 The below code block shows how to throw errors within the promise. (note that you will learn more about "Error Handling in Node.js" in the next lesson. In this example. Only thing that I have changed is I'm throwing an error. So inside one then block I'm throwing an error. So if there's an error somewhere. So we are using promises to deal with some different functionalities of the application. It can be maybe a database connection, it can be a network call .It can be a file reading example. At some point if there's an error. We have to handle these errors. So this is a simple example of throwing an error or how we are handling errors using if you are using promises. In this example if I run this Code .Here you can see the output is error occurred. How it is happening? When you are so first. Within the promise creation, it's a resolve, it's a success. The success value is coming into the first then block, but they are in the first line we are throwing an error. Because of this throw error this line other lines are not going to be executed. We are returning or throwing an error . Because of this error throwing, we will directly go into catch block. And we are firing this error. Console log and we are printing this error. What is the error value? Error value is error occurred? Because of that we are getting the output only as error occurred but other than locks are not going to be executed. Why? Because it is an error we are returning an error. That is how Right.It's worth mentioning that in the next lesson you are going to learn handling errors in node JS in detail, so I invite you to check the next lesson to get a better idea about error handling. I will show another example. Activity4 I will show another example for promises Promise4.js . In this example What I have done is I want to show you another way of.Creating promises our usual way is we are using this new promise keyword. But you can reduce number of code lines by using this way.So you are declaring promise.You can directly say promise.resolve. You are using the keyword resolve. .Now the difference is in the first approach you are allowing both functions resolve function and reject function. But here you are using resolve keyword and you can insert any value you like to have the resolve value. In this example we use success value. Likewise you can have any resolved value.In this example, let's say it's ABC. And then?Let's remove this line this moment. And if I run this example. node promise4.js here you can see.It's a result ABC printed first and then we are returning one so it is going to print it and then two and three likewise. So it's the same but you reduce number of lines by using promise.resolve. Activity5 Example1 I have one more example to show you. In this example I'm showing both ways of doing the same functionality. In this example I'm using a file read mechanism. There first You can see I am reading a file without using promises, right? We learned this file reading in callback lesson. So this is a callback, but we are not using any promises. then I'm going to show how to do the same with promises.So here we are using promises. So first let's focus into the first part here what I'm doing.To read a file you already know we need a module file system module. I'm importing it, I require it then I have two console logs, just ABC and XYZ and I have this callback, I'm reading a file, file name is customers1.Text and I'm printing the data as string format. the file is in the same folder. This is the file. We are going to read. Now Let's comment out these promises for this moment and. Let's run this. So I'm going to execute this program. It is promise5.js .OK, now you can see the output.We are getting ABC XYZ. Then we are getting the data of the file one customers1.But why we are getting ABC and XYZ first? Because this is asynchronous. This is called back. We learned how this asynchronous function works. So first we are getting ABC and the XYZ and then we are good getting this file data because it takes some time and call back actually reads this entire text document and prints. but before that. These two lines are going to be printed. It is asynchronous. Now, this is OK. But we can modify this. By including promise approach .To do it. You can declare a promise and within the promise you can read the file.Within the promise you can read the file. So in this case we are creating a new promise. It accepts both resolve and reject both functions. And within the promise we are reading the file as we did in callback function. So we have the callback function here also but inside the promise and we had a file name and if there's an error we are rejecting. If there's no error, we are resolving.Right, so this is promise.Then if there is no any error.Yeah resolving we are getting the data out of this file. we have then block and catch block. This is the nature of promises, right? So if this is a result, if this is a success. We can get the output of the data. So since this is this function returning a promise, this function returns a promise. To access promise you need (.then) and you assign this data Into a variable data. then you print out it in string format. If there's an error, you log the error. Now let's execute this. Now in this example you can see. We are getting the same output. Actually I removed the console.logs and then you can see the file output file data is getting printed. Now when you're looking at this code you will see. Now we have written a lot of code lines to do this activity. So if I show you the both approaches. Now without promises we just need three lines to get the output. But with promises we have written multiple lines of code, right? We have written multiple lines of code. You might think this is an overhead. Why are we writing this much of lines?It's a reasonable argument.But by using promises, actually it allows you to structure your code in much more readable way. It is encouraged to use promises in this kind of work. Example 2 To emphasize his further. I will show another complicated example. Let me clear the terminal. Now imagine. You have multiple text documents to read. We have customer1 file we have customer2 file and customer3 file. We have three files. if you have multiple files like that.If you're using without promises approach, this is the way that you have to write your code. Now, it actually creates lot of unreadable code. Imagine if there are like 25 or 30 files. So you have to write your code like this first you are reading the file. Within that function you are reading the other file and the third one likewise. You are moving your code to your right hand side further and further. So this is not a good code writing style. This is not encouraged. There can be lot of readable issues. And also there are some other reasons, also some advanced reasons. Main thing is the readability. It's very hard to read, so because of that it is not recommended. But if you're using promises. It is very readable. See this is how you do the same job by using promises. The interesting Thing here is there's an option called promised all and you can pass all the text files into an as an array to their promise so it is one shot and you can execute you can read them. So that's One of the advantage of using promises. So in this here actually I'm using a util function called promisify so it makes our work a bit more easy as well. First, what I have done is let's get rid of without promises . At minimum. So what we have done is to read file we need fs module, file system module and I have imported another module called util . So util module supports the need of node.js internal APIs, so we are using another internal module .Call it util.By using util. You can directly read file and you can make it a promise very easy. You don't need to create promise like this. You can use this approach also but without using new promise keyword. That this is an another approach you can directly use utili.promisify and you can insert this other function, so file system function as a promise directly. Now we have this promise read variable. So using that you can have all the files. you write promised all and inside an array. You put all the file names you need. If you have 10 files you can have that. We can expand this file further.So let's say you have customer4.txt and likewise you can have any number of files, as much as you want. So your code is still readable, right? It is not messy so it is very easy to understand.And then if everything goes correctly if it is resolving then you can have the outputs as you want. So here since we are adding array of files customer1, customer2, customer3.Inside then what we are doing is first we create a constant. We have data1, data2 and data3 and then you can print them one by one. So data1 output, data2 output, data3 output .If there's an error. The error will be logged. So let me execute this code.This is promise7.js .Here you can see the output is coming. Group1 , group2 and group3 . We are printing them with much more readable way. So this is good approach to write your code with promises. So I took the file reading example for this example, but promises can be used to many other reasons. For an example, you can even use promises too. Get some data from a database. You can write code to retrieve data from an API. So if you have multiple APIs to call or if you have multiple data points to channel, you can use the same. You can use promise all and do it. Aync/Await To further improve Node.js code, you can use Async/Await as a wrapper to restructure asynchronous code. Activity 6 Example1 The below code snippets show how to use Async and Await keywords in Node.js Applications. It's a special syntax to work with promises. It is a more comfortable and readable way of writing code. So in async and await. There's something very important for you to keep in your mind. If you're using await keyword, you have to place this await keyword inside an async function. If you use a web keyword in general function, you will get an error. I will explain the usage of async and debate using Visual Studio Code.OK, in this example I'm going to show the usage of async await. Here I am going to retrieve some data from an API. This is an API.If I hold this API, I'm getting some data from this endpoint .Now I'm going to fetch the data from this endpoint and I'm going to show it in my application. So you know, I think it's kind of a wrapper. That we are using on top of promises, so it makes our code much more readable, much cleaner and it's a better practice. So in this example I'm going to retrieve data from this endpoint and using this wrapper async await I'm going to display that .Right So first this is without using async and await this code. Then I'm going to add async await and show you how easy it is to do the same using async and await and its readability. First.To fetch this data from this endpoint I'm using a third party module NPM package called node-fetch. So if you go to NPM Site there if you search node-fetch you can have it and to install. You can refer the guideline. So by looking at this you can use this come on and download it. There are some version mismatches specific to this north face, so I prefer node fetch version two. So I'm using this particular command to download it. When you have this node fetch package, you can install it and then you have to import it. So to your JavaScript file you are familiar you learned NPM lesson, you can use constant page or whatever variable you need and then use require keyword and include node fetch so the package will be imported. Then I have created a constant called link and I added my API endpoint. If you're trying out you can use the same URL or you can find any other API URL that you like to use and edit. Now then. Actually we are using the fetch so this fetch this import we imported this fetch module so I can use this fetch keyword and I'm adding this link.So according to the definition what this fetch command is doing is it's actually fetching or loading data from outside the world and it's giving the data as a promise. So this is actually a promise. So because of that you can use then keyword. We have the then keyword and if this promise is success or If it is resolving, we can get the output. Usually this endpoint sense data in JSON format because of that I'm adding this (response.Json) to get the output in Json. So we should see we should get the output here. we have then data and we are printing the data .So we should get the output here. If there's an error, we will get the error logged under catch bllock . Let's run this code and see what the output is. OK, so now I'm going to run my code. Hit Enter and here you can see we are getting the output. There are two Jason objects, 2 Jason objects. We are getting this from our back end actual endpoint. So we have two objects coming and it is getting printed. Why? Because they are getting it from this fetch promise and since this is a success we are getting the output as Json object and we are printing it. So if there's an error, what will happen? So for the moment maybe I'll change this URL to bit so incorrect one. Now the URL is incorrect, so probably we should not get the data from this link when you're fetching. So let's see what is going to happen. Now in this case you can see if I run this we are getting an error. Error is getting painted because we are firing this catch block and we are recording the error here. So we are getting the error as system not found this error and stacks stack trace of this error as well. So it says fetch error request to this URL is failed reason get this address info is not found and it looks there. So as developers. It is easy for us to. See what is the error and fix it. Now the output is correct. We are getting Output.Now in this example still we are not using async await but we are using promises. We are using promises. So this is a promise. Actually this fetch is actually a third party library. This phase actually produces a promise if returns a promise so that's why we use then key block and catch block. Example2 Now If you're using async and await, we can further expand this example. Now in this example the same functionality but we are using async and await. So still we need our third party module node-fetch and then this is the interesting part. Now to declare async await I told you to include await. This await should be within async function. So I have created an async function here. So the constant name is loadDataFunction you can give any name and here using async keyword I'm creating asynchronous function.So this particular function is asynchronous function or async function. So in that function I am using this link our usual server side URL. And then?This try catch might be a new thing to you.This is how we handle errors in nodeJS in much more cleaner way. So you will learn this trick catcher in upcoming lessons But to give you a brief idea, all the function activities which can occur which can cause some errors, you can put them inside try block inside a try block. So all the things within try block will be executed and if there's an error. This catch this particular catch block will be executed just like you know in promises we have this then and catch these blocks. The same in this try catch block. So all the functionalities within try block and if there's an error those will be handled in catch block. Now what we are doing here? We are getting the response. We are using this fetch module and just like in previous example we use fetch inside we pass the link. We are doing the same here but in await manner. Now what is await your program will wait until this fetching happens so it await it will wait. It will hold here and get the response. And then we convert the response into Json. So it will wait until this happens. Then it will return the data. If there is qn error happening in one of these points, it will log the error. Now to get the output you have to call the function. This is a function function name loadDataFunction but this function still returns a promise. Why? This is asynchronous function and we are using await keyword but we need this asynchronous and we are using this await keyword as a wrapper or it's kind of a decorator that we use on top of a function? Make it more readable. Now this is a normal promise function, but we wrap it. We use async and await words to make it look nicer but still this function returns a promise. It threatens the promise. So how to access the promise? Or how to read data from a promise? It's our usual way. You write the promise. This is the promise now and then. You get the data variable and you print it. Now this is same now loadDataFunction .It's the same if you see here. This fetch and this part it is actually something like our loadDataFunction(). It's the same, but the interesting thing here is we use it as an asynchronous function using await, so we definitely get the output. We resolve the promise before proceeding further. now this is an another example that you can use to understand the usage of async and await. I encourage you to try this example in your computer and also make sure to read further because async, await and promises can be. I encourage you to start small and then you can try to improve your knowledge by doing a lot of hands on activities. Error Handling Overview In computer programming when we execute a set of code, if something goes wrong or if there is an error in the code segment, we can use error handling to capture it and take necessary actions to handle the situation. Errors are an unavoidable part of a software developer’s life. While building a software application, we need to manage errors effectively to: o Improve the end-user experience, i.e., providing correct information and not the generic message “Unable to fulfill the request”. o Develop a robust codebase, which consists of powerful and strong code segments. o Reduce development time by finding bugs efficiently. o It will avoid abruptly stopping a program when an interruption happens. Error Handling As software developers we want to make fixing bugs (errors in coding) less painful. Error handling helps us to write cleaner code. It also centralizes all errors and enables alerting and notifications, so we know when and how our code breaks. Different types of errors There are two types of errors, programmer and operational. The main difference between these two types of errors is the root cause. Operational errors epresent runtime problems. These errors are expected in the Node.js runtime and should be dealt with in a proper way. In reality, operational errors can occur frequently due to external factors. Here we have some examples for operational errors. o Unable to connect server/database o Request timeout o Invalid input from the user o System is out of memory o Socket hang-up o File not found o 500 response from a server (i.e., the server encountered an unexpected condition that prevented it from fulfilling the request.) Programmer errors are what we call bugs. They represent issues in the code itself. These are the errors caused by the programmer’s mistakes while writing a program. The only way to correct them is to fix the codebase. Here are some of the common programmer errors: o Array index out of bounds (example: if we try to access the seventh element of an array when only six are available). o Syntax errors (example: failing to close the curly braces while defining a JavaScript function). o Reference errors (like accessing a function or variables that are not defined). o Deprecation errors and warnings (such as calling an asynchronous function without a callback). o Failing to handle operational errors. Handling Errors To handle the errors effectively, we need to understand the different types of error handling techniques that are available. try…catch blocks, Callbacks and Promises are some fundamental strategies to handle errors in Node.js. try…catch block In the try…catch method, the try block surrounds the code where the error can occur. In other words, we wrap the code for which we want to check errors. try-block, can contain one or more statements. double curly braces {} must always be used, even for single statements. The catch block handles exceptions in the try block. It contains statements that specify what to do if an exception is thrown in the try block. If any statement within the try-block throws an exception, control is immediately shifted to the catchblock. If no exception is thrown in the try-block, the catch-block is skipped. Following Figure 01 shows the syntax of the try…catch block. Figure 01: syntax of the try…catch block try_statements are the statements to be executed. catch_statements are the statements that are executed if an exception is thrown in the try-block. exception_var is an optional identifier to hold an exception object for the associated catch-block. Callbacks Callbacks are the most basic way of delivering an error asynchronously. It passes a callback function as a parameter to the calling function, which is later invoked when the asynchronous function completes executing. The purpose of a callback function is to check the errors before the result of the primary function is used. Following Figure 02 shows the syntax for a callback function. Figure 02: syntax for a callback function The first argument is for an error, and the second is for the result. In case of an error, the first attribute will contain the error, and the second attribute will be undefined and vice versa. Promises A promise is an object that represents a future value. Promises allow us to model asynchronous code like synchronous code by using the Promise API. In the function, we will return a promise, which is a wrapper to our primary logic. We pass two arguments while defining the Promise object resolve and reject. Resolve is used to resolve promises and provide results and Reject is used to report/throw errors. Following Figure 03 shows the syntax for the promise function. Figure 03: syntax for the promise function It’s also worth noting that a promise usually comes in a chain, where one action executes, then another and so on. Promises handle errors quite elegantly and will catch any errors that preceded it in the chain. Using promises you can chain different operations, and handle errors at the end and it is usually preferred compared to callbacks. As an example (Figure 04), if we have a code segment like following, how do we know where the error occurred? we don't really know. Figure 04: promises example But we can handle errors in each of the functions we call according to this example, doSomething 1,2 or 3. Inside the error handler, it will throw a new error, that's going to call the outside catch handler. Then the above code segment can be modified as you can see below (Figure 05). Figure 05: modified code segment To be able to handle errors locally without handling them in the function we call, we can break the chain. We can create a function in each then() and process the exception (Figure 06). Figure 06: create a function in each then() Other techniques used to handle errors There are some other techniques that we can use to handle errors. We can use the EventEmitter class from the events module to report errors in complex scenarios lengthy async operations that can produce numerous failures. We can continuously emit the errors caused and listen to them using an emitter. Sometimes, errors can be caused by the external system for valid requests. At this point, the service might be back in a few seconds, and reporting an error might not be the ideal thing to do, so you retry the operation. For example, while fetching some coordinates using an API, you get the error 503, service not available, which is caused due to overload or a network failure. While receiving the wrong input from the client, retrying doesn’t make sense because we might get the same result upon reprocessing the incorrect information. In such cases, the most straightforward way is to finish the rest of the processing and report it to the client. In case of unrecoverable errors, crashing the program is the best option. For example, an error is caused due to accessing a file without permission; there is nothing you can do except for crashing the system and letting the sysadmin provide the access. Crashing is also the most practical way to deal with programmer errors to recover the system. Following code segment is writing a file named 'test.txt' and the errors are handled using the try...catch block. Modify the code to display the error message as "Unable to write the test file" when it throws an exception in the try block. HINT: Type 'node index.js' in the terminal and press Enter to execute the code. Activity 2 Correct the error in the following code segment (HINT: there is an error with the arguments that passes to the callback fuction). Modify the code to display the error message as "Unable to write the test file" when it throws an exception. Resources Error Handling in NodeJs Demo Try…catch block This is a simple code that reads a text file. There is a text file named ‘node.txt’ and it is read and displayed in the console inside the try block. Further it will display “This is the start of the try block” at the beginning of the try block and “This is the end of the try block” will display at the end of the try block. When reading the file, if any error occurs, it will be handled by the catch block. Here it will display the errors that captured by the exception object. It can be changed to a custom error message as well as you can see here. When we execute the code, it will run smoothly as you can see here as there isn’t any errors caught. But when I change the name of the file to a different name, then there will be an error which is captured by the try…catch block. Here I will change the error message we want to display. Instead of displaying the error message I have given a text to display as error message. When we execute the code the code you can see that it will display that incorrect file name. Callbacks This is similar to the previous example which I showed you earlier. Here also I am reading a file named ‘node.txt’ and the error is handled using callback function. If there is an error like wrong file name, then it will be handled using the callback function as you can see here. promise Suppose that you want to perform the following asynchronous operations in sequence: First, get the user from the database. Second, get the services of the selected user. Third, calculate the service cost from the user’s services. We have handled the errors locally as you can see here. After executing the code it will smoothly run as there are no errors. The following functions illustrate the three asynchronous operations. Then, the following uses the promises to serialize the sequences. To handle errors locally, we can modify the code as you can see here. 8/10 Server Security and challenges Introduction to web server security Overview for Security Security is about protecting valuable assets from threats. It's a part of our everyday life. We are familiar with different security measurements to secure our homes, buildings, and even the country. Similarly, computer systems also require security to protect assets. The assets include data, software, and hardware. Who is an Attacker? An attacker harms a computer system and its assets by disrupting its services or stealing or destroying assets. A simple analogy to understand this is thieves breaking into a house to steal money or jewelry. These attackers could be either external or internal to the system. For instance, we know that a family member in the house also could steal assets if they have malicious intentions. Who is a Benign User? In the context of security, we call the non-harmful users of a system benign users. A simple analogy to understand this is relatives with good intentions who visit a house. They would not steal or destroy the assets in the house. Figure 1 Benign User vs Attacker Security Goals: There are three main goals for computer security, i.e., confidentiality, integrity, and availability. Confidentiality: Only authorized users can access sensitive data and services. Integrity: The data should not be changed by unauthorized users. Availability: The data and services should be accessible to authorized users whenever needed. Security of the Web Server The security goals above apply to web-based systems too, where the clients communicate with a web server for data and services. The security of a web-based system is a broader topic. So, let's define the boundaries by identifying the threat model for webserver security. Threat Model: We assume the web server is trusted since we are the developers. However, visitors to the web server could be a threat, since both benign and malicious users can visit it. The webserver stores sensitive information about users and applications. The malicious users may try to exploit vulnerabilities in the webserver, and we need to protect the web server from them. Furthermore, the communication channel between the client (visitor) and the server (web server) also cannot be trusted. The network attackers may be eavesdropping on the channel. So, we need to protect the web server against network attackers too. Resources Security Goals What is Web Security? What is Web Security? – Website Security Tools 66.67/100 Secure coding Overview A webserver is a part of a web-based system. The security of the webserver is affected by how the other components and users of the system behave. The server-side web developers develop the software (web application) that runs and utilizes web server resources. However, the developers may introduce bugs and logic flaws during the design and development stages. These bugs and logic flaws could be vulnerabilities that can be exploited by the attackers to gain access to sensitive data and disrupt the services of the webserver. Web-based System: This includes the web server and clients that communicate with the web server over the Internet. The internet is a public network, so the web applications hosted on a web server can be accessible to anyone connected to the internet. That includes both benign users and malicious users. Fgure 1 below shows an abstract view of a web-based system. Benign Users: A user who accesses the system for its data and services by following the standard behavior. They do not have any malicious intentions that harm the system. Malicious Users: A user who exploits the vulnerabilities of the system to gain unauthorized access to data and services. Figure 1: An abstract view of a web-based system Secure Coding Secure coding is the practice of writing secure codes for web application development. Secure coding can remove bugs and logic flaws of the software that could lead to vulnerabilities that can be exploited by malicious users. The industry follows the standards and best practices provided by the OWASP project to achieve secure coding. Hence, it is recommended for every developer to learn them. Knowing the Web Security Vulnerabilities The OWASP Top 10 provides a list of the 10 most critical web security vulnerabilities. The OWASP community keeps this documentation up to date. The OWASP Top 10 -2021 guide can be found at https://owasp.org/Top10/. As you can see in the below figure, the priority of a vulnerability could change due to the dynamic and challenging nature of security. Hence, the developers should be referring to the latest documentation. Figure 2: OWASP Top 10 Vulnerabilities (Source: https://owasp.org/Top10/) How to Write Secure Coding? The OWASP Top 10 guide provides comprehensive information on each vulnerability, including reasons, how to prevent them, and attack scenarios. However, the actual implementations depend on the programming language. Therefore, the web developers can refer to SonarSource (https://rules.sonarsource.com/), to learn language-specific secure coding fixes. Example In the below, we discuss one of the examples stated in the SonarSource how secure coding can avoid cross-site scripting attacks (Source: https://rules.sonarsource.com/javascript/type/Vulnerability/RSPEC-5131). Vulnerable JavaScript Code: A JavaScript code snippet that is vulnerable to Cross-site Scripting (XSS) Attacks: function (req, res) { const tainted = req.query.name; res.send(tainted); // Noncompliant }; Here, this function takes an HTTP request as input. This HTTP request includes URL parameters (accessed by req.query.name). The function also has another input which refers to the HTTP response that is relevant to the request. Here, the developer has directly passed the values in the URL parameters in the HTTP response. As explained in the lecture video, these URL parameters may include malicious scripts. Therefore, this code snippet is vulnerable to cross-site scripting attacks. Secure JavaScript Code: JavaScript Implementation of Secure Coding to Avoid Cross-site Scripting Attacks: import sanitizeHtml from "sanitize-html"; function (req, res) { const tainted = req.query.name; res.send(sanitizeHtml(tainted)); // compliant }; In this code, the developer has used the sanitizeHTML function provided by the "sanitize-html" library, to sanitize the user inputs in the HTTP request. This function sanitizes and encodes all HTML content in user input, hence preventing the XSS attack. Activity Find the answers for the following by going through the OWASP Top 10 and SonarSource (refer to the resource links). o what is a "SQL Injection" attack, o the vulnerabilities that cause a SQL Injection attack o How to prevent SQL Injection attacks? o Give an example SQL Injection vulnerable code snippet, and how to secure the code? Resources OWASP Top 10 - 2021 SonarSource static code analysis 10/10 HTTP Basic Authentication Overview The client accesses the resources on the web server over the HTTP protocol. The web server provides access to its resources through an API (Application Programming Interface). Since the webserver hosts the resources over the internet, any client can send HTTP requests to the API endpoints to access the resources. That includes malicious users. Therefore, the webserver should restrict who can access its web resources. To achieve this the webserver should be able to verify the identity of the clients who send requests. This process is called authentication. There are different ways a web server can authenticate a client who accesses API endpoints. The simplest method is to use the “HTTP Basic Authentication”. HTTP Basic Authentication Basic Authentication is a standard authentication scheme (RFC 2617) built into the HTTP protocol. The web browsers by default support basic authentication. Therefore, additional implementation is not required on the client-side. This scheme is also known as a challenge-response scheme. As shown in Figure 1, the server challenges, and then the client responds to the challenge. In simple terms, basic authentication requests authentication information from a client, if a client sends an unauthorized HTTP request. So, for the client to get access to the web resources, the client should prove its identity to the web server by sending credentials. Now, let’s look at how this is implemented. Example Unauthenticated Client Request: GET /HTTP /1.1 Host: example.com Figure 1: The challenge-response shceme Server's Challenge When the server receives an HTTP request from a client without any authentication information, the server sends the challenge request (shown in Figure 2). Example Challenge by Server: HTTP /1.1 401 WWW-Authenticate: Basic realm=”MyApp” The status code of the challenge request is 401. It informs the client that the request is unauthorized. Further, the challenge request includes the header “WWW-Authenticate” that specifies the authentication scheme as “Basic” and the protected scope which is a string assigned by the server for a URI. Figure 2: The Server's Challenge Client's Response When the browser receives the challenge from the server specifying the 401 status code, the browser displays a prompt window requesting the user to enter credentials. Here, it assumes that the client or the user who operates the client obtained the credentials in some way. Then the user enters the credentials, which include a username and a password. (Note: Although user credentials are used here basic authentication is not used for authenticating users.). After that, the browser constructs the client response (shown in Figure 3) by generating a bse64 string of the credentials. Example Response by Client: GET /HTTP /1.1 Host: example.com Authorization: Basic QW1hbGk6bXlzZWNyZXQ The header field “Authorization” in the client’s response specifies the authentication scheme as Basic and then the credentials in the Base64 format. Figure 3: The Client's Response How to Generate Base64 String When the user enters the credentials, the browser concatenates the username and password by separating them using a colon character. This is called a user-pass string. Then encode the resulting string using Base64. This is performed to ensure that the authentication information transmitted over the HTTP protocol has compatible characters. Base64(username:password) Example Base64 String: Base64("Amali":"mysecret") = QW1hbGk6bXlzZWNyZXQ Validating Authentication Information: When the client sends the base64 string, the server decode it and extract the username and password. Then validate them by comparing username and password stored in the database. If the validation is succesful, the server responds with a 200 status code. Limitaitons of HTTP Basic Authentication o This scheme does not ensure the confidentiality of the credentials since the base64 is an easily reversible encoding mechansim. o The base64 string is transmitted over HTTP as a plaintext. Therefore, an attacker who listens on the channel can easily decode it to obtain the credentials. Solution: Use basic authenticaiton over HTTPS protocol. Activity o Find out other approaches that can authenticate a client's access to an API endpoint. Resources RFC 7617: The 'Basic' HTTP Authentication Scheme The Difference Between HTTP Auth, API Keys, and OAuth MDN Documentation (Basic Authentication) HTTPS and Secure Communication Overview A client and a server connected to the same network can communicate over the HTTP protocol. A network is a set of computers or hosts connected through a wired or wireless medium. This network not only has the client and the server but other hosts. If the network is public, the network allows any host to connect to the network. Then there is a high chance that there are hosts that are controlled by malicious users or a malicious program connected to this network. These malicious hosts are considered network attackers. Therefore, the channel between the client and server over the internet is insecure. The network attackers can listen to the conversation between the benign hosts. There are two main types of network attackers. Passive Attacker: Eavesdrops on the conversation between the benign hosts. They read the messages but do not change the content. However, they can steal sensitive information from the messages. Active Attacker: These attackers modify or remove the content of the messages in addition to eavesdropping. Figure 1: Threat to client-server communication Problem with HTTP The HTTP protocol is an application-layer communication protocol (refer to the OSI model). It is responsible for the communication between the client application and the server application. The problem with HTTP is that it transmits the messages in plaintext. Then, if a network attacker listens to the conversation between the client and the server, he can see and understands the content of the message. This problem can be solved with HTTPS Plaintext: The messages are in cleartext. HTTPS HTTPS stands for Hypertext Transfer Protocol Secure. It is the HTTP protocol with the Transport Layer Security (TLS). The predecessor of TLS is the Secure Socket Layer (SSL). TLS is a cryptographic protocol, which ensures the security of the messages exchanged between two hosts over the internet. It technically builds a secure channel between a client and server for communication. HTTPS is essential if your web application process sensitve data such as credit card details and login credentials. Secure Channel: A secure channel should ensure the confidentiality and integrity of the messages and authenticate the communication parties. These three properties are key goals of cryptography. Cryptography Three key goals of cryptography o Confidentiality: The message content is only known to the intended parties. o Integrity: The message content is not altered during the transmission o Authentication: The communication parties can verify the identity of each other. Figure 2: Security goals: confidentiality, integrity, and authentication Trust Models: o Symmetric trust model: The sender and the receiver both use the same secret key for encryption and decryption. The secret key is shared between the sender and receiver before using some mechanism. o Asymmetric trust model: The sender and the receiver both have a key pair. The key pair includes a public key and a private key. the public key is known to everyone including the attacker. The private key is only known to the owner. So, an attacker won't be able to own it. This key pair is generated by each party themselves. How HTTPS Achieves Confidentiality To ensure the confidentiality of the message, it should not be understandable by the network attacker. To achieve this cryptography provides encryption and decryption algorithms to convert the plaintext message into a ciphertext, which is not understandable by anyone without the correct keys. HTTPS uses the symmetric trust model to achieve confidentiality. Ciphertext: The secret code resulted by encrypting a plaintext. Encryption To encrypt the message the sender (client or server) uses the shared secret key. After applying the encryption algorithm for the plaintext using the secret key, the result is the ciphertext. This ciphertext is transmitted to the receiver (client or server) over the internet. Figure 3: An example of encryption using the symmetric trust model Decryption To decrypt the ciphertext the receiver uses the same secret key. After applying the decryption algorithm for the ciphertext using the secret key, the result is the plaintext. Although an attacker receives the ciphertext, he won't be able to decrypt the message, since he does not know the secret key. Figure 4: An example of decryption using the symmetric trust model How to Securely Exchange the Keys To securely exchange the secret key used for encrypting the messages, HTTPS uses the asymmetric trust model. If the client generates the secret key, the client encrypts the secret key using the public key of the server. Then, transmits the encrypted secret key to the server. To decrypt and recover the secret key, the server uses its private key. However, there are other ways to exchange the secret key without transmitting it over the internet. One approaches: Diffie–Hellman cryptographic algorithm Server Authentication A network attacker who impersonates a benign server can generate a pair of public-private keys. Then the attacker can send the public key to a client to establish a secure connection. Therefore, a client should verify the identity of a server before establishing a connection. To prove the identity, the server should provide some authentication information. The authentication information used by HTTPS to achieve server authentication is a digital certificate. Digital Certificate: This is also called an SSL/TLS Certificate. It is a certificate provided by a third-party organization to prove that the owner of the public key of a server is the particular server. These thirdparty organizations are also called certificate authorities (CA), e.g., Verisign and DigiCert. They are wellknown and trusted organizations. Validating the Digital Certificate: To validate the authenticity of the digital certificate, the client checks the issuer of the certificate, against a list of known certificate authorities. Generally, web browsers trust a list of CAs by default. If the CA is trusted, then the client can proceed with communication. Otherwise, the client or the web browser shows an error message as shown in Figure.5 Figure 5: Privacy error on the web browser Activity o Find the list of trusted root certification authorities by your web browser. Resources RFC 5246: The Transport Layer Security (TLS) Protocol What Is a Certificate Authority? Certification Authorities Explained Guided project Part1 Hi everyone. Welcome to the guided project for NodeJS. the objective of this guided project is to give you a better understanding and hands-on experience in developing a NodeJS application. Before starting the development, you need to understand what is NodeJS. NodeJS is a server-side JavaScript runtime environment that executes JavaScript code. What is NPM? NPM is its package manager that makes it easier to publish and shareNodeJS source code libraries. The default package manager for NodeJS is NPM. TheNPM package manager simplifies library installation, updating, and uninstallation. What is express? Express is a server web application framework that NodeJS uses to build web apps. With express, you can use different front-end frameworks to create a user interface? Once we have installed node JS, we can build our first web server. For that, we need to create a file name app.js .You can see the example below. Let's try to write an app.js file and see the outcome. OK, let's try to write an app.js file. You can use your Visual Studio code to write the same. Let's try it out. Click on the file and go to a new file. You can see that there's a new file appearing. What you can do is you can go to file and then go to save as give a file name. Let me give a file name for that app.js and then select file type as all files. Let me select a folder for that I'm going to create a folder and then I'm going to save this file inside the same link. what do we need to write? We need to initiate the required libraries. We need to declare required variables. Now let's try out to initiate a few requirements. We need to have a variable const HTTP and then we are going to tell that we need to have HTTP here. Then we need to give a hostname to our application, const hostname and the name can be given within a single quotation. I'm going to give a particular IP address for that. Which is the IP address for Localhost 127.0.0.1. And I'm going to terminate this statement. We also need to have a particular port to run this application. We write a port for that. We have defined a constant port and let's say the port that you are planning to run this application is 8080 in this time. Now is the time for us to write the code statement to create a server here. What we are going to do here? We are going to create an HTTP server. Let's create that. Now we need to write http.createServer, and we have to include these parameters. We are going to include request parameters and responses. We're going to open a curly bracket and also we need to terminate the entire statement. Now let's look at what are the response codes that you are going to assign? We can assign a status code for that 200 and also we can assign a header. So, you can define headers as required, but here at this time we are going to declare a Content type for that. How to write the header? You have to have the single quotation and then content type and the value that you're going to assign for the content type "text/plain". You are going to terminate the statement. Not only that we do have sort of a message, that we can see as a response. Lets defined the message. res.end and you have to put a single quotation. We gonna write that this is a test application. We are going to terminate the same and then format the code a bit. Now, we have to tell that the particular server has to listen to the port that we have defined. And also we can include sort of a console log for the same. We are going to assign the return from the same to a constant which is the server right now the return given by this creating server will be assigned to the server. We can use the same variable server.listen. Then we can assign the port. Include the port here and the host name variable that we defined. Then we can terminate the statement. We can write console.log and then we can provide a particular message that you are planning to do. Let's say like "server runs at http://${hostname}", particular variable name then we have hostname. Also, we can put the port. OK this is how we put the port, the variable that we defined and the closing statement in this manner. Now let's try to run this application. Right, You have to go to console and run this. So, make sure that you are in the correct directory that you have saved the file. So, let me get the exact location and go to that so that we can run this. I think we have to go for "..Guided Project\Practical". We are going to run the app.js here. Now that indicates we have executed the app.js, which helps us tor run a server under this particular IP address Part3 Let's try to define the database.js file, like what we discussed in the previous video. Let's start. We need to define a variable, but we have to indicate that this variable is for “sqlite3”. That is the “sqlite” version that we are going to use for this practice. we have to include the required library as well. That is a sqlite3. Also, we had to indicate this particular version of the verbose. And I'm going to define a constant to track the DBSOURCE that is going to use in the future. For that, I'm going to assign “db.sqlite” to the skill light as well. I think this is quite simple for you to understand. Now let's try to connect to this sqLite3 database and we'll use the data source to create a table and work towards writing an application. Right. I'm defining db and I'm going to create a new instance of sqlite3. That is going to be a database. And I'm going to pass the defined constant DBSOURCE . Also, I'm going to handle errors. Let's say err. Then we need to open the brackets to write the required statements. Now, in this case, for any reason, if we are unable to connect to the database, there can be an error that is generating or is a situation that we cannot control. For that, we need to handle the errors. Let's say if it returns an error, we should provide a proper message to the console. Saying that console.error. Then particular error message. Also, the generated error can be drawn here. If it is not the case, that means our else case is going to help us with the logic region. To indicate that the application has connected to the SQLite db. And I'm not going to indicate it as an error. I'm going to declare a console.log and indicate that connected to the SQLite Database. All right. Then what do we have to do? We already have defined this db. We are going to use that. Now, the time that you are going to run the data definition for what we need. To save time, I'll be directly taking the written statement for the same and we’ll discuss it further. So I have taken the written data definition or in simple terms, create a table statement. Let me explain for you to understand this in a simple manner. We have stated that we need to create a table. The table name is going to be products and we are going to have an ID to uniquely identify a particular product that is added to the product table. Now, what is an integer here? The data type of this ID is going to be an integer, or in simple terms, that is going to be a whole number. We already have defined that this is going to be the primary key for this table. If you don't remember, what is the primary key? The primary key is a field of a data table that we can use to uniquely identify a particular record or a tuple. And we have defined that the key has to be autoincremented. What does that mean? Whenever a particular user who is going to add a record to this table, it is going to look for the last record that has been added to the table and increment the ID of the last record by one and set the new ID for the new record. Let's move to the next parameter or to the next column which is the product name. You might be able to understand that when we add products to the table, we need to have a product name to identify the product. But the data type is going to be text. This is the data type that we can use in sqlite databases to keep a set of characters together. So the product name should consist of characters where it is going to give a meaningful name. So we have defined the product name and the data type is going to be text. Then we have a particular description at it and the data type is going to be text again. This is the description of the product. We have a category to identify the product. In simple terms what classification the product belongs to. The data type is going to be text here and we do have a product brand. The data type of the brand is also going to be text. We are going to define an expiry date for a particular product. The data type is going to be text. We do have a manufacture date. Again, the data type is going to be text here. We do have a batch number, unit price, quantity, and create a date as well. For that, we define integers, assuming that batch number, unit price, and quantities are going to be an integer value. In simple terms, whole numbers. We have to create a date to indicate the date that the record has been created. Again, that is the text for any reason. If an error being generated, we are planning to handle it like what we discussed. Now, if we find any errors that have to be handled, as discussed else, we are going to insert data into the product table. How are we going to enter the data there? We have to write an insert statement and insert it into products with all of the column names to include data. We have the product name, description, category, brand, expiry date, manufacture, date, and everything together. We are going to assign that to a variable that is insert. Then at the runtime, we can execute this query and insert this dataset that is defined here. For the product name, there is a given product name for that. But you can see that there is no ID parameter that is going to be auto-assigned by the database at runtime. Then we do have a product description. We do have product categories, right? and we do have a brand write and manufacture date and all the other data that is required to be inserted. Let's move and try to write the API that is required to insert data to this table that we have created. Part4 Let's try to write an API to add products into a database. Later in time we can get the data and see whether the added data is available or not. Let’s start. We have already defined a variable. You might remember that. It is called the Post method. It is appropriate to add data to a database and we have to give a URL pattern. I'm going to give a pattern like api/products. So this is going to be the URL pattern that you are going to access the API through the URL. I'm going to put a Comma “,” and then I have to define request and I have to define the response and keeping this as well. Next, I'm going to open curly bracket and I'm going to terminate the entire code base. So that I can conclude it. Fine, now I have the method that is specifically prepared to save data in a database table. Let's try to implement the required stuff or required code statements to get this data. If you carefully look at we have a parameter to get request data. This is very important here. Let's try to use this parameter to get the data when a particular user sends data to the same API. In simple terms, the data being sent to the API is called data in rest. Let's try to get this data and store it in a local variable and then save it in a database table. Let’s start. Fine. Now, since we need to keep set of data and going to create a constant. And then I'm planning some parameters to get. Now, my first parameter is going to be a product name. I’m going to put a comma, and then I'm going to get a description. Then I need to have a category. Then I need to have a brand for that. And then an expire date. And also, I need to have manufacture date. I need to have a batch number to refer and a unit price. And the quantity. And a created date for the record. Now, what we have to do is we have to get this set of parameters from the request. Right now, you can see that a lot of errors which were appearing vanish suddenly. So, I'm going to get this request data or body that it comes from the request and then I'm going to divide it and assign those parameters to these particular variables inside the constant. That is very simple. Then we have to focus on writing a SQL statement. For that what we can do. We have to create a variable. The statement is going to be little longer. What I'm going to do is I have a prepared insert into statement. I'm going to put it here to make our life easier. All right. Now, you can see that there are a lot of parameters that we are focusing here like what we define. So, we are going to insert data into a table called products. We are going to insert product name, description, category, brand, expired date, manufactured date, batch number, unit price, quantity, and created date. Everyone wonder what is value? Values is a statement that we have in a typical SQL statement. But what is the important thing to understand in this statement? The question marks. These question marks are going to be replaced by actual values in runtime. Let's try to define it further. We need to define parameters that we need to have or to support these variables. Now I'm going to define another variable called “params”. They are going to keep these particular variables, which we just discussed. Let me put those variables at once where it's going to save our time. Yes, we do have set parameters, something similar to what we discuss inside the constant. We have product name, description, category, brand, expired date, manufactured date and other things as well. Right. We have every parameter that is required to save inside the database. Let's move ahead. Then what to do? Yes. Once we have created the SQL statement and we also have arranged the required parameters to be passed, then it's the time for us to run this SQL statement, right? Yes, of course. It's our turn to write and statement to run these SQL queries and to pass parameters and to get the results of the executed query. We’ll write. We had to write db.run. What do we have to pass? We have to pass this insert statement. We are passing the variable SQL for that. And then we have to pass the parameters that we've defined. Then we need to input a function, and we need to capture the errors and the result. That is what important. Now, for any reason if the SQL statement or the executed SQL statement returns an error, we have to define a proper error message to the user. Let's try to do that. We are going to check whether this particular error(err) is going to have a value. If there is a value in error, we are going to define a proper error message. You might remember that we already have defined a response and we are going to assign a status. A specific status that I'm going to define as 400. And then I'm going to make the return, which is JSON, and I'm going to assign a particular JSON string to the same. I'm defining that it is an error and putting the colon “:” the error and I'm going to get the message that we are going to get out of the defined error. All right. We do have to return the same right, what we have to do is we have to write a return statement. Right? Else what do we have to do? Yes, there is a success story, right? Yes. Let's say if it is not an error, it should return a JSON, which we need to include our success story. Yes, that is going to be a JSON error message. The message is going to be success and data we are going to display the entire response body. And then, we have to indicate a particular id. Why do we need to have an id here? You will wonder why? Yes, id is required when we add data to the database. We need to know the unique id that is being generated in the database for a particular set of data or in simple terms when we add a product, we need to get to know the assigned id to uniquely identify the product. Right. So we also have defined everything that is required. Right. Is this enough? No. We need to define more. What do we need to define? Yes. We also have to manage errors like what we have done over here. There can be cases where it generates certain errors. So, for that we need to check whether the code is going to return any exception. If it is the case, we have to manage that as well. There can be some other cases where we don't get the required request in the message body. For that, it is important to write a statement. Let's try to define request body. For any reason, if this body is not having data, we are going to give a proper error message. For that we have to define an array of errors. This is typically of defining an array in Node JS. Now, what are we going to do? We have to push a particular error and tell that an invalid input. Let's say a simple error message and invalid input. Right. So, this is required when we talk about error handling. Still, there are things to improve. What are they? Yes, we have seen that we already have defined this particular API. Yes, that is for products. And that is capable of getting data and store it in a database. But still, there can be cases whenever we try to make the connection there are certain errors that are occurring. For that what is the solution? The solution is including a try statement that is very important to have. So, let's try to define a try statement that's going to help us. I already have written try statement. And where we have to close it. Yes. We have to go to the last statement that we currently have, which is this one. then we have to close the catch. Yes. And then we have to indicate a particular error. And then we have to write a proper response. The status and status code can be like 400 and it will be able to send that the same exceptions we will sent, and we have to terminate it. Right now, if you look at the entire code base, still we need to terminate this. Right. Okay. What we have to do is include termination for the entire code base. Right, now we have finished our coding. Right so it's our time to run the code base and see the outcome. Let's move and see the outcome together. Now it's the time for us to see the outcome for adding a product to our database table. Let's look at the data that we have added. We have a JSON that we have added. We have a product name assigned. We have a description assigned. We have a category, brand, expired date, manufactured date, batch number, unit price, quantity, and the created date as for today. Right. Now we can try to send data to the particular API. What is the URL that we need to access? Since we are running this API or service in my machine, it should be localhost and the port should be the port that you have defined. And you might remember that we have defined the URL pattern. It should be /api/products. Now what we need to know. We should indicate that the data that we are trying to pass should be raw and specifically the JSON. We'll try to hit it and see the response. Right, now we have received the status of 200, . Message which is success The data that we have entered and specifically the id that is generated automatically inside the database. Right. With that, we can conclude the data that we have tried has been entered to the table itself. Part5 Let's try to write an API to get data that we have already entered to the table, which is products. Let's start. You might remember that we've used up the app.post () method, but this time to get data we are going to refer to the app.get() method. Carefully look at the URL pattern that I am going to use here. That's going to be /api/products. That so. Then we have to define a comma and then the request, like what we did earlier. Then we have to find a response. And the next part. Then we have to start the curly bracket to indicate to write the body of the message. Let's start to write a SQL statement to get data from this particular table. We are going to define a variable to store the SQL statement, and it's going to be a very simple SQL statement, select all from products that indicate we are going to get data from the products table itself. That is not sufficient. We have to look at the data that we are going to get. For that, we can use a variable array, which is “param”. Then in the same way that we did for the last time, we have to call DB and execute this with all() and pass the SQL statement. Then passed param array and then have to define error and the result rows. Why do we define rows here? For a particular select statement there can be more than one records that we can get out of the table. That is the major reason. Then for any reason, if we don't get an error, we can return the success. For some reason, if you get an error, we have to provide a proper error message to the user. Now we are going to define a proper error message if there is an error in status. 400 and JSON type. I'm going to define the JSON, like what we did the last time. It's going to be an error. So I'm going to clearly mention that it is an error. The message going to be the message that we have inside the error. We are going to return the same. If we have a successful response, then we can call for a result. So in simple terms, we can define the response, Json as well. Let's try to define it. We are going to define a message. The outcome is going to be the rows here. And you also need to have a particular you see that the data is going to row, and our message is going to be “success”. Fine. Now, in the same way, we have to manage the errors, the exceptions that are going to be there. Now for that. We are going to try that. And if we receive a particular error, what we are going to do? For that is we have to write a catch statement, elliptical error, which is going to help us to manage the response as well. So I'm going to set the status, which is 400 again, and send it to the output. I think we are all clear We have defined a get API to get multiple products at the same time if we do have data in our database. Let's try to run this and see the outcome. We can open the postman and call to get all products. If you look at the URL pattern, like what we already defined, we have localhost:8080/api/products and the method is get(). I will try to get the data from the particular API. You might remember that we have added data in the previous activity. We try to hit this send button and see the results. Fine. We received data. We have a success message. We have 200 status. We do have the ID that we could identify at the time that we have entered the data and all the other parameters that we have clearly defined at the time that we inserted the data into the database. Part6 Let's try to look for an update API like what we did for two other APIs. We also have to write limited declaration and limited body so that we can use the update function to update existing data in our database table, which is the product. Let's look at the written API. This is quite similar to the previous API which we defined to enter data. There are a few differences to identify here. If you look at the method that you're using, we are using the put method we are referring to the same URL pattern. We have a request, defined, response, and next we have a constant defined to get the request parameters like what we did earlier but we have a different query in this time. That's the difference which we need to understand. We have tried out to execute the query with db.run. The statement is quite different. This time we have an update query. We are writing update products. Then we are going to set values to the parameters that we have entered for the last time. Let's look at the important parameters here. Product name, description, category, brand, expiry date, manufacture, date, and all the other parameters are available. Yeah, there is a specialty that we need to identify after all of these parameter values. We do have a WHERE statement or a WHERE closure and then we have ID with a question mark. This is where we are going to use the ID from the method body and that is going to select the specific record based on the ID that we have given and update the entire record. In the same way we have tried to manage the errors and provide required responses. And also we are going to provide an update message with 200 responses. Let's try to use the update API that we have defined and see the result. If you look at what I have here, I have clearly defined the ID, which is four that is the ID, which we could get it as a return at the time that we have inserted the data. Now we have to refer to the same object or to the record that we have in our database to update it for this time. Now I'm going to make this particular product name a different one. Let's say that is white. And also I'm going to change the product. Let's say that ABC. Hit the send button to see the results. If you look at the result that indicates we have already updated the data. We had one record and we have updated one row, based on the unique identifier that we have defined. Part7 Let's write a delete API to delete a particular product from the database table based on a given ID. You might remember that we have a defined unique ID, which is the primary key ID here in our table. We'll be using the same ID to uniquely identify a particular record from the database and remove it. Right. Let's start to write the API and try to test it. We have to use the app here and the method is delete in this time. It's quite differ than all other times. And I'm going to define the URL pattern /api/products/delete/ to clearly indicate that this specific API being created to delete a particular data and “:id” then comma(,). This is quite similar to the other API definitions. And continues the request. And then the response. And then the next, I’m going to open the curly brackets to write the method body. Right. Let's try to write a query and run it. I'm going to use db.run. I have to define a query clearly. For that, I'm going to write DELETE FROM products WHERE id =?. That is where the ID is going to pass. Then I'm going to pass the request parameter - req.params.id. Then I have to extend the code. I'll be writing a function to get the errors and also result. Let's try to further write the code. If there is an error, we are going to provide a proper response. res.status(400).json({“error”:res.message}). I think we are quite clear about our requirements now. If the data has been deleted, what to do? Anyway, we have to return the response, then we have to indicate that the data has been removed from the database without a problem. And I'm going to define a message. The message is going to be something to indicate that the record has been deleted from the table. And I'm going to come out here and then rows, the number of rows that has affected. I think that is clear to all of us. We had to put the comma (,) over here to clearly segregate the message and the rows that you have to display. I think this code is quite simple for anybody to understand, and that can manage easily. We also need to manage the exceptions or runtime errors if we have like what we discussed earlier. For that, what we need to do, we have to terminate the statement and then we have to try the entire statement with the try catch. Let's say we need to have a try and then we have to close it. Then we need to catch. The error that is going to return. res.status(400).send(E) and you are going to expose the error. Once we have completed the coding, we can format the entire code base for our reference. Right. Then we have to move to run the API and see how it deletes the particular product. Let's try to hit the delete API and delete the particular product which we've already updated in our previous activity. The id of the product or the record has to be clearly defined in the URL as the parameter. In this way, right now, let's hit the send button and see the result. All right. It has indicated that the particular product has been deleted and the number of affected rows is one. I think this is quite easy for you to understand. I hope that you enjoy this guided project. Thank you.