Securing REST APIs With Client Certificates

Securing REST APIs With Client Certificates

Securing REST APIs with server-side certificates is a best practice. But what if you want to take security to the next level and require client certificates?

Securing REST APIs with server-side certificates is a best practice. But what if you want to take security to the next level and require client certificates?

This post is about an example of securing a REST API with a client certificate (a.k.a. X.509 certificate authentication).

In other words, a client verifies a server according to its certificate and the server identifies that client according to a client certificate (so-called mutual authentication).

In connection with Spring Security, we will be able to perform some additional authentication and authorization.

Technologies used:

  1. Spring Boot 2.0.5.RELEASE
  2. Spring Web + Security 5.0.8.RELEASE
  3. Embedded Tomcat 8.5.34

Quick post overview:

  • Create a simple REST API service (without any security)
  • Create certificates for server and client
  • Configure the server to serve HTTPS content
  • Configure the server to require a client certificate
  • Spring Security for further client authentication and authorization
  • Test our secured REST API
Final Project Structure

Creating a New Base Spring Boot Project

We will start with a new project generated by Spring Initializr. We just need two Spring dependencies, i.e. Spring Web + Spring Security.

All required dependencies are shown here:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Create a Simple REST API Service

Let’s create a simple REST controller serving a detail about a customer using an HTTP GET method:

@RestController
@RequestMapping("/customer")
public class CustomerController {

    @GetMapping("/{id}")
    public Customer GetCustomer(@PathVariable Long id) {
        return new Customer(id, "Customer" + id);
    }
}

Displaying URL http://localhost:8080/customer/1 returns this JSON object:

{
    "id":1,
    "name":"Customer1"
}

Create Certificates for Server and Client

I want to stay focused on securing REST APIs so I will show you how to generate all required files in a very concise way. For more details about commands, visit my other blog post about creating a PKCS #12 key store.

#Create folders to generate all files (separated for client and server)
mkdir ssl && cd ssl && mkdir client && mkdir server

## Server
# Generate server private key and self-signed certificate in one step
openssl req -x509 -newkey rsa:4096 -keyout server/serverPrivateKey.pem -out server/server.crt -days 3650 -nodes
# Create PKCS12 keystore containing private key and related self-sign certificate
openssl pkcs12 -export -out server/keyStore.p12 -inkey server/serverPrivateKey.pem -in server/server.crt
# Generate server trust store from server certificate 
keytool -import -trustcacerts -alias root -file server/server.crt -keystore server/trustStore.jks

## Client
# Generate client's private key and a certificate signing request (CSR)
openssl req -new -newkey rsa:4096 -out client/request.csr -keyout client/myPrivateKey.pem -nodes

## Server
# Sign client's CSR with server private key and a related certificate
openssl x509 -req -days 360 -in request.csr -CA server/server.crt -CAkey server/serverPrivateKey.pem -CAcreateserial -out client/pavel.crt -sha256

## Client
# Verify client's certificate
openssl x509 -text -noout -in client/pavel.crt
# Create PKCS12 keystore containing client's private key and related self-sign certificate 
openssl pkcs12 -export -out client/client_pavel.p12 -inkey client/myPrivateKey.pem -in client/pavel.crt -certfile server/myCertificate.crt

You can find the SSL folder with all generated files on the project’s GitHub page.

We will use files in the server folder to configure our server.

The final client’s file client/client_pavel.p12 can be either imported into your browser or used in another client application.

On Windows, just open this file and import it into your system to test the REST API with any browser.

Configure the Server to Serve HTTPS Content

Basically, there are two options.

You can use any standalone server (e.g. Tomcat, WildFly etc.) so the configuration would be specific to your choice. I prefer this choice for production environments.

Instead of configuring an application server, I will show you the second, simpler way of using an embedded Tomcat server inside Spring Boot.

The configuration is quite easy, we will change the port to 8443 and configure the server key store generated in the previous steps:

# Define a custom port (instead of the default 8080)
server.port=8443
# The format used for the keystore
server.ssl.key-store-type=PKCS12
# The path to the keystore containing the certificate
server.ssl.key-store=classpath:keyStore.p12
# The password used to generate the certificate
server.ssl.key-store-password=changeit

Configure the Server to Require a Client Certificate

The configuration of any server to require a client certificate (i.e. the mutual authentication) is very similar to the server side configuration except using words like a trust store instead of a key store.

So the embedded Tomcat configuration seems like:

# Trust store that holds SSL certificates.
server.ssl.trust-store=classpath:trustStore.jks
# Password used to access the trust store.
server.ssl.trust-store-password=changeit
# Type of the trust store.
server.ssl.trust-store-type=JKS
# Whether client authentication is wanted ("want") or needed ("need").
server.ssl.client-auth=need

The embedded server now ensures (without any other configuration) that the clients with a valid certificate only are able to call our REST API.

Other clients will be declined by the server due to being unable to make correct SSL/TLS handshake (required by mutual authentication).

Please note that all configuration items starting server. are related to an embedded Tomcat server only. You do not need it when using any standalone application server.*

Spring Security for Further Client Authentication and Authorization

It would be fine to get an incoming client for our application as a logged user.

That gives us the possibility to perform some other authentications and authorizations using Spring Security (e.g. securing method calls to specific roles).

Until now, no Spring Security was needed, but all clients with any valid certificate may perform any call in our application without knowing who the caller is.

So we must configure Spring Security to create a logged user using a username from a client certificate (usually from the CN field, see the method call subjectPrincipalRegex):

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated().and()
                .x509()
                    .subjectPrincipalRegex("CN=(.*?)(?:,|$)")
                    .userDetailsService(userDetailsService());
    }

    @Bean
    public UserDetailsService userDetailsService() {
        return (UserDetailsService) username -&amp;amp;amp;amp;gt; {
            if (username.equals("pavel")) {
                return new User(username, "",
                        AuthorityUtils
                                .commaSeparatedStringToAuthorityList("ROLE_USER"));
            } else {
                throw new UsernameNotFoundException(String.format("User %s not found", username));
            }
        };
    }
}

Using the bean UserDetailsService is a kind of fake, but it shows an example of an additional authentication to accept only the username “pavel”.

In other words, it accepts a client with a certificate containing the value “pavel” only in the certificate’s CN field (as mentioned before, configured with subjectPrincipalRegex).

As you might have noticed, only the user “pavel” is a member of the role “user”, so now we are able to restrict method calls to specific roles:

    @GetMapping("/{id}")
    @Secured("ROLE_USER")
    public Customer GetCustomer(@PathVariable Long id) {
        return new Customer(id, "Customer" + id);
    }

Test Secured REST API

When you successfully import client/client_pavel.p12 into your system and the application runs, you can visit URL [https://localhost:8443/customer/1.](https://localhost:8443/customer/1. "https://localhost:8443/customer/1.")

The first access of this page displays a window to select the correct certificate to authenticate with the server:

When you submit an incorrect certificate, you will see the “access denied” page (otherwise JSON object returned):

That is all! You can find all my source code on my GitHub profile.

What is REST API? | Restful Web Service

What is REST API? | Restful Web Service

In this post "Restful Web Service", you'll learn: What is Web services, what is API, What is REST API, How REST works and Implementation of REST API

What is REST API? | Restful Web Service

A REST API defines a set of functions to process requests and responses via HTTP protocol.

REST is used in mobile application as well as in web applications.


Web Development with Rust - 03/x: Create a REST API

Web Development with Rust - 03/x: Create a REST API

Since Rust is a static typed language with a strong compiler you won't face many of the common pitfalls about running a web service in production. Although there are still run time errors which you have to cover.

Content
  1. HTTP Requests
  2. POST/PUT/PATCH/DELETE are special
  3. The Job of a Framework
  4. Creating an API spec
  5. Crafting the API
  6. Input Validation
  7. Summary

APIs are the bread and butter of how a modern and fast-paced web environment. Frontend application, other web services and IoT devices need to be able to talk to your service. API endpoints are like doors to which you decide what comes in and in which format.

Since Rust is a static typed language with a strong compiler you won't face many of the common pitfalls about running a web service in production. Although there are still run time errors which you have to cover.

HTTP Requests

When we talk about creating an API we basically mean a web application which listens on certain paths and responds accordingly. But first things first. For two devices to be able to communicate with each other there has to be an established TCP connection.

TCP is a protocol which the two parties can use to establish a connection. After establishing this connection, you can receive and send messages to the other party. HTTP is another protocol, which is built on top of TCP, and it's defining the contents of the requests and responses.

So on the Rust side of things, TCP is implemented in the Rust core library, HTTP is not. Whatever framework you chose in the previous article they all implement HTTP and therefore are able to receive and send HTTP formatted messages.

An example GET requests for example looks like this:

GET / HTTP/1.1
Host: api.awesomerustwebapp.com
Accept-Language: en

It includes:

  • GET: the HTTP method
  • /: The path
  • HTTP/1.1: The version of the HTTP protocol
  • HOST: The host/domain of the server we want to request data from
  • Accept-Language: Which language we prefer and understand

The most common used HTTP methods are:

  • GET
  • POST
  • PUT
  • PATCH
  • DELETE
POST/PUT/PATCH/DELETE are special

We are using GET every time we browse the web. If we want to alter data however (like using POST to send data over to another server), we need to be more cautions and precise.

First, not everyone is allowed to just send a bunch of data to another server. Our API can for example say: "I just accept data from the server with the host name allowed.awesomerustapp.com.

Therefore, when you send a POST to another server, what actually happens is the CORS workflow:

We first ask the server what is allowed, where do you accept requests from and what are your accepted headers. If we fulfill all of these requirements, then we can send a POST.

Disclaimer: Not all frameworks (like rocket and tide) are implementing CORS in their core. However, in a professional environment, you handle CORS on the DevOps side of things and put it for example in your NGINX config.
The Job of a Framework

We use the hard work of other people to create web applications. Everything has to be implemented at some point, just not from you for most of the time. A framework covers the following concerns:

  • Start a web server and open a PORT
  • Listen to requests on this PORT
  • If a request comes in, look at the Path in the HTTP header
  • Route the request to the handler according to the Path
  • Help you extract the information out of the request
  • Pack the generated data and HTTP StatusCode (created from you) and form a response
  • Send the response back to the sender

The Rust web framework tide includes http-service, which provides the basic abstractions you need when working with HTTP calls. The crate http-service is built on top of hyper, which transforms TCP-Streams to valid HTTP requests and responses.

Your job is to create routes like /users/:id and add a route_handler which is a function to handle the requests on this particular path. The framework makes sure that it directs the incoming HTTP requests to this particular handler.

Creating an API spec

You have to define your resources first to get an idea what your application needs to handle and uncover relationships between them. So if you want to build a idea-up-voting site, you would have:

  • Users
  • Ideas
  • Votes

A simple spec for this scenario would look like this:

  • Users
  • POST /users
  • GET /users
  • PUT /users/:user_id
  • PATCH /users/:user_id
  • DELETE /users/:user_id
  • GET /users/:user_id

Ideas and Votes behave accordingly. A spec is helpful for two reasons:

  • It gives you guidelines not to forget a path
  • It helps to communicate to your API users what to expect

You can tools like swagger to write a full spec which also describes the structure of the data and the messages/responses for each path and route.

A more professional spec would include the return values for each route and the request and response bodies. However, the spec can be finalized once you know how your API should look like and behave. To get started, a simple list is enough.

Crafting the API

Depending on the framework you are using, your implementation will look different. You have to have the following features on your radar to look out for:

  • Creating routes for each method (like app.at("/users").post(post_users_handler))
  • Extracting information from the request (like headers, uri-params and JSON from the request body)
  • Creating responses with proper HTTP codes (200201400404 etc.)

I am using the latest version of tide for this web series. You can add it in your Cargo.toml file and use it for your web app:

[dependencies]
tide = "0.1.0"

Our first User implementation will look like this:

async fn handle_get_users(cx: Context<Database>) -> EndpointResult {
    Ok(response::json(cx.app_data().get_all()))
}

async fn handle_get_user(cx: Context<Database>) -> EndpointResult {
let id = cx.param("id").client_err()?;
if let Some(user) = cx.app_data().get(id) {
Ok(response::json(user))
} else {
Err(StatusCode::NOT_FOUND)?
}
}

async fn handle_update_user(mut cx: Context<Database>) -> EndpointResult<()> {
let user = await!(cx.body_json()).client_err()?;
let id = cx.param("id").client_err()?;

if cx.app_data().set(id, user) {
    Ok(())
} else {
    Err(StatusCode::NOT_FOUND)?
}

}

async fn handle_create_user(mut cx: Context<Database>) -> EndpointResult<String> {
let user = await!(cx.body_json()).client_err()?;
Ok(cx.app_data().insert(user).to_string())
}

async fn handle_delete_user(cx: Context<Database>) -> EndpointResult<String> {
let id = cx.param("id").client_err()?;
Ok(cx.app_data().delete(id).to_string())
}

fn main() {
// We create a new application with a basic, local database
// You can use your own implementation, or none: App::new(())
let mut app = App::new(Database::default());
app.at("/users")
.post(handle_create_user)
.get(handle_get_users);
app.at("/users/:id")
.get(handle_get_user)
.patch(handle_update_user)
.delete(handle_delete_user);

app.serve("127.0.0.1:8000").unwrap();

}

You can find the full implementation of the code in the GitHub repository to this series.

We see that we first have to create a new App

let mut app = App::new(())

add routes

app.at("/users")

and for each route add the HTTP requests we want to handle

app.at("/users").get(handle_get_users)

Each framework has a different method of extracting parameters and JSON bodies. Actix is using Extractors, rocket is using Query Guards.

With tide, you can access request parameters and bodies and database connections through Context. So when we want to update a User with a specific id, we send a PATCH to /users/:id. From there, we call the handle_update_user method.

Inside this method, we can access the id from the URI like this:

let id = cx.param("id").client_err()?;

Each framework is also handling its own way of sending responses back to the sender. Tide is using EndpointResult, rocket is using Response and actix HttpResponse.

Everything else is completely up to you. The framework might help you with session management and authentication, but you can also implement this yourself.

My suggestion is: Build the first skeleton of your app with the framework of your choice, figure out how to extract information out of requests and how to form responses. Once this is working, you can use your Rust skills to build small or big applications as you wish.

Input Validation

Your best friend in the Rust world will be serde. It will help you parse JSON and other formats, but will also allow you to serialize your data.

When we talk about input validation, we want to make sure the data we are getting has the right format. Lets say we are extracting the JSON body out of a request:

let user: User = serde_json::from_str(&request_body);

We are using serde_json here to transform a JSON-String into a Struct of our choice. So if we created this struct:

struct User {
name: String,
height: u32,
}

we want to make sure the sender is including name and height. If we just do serde_json::from_str, and the sender forgot to pass on the height, the app will panic and shut down, since we expect the response to be a user: let user: User.

We can improve the error handling like this:

let user: User = match serde_json::from_str(&request_body) {
Ok(user) => user,
Err(error) => handle_error_case(error),
};

We catch the error and call our handle_error_case method to handle it gracefully.

Summary
  1. Pick a framework of your choice
  2. rocket is nightly
  3. actix is stable
  4. tide is fostered close to the Rust Core and also works on Rust nightly
  5. Know that there is no common CORS handling (yet). Recommendation is to handle this on the DevOps side (NGINX for example)
  6. After picking a framework, spec out your resources (/users: GET, POST etc.)
  7. Figure out how the framework of your choice is handling extracting parameters and JSON from the request and how to form a response
  8. Validate your input via match and serde_json

Thanks For Visiting, Keep Visiting. If you liked this post, share it with all of your programming buddies!

Why you should learn the Rust programming language

☞ The Rust Programming Language

☞ Rust Vs. Haskell: Which Language is Best for API Design?

☞ An introduction to Web Development with Rust for Node.js Developers

☞ 7 reasons why you should learn Rust programming language in 2019

Why you should move from Node.js to Rust in 2019

☞ Rust: Building Reusable Code with Rust from Scratch

☞  Programming in Rust: the good, the bad, the ugly.

☞  An introduction to Web Development with Rust for Node.js Developers

☞ Intro to Web Development with Rust for NodeJS Developers

☞ Introducing the Rust Crash Course

3 Frameworks for Building APIs Using Rust


This post was originally published here

What is REST API? – The Complete Guide to RESTful APIs

What is REST API? – The Complete Guide to RESTful APIs

We have been using different applications and web pages to get data for various resources. However, have you ever thought, where does this data come from? . So in this article on What is REST API, let us look into how a client communicates with the servers to extract the required information.

The following topics will be covered in this article "What is REST API":

  • Need of REST API
  • What is REST API?
  • Principles of REST API
  • Methods of REST API
  • How to create a REST API?

Now, before I define REST API for you, let me take you through an example to make you understand the need of REST API.

Need of REST API

Consider a scenario where you are using the Book My Show app. Now, obviously, this application needs a lot of Input data, as the data present in the application is never static. Either it is movies getting released on a frequent basis, or various cities showing different languages movies at various times of the day. It’s never static which implies to the fact that data is always changing in these applications.

Now, where do you think we get this data from?

Well, this data is received from the Server or most commonly known as a Web-server. So, the client requests the server for the required information, via an API, and then, the server sends a response to the client.

Over here, the response sent to the client is in the form of an HTML Web Page. But, do you think this is an apt response that you would expect when you send a request?

Well, I am assuming the fact that you would say NO. Since, you would prefer the data to be returned in the form of structured format, rather than the complete Web page.

So, for such reasons, the data returned by the server, in response to the request of the client is either in the format of JSON or XML. Both JSON and XML format have a proper hierarchical structure of data.

Now, this sounds quite simple, right?

But, the only issue which is present in this framework till now is that you have to use a lot of methods to get the required information. To the fact, using these methods to retrieve information, becomes quite cumbersome when you require complex data.

So, this is where REST API comes into the picture. The REST API creates an object, and thereafter send the values of an object in response to the client.

Now, that you know the need of REST, next in this article, let us look into the What is REST API?

What is REST API?

REST suggests to create an object of the data requested by the client and send the values of the object in response to the user. For example, if the user is requesting for a movie in Bangalore at a certain place and time, then you can create an object on the server side.

So, over here, you have an object and you are sending the state of an object. This is why REST is known as Representational State Transfer.

If I have to define REST, then,  Representational State Transfer a.k.a REST is an architectural style as well as an approach for communications purpose that is often used in various web services development.

The architectural style of REST helps in leveraging the lesser use of bandwidth to make an application more suitable for the internet. It is often regarded as the “language of the internet” and is completely based on the resources.

To understand better, let’s dive a little deeper and see how exactly does a REST API work. Basically, the REST API breaks down a transaction in order to create small modules. Now, each of these modules is used to address a specific part of the transaction. This approach provides more flexibility but requires a lot of effort to be built from the very scratch.

So, now that you know what is REST API, let us next understand the constraints or principles which must be satisfied for an application to be regarded as REST API.

Principles of REST API

Well, there are six ground principles laid down by Dr. Fielding who was the one to define the REST API design in 2000. Below are the six guiding principles of REST:

Stateless

The requests sent from a client to a server will contain all the required information to make the server understand the requests sent from the client. This can be either a part of URL,  query-string parameters, body, or even headers. The URL is used to uniquely identify the resource and the body holds the state of the requesting resource. Once the server processes the request, a response is sent to the client through body, status or headers

Client-Server

The client-server architecture enables a uniform interface and separates clients from the servers. This enhances the portability across multiple platforms as well as the scalability of the server components.

Uniform Interface

To obtain the uniformity throughout the application, REST has the following four interface constraints:

  • Resource identification
  • Resource Manipulation using representations
  • Self-descriptive messages
  • Hypermedia as the engine of application state

Cacheable

In order to provide a better performance, the applications are often made cacheable. This is done by labeling the response from the server as cacheable or non-cacheable either implicitly or explicitly. If the response is defined as cacheable, then the client cache can reuse the response data for equivalent responses in the future.

Layered system

The layered system architecture allows an application to be more stable by limiting component behavior. This type of architecture helps in enhancing the application’s security as components in each layer cannot interact beyond the next immediate layer they are in. Also, it enables load balancing and provides shared caches for promoting scalability.

Code on demand

This is an optional constraint and is used the least. It permits a clients code or applets to be downloaded and to be used within the application. In essence, it simplifies the clients by creating a smart application which doesn’t rely on its own code structure.

Now, that you know the principles behind REST API, next let’s look into the Methods of REST API.

Methods of REST API

All of us working with the technology of the web, do CRUD operations. When I say CRUD operations, I mean that we create a resource, read a resource, update a resource and delete a resource. Now, to do these actions, you can actually use the HTTP methods, which are nothing but the REST API Methods. Refer below.

Now that you know what is a REST API and what all you need to mind in order to deliver an efficient application, let’s dive deeper and see the process of building REST API.

How to create a REST API?

In this practical demonstration, I will be creating a simple CRUD REST application using Node.js. To build this application, you will need to install the following:

  1. Node.js
  2. Express.js
  3. Joi
  4. nodemon (Node Monitor)

For this hands-on, I will be using the WebStorm IDE to write and execute the codes. You can use any IDE or code editor according to your choice. So, let’s get started.

Step 1: Create a project directory, which will consist of all the files present in the project. Then, open commands prompt and navigate to the project directory. Refer below.

Step 2: Now, call npm using the below command. This will initialize the npm modules in your system.

npm init

Once you hit enter, Node.js, will ask you to enter a few details related to the project. These details will basically be the metadata for your project. Refer below.

Here you can define your entry point along with several other information. For this demo, I will be using script.js as an entry point.

It will then, ask you for a confirmation for the data you must have mentioned. Just press on Y to confirm. Refer below.

Step 3: Next, you have yo install Express.js using the below command:

npm i express

Express is a web framework which can be used along with Node.js. This web framework will allow you to create Restful APIs, with the help of helper methods, middle layers to configure your application.

Step 3.1: Similarly, you have to install Joi.

npm i joi

This package allows you to create blueprints for JavaScript objects which store information to ensure validation of key information.

Step 3.2: Finally, install the node monitoring package nodemon, using the below command.

npm i -g nodemon

Nodemon, keeps a watch on all the files with any type of extension present in this folder. Also, with nodemon on the watch, you don’t have to restart the Node.js server each time any changes are made. Nodemon will implicitly detect the changes and restart the server for you.

package.json

{
"name": "restapidemo",
"version": "1.0.0",
"description": "Creation of REST API",
"main": "script.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "sahiti_kappagantula",
"license": "ISC",
"dependencies": {
"express": "^4.17.1",
"joi": "^14.3.1"
}
}

script.js

const express = require('express'); //Import Express
const Joi = require('joi'); //Import Joi
const app = express(); //Create Express Application on the app variable
app.use(express.json()); //used the json file
 
//Give data to the server
const customers = [
{title: 'George', id: 1},
{title: 'Josh', id: 2},
{title: 'Tyler', id: 3},
{title: 'Alice', id: 4},
{title: 'Candice', id: 5}
]
 
//Read Request Handlers
// Display the Message when the URL consist of '/'
app.get('/', (req, res) => {
res.send('Welcome to Edurekas REST API!');
});
// Display the List Of Customers when URL consists of api customers
app.get('/api/customers', (req,res)=> {
res.send(customers);
});
// Display the Information Of Specific Customer when you mention the id.
app.get('/api/customers/:id', (req, res) => {
const customer = customers.find(c => c.id === parseInt(req.params.id));
//If there is no valid customer ID, then display an error with the following message
if (!customer) res.status(404).send('<h2 style="font-family: Malgun Gothic; color: darkred;">Ooops... Cant find what you are looking for!</h2>');
res.send(customer);
});
 
//CREATE Request Handler
//CREATE New Customer Information
app.post('/api/customers', (req, res)=> {
 
const { error } = validateCustomer(req.body);
if (error){
res.status(400).send(error.details[0].message)
return;
}
//Increment the customer id
const customer = {
id: customers.length + 1,
title: req.body.title
};
customers.push(customer);
res.send(customer);
});
 
//Update Request Handler
// Update Existing Customer Information
app.put('/api/customers/:id', (req, res) => {
const customer = customers.find(c=> c.id === parseInt(req.params.id));
if (!customer) res.status(404).send('<h2 style="font-family: Malgun Gothic; color: darkred;">Not Found!! </h2>');
 
const { error } = validateCustomer(req.body);
if (error){
res.status(400).send(error.details[0].message);
return;
}
 
customer.title = req.body.title;
res.send(customer);
});
 
//Delete Request Handler
// Delete Customer Details
app.delete('/api/customers/:id', (req, res) => {
 
const customer = customers.find( c=> c.id === parseInt(req.params.id));
if(!customer) res.status(404).send('<h2 style="font-family: Malgun Gothic; color: darkred;"> Not Found!! </h2>');
 
const index = customers.indexOf(customer);
customers.splice(index,1);
 
res.send(customer);
});
//Validate Information
function validateCustomer(customer) {
const schema = {
title: Joi.string().min(3).required()
};
return Joi.validate(customer, schema);
 
}
 
//PORT ENVIRONMENT VARIABLE
const port = process.env.PORT || 8080;
app.listen(port, () => console.log(`Listening on port ${port}..`));

Step 4: Now, the next step is to check whether the handlers are working properly or not. For that, we will use a Chrome extension called Postman. To install Postman you can visit here and click on ‘Add to Chrome’.

Step 5: Now, once you have installed Postman, open it to test your application.

Step 6: But before that you have to start your server. To start your server, type the following command.

node script.js

You would see the output as below:

Results

Let us start by testing the GET Method.

Step 7: In order to do that you need to select GET from the drop-down list, type in the defined URL and hit send.

If your code is working fine, then you will see the list of all the customers which we have added manually in our code. In the below picture, you can see how my result looks like. Here I have mentioned the URL to be localhost:8080/api/customers

Step 8: Now, let’s try adding a new customer to our stack of customers. For that, select ‘POST’ from the drop-down list and type in the defined URL for the POST method. Then, click on ‘Body’, select ‘raw’ and move on to select ‘JSON’ from the drop-down list as depicted in the below image. Now, in the text area, type in the name of your customer as shown and hit send.

If your POST method is working fine, your response body will contain the new customer’s name along with the Customer ID. Here if you observe, we have only mentioned the name but we did not give the customer ID. This implies that the Customer ID is automatically incremented

Step 9: Now, let’s try to update a Customer name. Let us say we ant to update the name of the Customer ID = 3. So, to update the data, you need to first select ‘PUT’ from the drop-down table and enter the PUT request’s URL along with the customer id you wish to update. Next in the ‘Body’, type in the new customer name and hit enter.

This will give you a response with the customer id and updated customer name.

Step 10: Finally, let’s send a ‘DELETE’ request to delete an existing record. For that select DELETE from the drop-down list and type in the URL of the delete request handler along with the customer’s details, you want to remove and hit enter. Let’s say, I want to delete the details of a customer with id = 3. If your transaction is successful, you will see the complete details of the entry you have removed in the response body.

Now, let’s send a GET request for our final list of customers.

As you can see from the above screenshot, the response body contains a total of five customers with the customer id 3 missing as we have already deleted that entry.