Restful Api
Restful Api
DEPARTMENT OF
ARTIFICIAL INTELLIGENCE & MACHINE LEARNING
Exercise 1:
The Course Overview
Prerequisites:
Basic Knowledge of Java script & Node.js
Knowledge of Express & Mongo is not required.
Goals:
Build robust RESTful APIs with Node, Express, and MongoDB
Develop authentication with JWT (JSON Web Token)
Design middleware in Express
Learn advanced features such as caching queries
Deploy your APIs to the cloud
Exercise 2:
Prerequisites for Setting up the development:
Browser (Chrome)
Code Editor (Visual Studio Code)
Node and NPM
MongoDB Compass
Postman
Exercise -3:
API:
Application Programming Interface (API)
Makes it possible for two pieces of software to communicate
Abstracts the implementation of one piece of software to the other.
Famous Examples:
200 Success
404 Not found
400- Bad request
401 – Unauthorized
500 Internal server error
Exercise 4
Code-package.jsm
Package process:
Go to workspace in visual studio
Go to terminal and click npminit we get “package name” and “versions”and “description”and “license”
Go to terminal and click npm install—save express cors body parser
Now click npm install—save dev nodemo it helps to set the path
In this shows the errors in the program after we should rectify the error
Testing Error Paths: Don't forget to thoroughly test your error-handling code. Create test cases that
simulate various error scenarios to ensure your code responds correctly.
Exercise 6: Diving into Validations
Diving into validations is an important aspect of programming, especially when working with user
input or data from external sources. Validations help ensure that the data your program receives is
accurate, consistent, andsecure. Here's a comprehensive guide on how to approach validations in
your code:
Ensure that required fields are not empty. Check for null values or empty strings and prompt the
user to provide the necessary information.
Ensure that the data matches the expected data type. For example, if you expect an integer, check
that the input isindeed an integer. Most programming languages provide built-in functions or
methods for type validation.
your data relies on relationships between different entities (e.g., foreign keys in a database), ensure
that these relationships are maintained and that the referenced data exists
Exercise 7
Code- postColler.js
Postman process:
Go to your workspace in Postman.
Click on the + symbol to open a new tab.
Enter the API Endpoint where it says, “Enter request URL” and select the method (action type
GET, POST, etc.) for that request as shown below.
Click on the Send button
Define the Post Attributes: Determine what information each post should contain. Common attributes
include:
Title: The title or headline of the post.
Content/Body: The main text or content of the post.
Author: The user or entity who created the post.
Timestamp: Date and time when the post was created.
Tags or Categories: Keywords or labels associated with the post for categorization and searching.
Likes/Reactions: The number of likes, reactions, or upvotes the post has received.
Comments: A list of comments or replies associated with the post.
Attachments: Any media files (images, videos, documents) attached to the post
Create a Database Schema: If you're building an application that uses a database, create a schema to
represent the post model. This involves defining tables and fields in the database that correspond to the
post attributes.
Validation Rules: Specify any validation rules for the post attributes. For example, you might require a
title for every post or restrict the length of the content.
Associations: If your application allows users to have profiles or authors to have multiple posts,
establish associations. For instance, a User model can be associated with multiple Post models through
a foreign key.
This code creates a basic representation of a post model in Django. You would typically integrate this
with a Django web application by creating views, templates, and URLs to handle creating, reading,
updating, and deleting posts. Additionally, you should run Django migrations to create database tables
based on your models.
In general, updating a post route involves making changes to the code that handles HTTP POST
requests for updating
existing data in your application. Here's a high-level overview of what you might need to do:
Now we open the postman and create a file
Shown in below
if you're using a REST API. Make sure that the route definition matches the changes you made in the
handler function.
Implement error handling to deal with cases where the update operation fails. This might include
database errors, validation errors, or other issues.
Exercise 13: Delete Post Route
Locate or define the specific route in your code that will handle the DELETE requests for deleting
posts. This route should include a URL endpoint and a handler function.
Inside the handler function, you'll need to implement the logic for deleting the post. This
typically involves:
Identifying the post to be deleted, often based on an identifier (e.g., post ID).
Checking if the post exists and is accessible to the user.
Deleting the post from your database or storage system.
Implement error handling to manage cases where the deletion operation fails. This might include
database errors,
authentication errors, or cases where the post does not exist
After successfully deleting the post, return an appropriate response to the client. This response should
indicate the
success of the operation (e.g., a success status code like 204 No Content) and optionally include any
relevant data or messages..
Contains metadata about the token, such as the type of token and the signing algorithm.
Open chrome and search localhost:8000/uploads to upload the file
Contains claims, which are statements about an entity (typically, the user) and additional data. Common
claims include user ID, username, roles, and expiration time.
Ensures the integrity of the token. It is generated using a secret key, and it helps verify that the sender
of the JWT is who it says it is and that the message wasn't changed along the way. After a user logs in,
a JWT is generated and sent back to the client.
The client includes this token in subsequent requests to prove their identity.
The payload of a JWT can contain user roles or permissions, allowing you to determine what actions a
user is allowed to perform.
JWTs allow you to create stateless authentication, as the token itself contains all the information needed
to validate a user. The user model is at the core of your application's authentication
and authorization system. When a user registers or logs in, their information is stored in the user model.
When a user makes a
request to access a protected resource, the application checks
the user's identity and permissions using the user model's data. Open termninal and install npm
CODE:JAVASCRIPT
const express = require('express');
const session = require('express-session');
const passport = require('passport');
constLocalStrategy = require('passport-local').Strategy;
const app = express();
// Configure Express sessions
app.use(session({
secret: 'your-secret-key',
resave: false,
saveUninitialized: false,
}));
// Initialize Passport
app.use(passport.initialize());
app.use(passport.session());
// Mock user database (replace with your database integration)
const users = [
{ id: 1, username: 'user', password: 'password' },
];
// Passport local strategy configuration
passport.use(new LocalStrategy(
(username, password, done) => {
const user = users.find(u =>u.username === username);
if (!user) {
return done(null, false, { message: 'Incorrect username.' });
}
if (user.password !== password) {
return done(null, false, { message: 'Incorrect password.' });
}
return done(null, user);
}
));
// Serialize and deserialize user
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
const user = users.find(u => u.id === id);
done(null, user);
});
// Your routes and application logic go here
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
3.Create Routes for Authentication:
Define routes for login, logout, and protected resources in your application. Passport will handle
the authentication process for the login route using the configured LocalStrategy.
CODE:JAVASCRIPT
// Example login route
app.post('/login',
passport.authenticate('local', {
successRedirect: '/dashboard',
failureRedirect: '/login',
failureFlash: true,
})
);
// Example logout route
app.get('/logout', (req, res) => {
req.logout();
res.redirect('/');
});
// Example protected route
app.get('/dashboard', isAuthenticated, (req, res) => {
res.send('Welcome to your dashboard, ' + req.user.username);
});
// Middleware to check if a user is authenticated
function isAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next(); }
res.redirect('/login');}
4.HTML Templates:
Create HTML templates for your login page (login.ejs) and other relevant pages.
5.Start the Server:
Run your Node.js application:
CODE: node app.js
This code sets up a basic Express.js application with Passport using a local strategy for
authentication. You will need to replace the mock user database (‘users’) with your actual user
database and adapt the code to your application's requirements. Additionally, you should use
secure practices such as password hashing and validation for a production application.
LOGIN ENDPOINT
Creating a login endpoint for authentication in a Node.js application typically involves setting up
a route that handles user login requests, validates user credentials, and establishes user sessions.
Below is an example of how to create a basic login endpoint using Express.js and Passport.js with
a local authentication strategy:
1.Install Required Packages:
Before you start, make sure you have the necessary packages installed:
CODE: npm install express express-session passport passport-local
2.Set Up Your Express Application:
Create a file (e.g., app.js) and set up your Express application, including the necessary
middleware and Passport configuration:
CODE JAVASCRIPT:
const express = require('express');
const session = require('express-session');
const passport = require('passport');
constLocalStrategy = require('passport-local').Strategy;
const app = express();
// Configure Express sessions
app.use(session({
secret: 'your-secret-key',
resave: false,
saveUninitialized: false,
}));
// Initialize Passport
app.use(passport.initialize());
app.use(passport.session());
CODE JAVASCRIPT:
app.post('/login',
passport.authenticate('local', {
successRedirect: '/dashboard',
failureRedirect: '/login',
failureFlash: true, // Enable flash messages for authentication failures
})
);
4.Create the Login Form:
In your HTML templates, create a login form (e.g., ‘login.ejs’) where users can enter their
credentials:
CODE HTML:
<form action="/login" method="post">
<div>
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>
</div>
<div>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required>
</div>
<div>
<button type="submit">Log In</button>
</div></form>
5.Handle Authentication Failure:
When authentication fails, Passport will redirect users back to the login page (/login) with a flash
message. You can customize the error message based on your application's needs:
CODE JAVASCRIPT:
app.get('/login', (req, res) => {
consterrorMessage = req.flash('error')[0]; // Get the first flash message (if any)
res.render('login', { errorMessage });
});
6.Start the Server:
Run your Node.js application:
CODE: node app.js
Now, when users access the ‘/login’ route and submit their credentials, Passport will authenticate
them. If the authentication is successful, they will be redirected to the ‘/dashboard’ route (you
should create this route and define what it displays). If authentication fails, they will be redirected
back to the login page with an error message.
Please note that this is a basic example for demonstration purposes. In a production application,
you should use secure practices like password hashing, validate user input, and integrate with a
proper user database rather than a mock one.
SIGNUP ENDPOINT
Creating a signup endpoint in a Node.js application involves setting up a route that handles user
registration requests. Below is an example of how to create a basic signup endpoint using
Express.js. In this example, we'll handle user registration by storing user data in a mock database.
You can replace the mock database with your actual database integration.
1.Install Required Packages:
If you haven't already, install the necessary packages:
CODE: npm install express body-parser
2.Set Up Your Express Application:
Create a file (e.g., ‘app.js’) and set up your Express application, including the necessary
middleware:
CODE JAVASCRIPT:
const express = require('express');
constbodyParser = require('body-parser');
const app = express();
// Parse JSON and URL-encoded bodies
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// Mock user database (replace with your database integration)
const users = [];
// Your routes and application logic go here
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
res.sendFile(__dirname + '/signup.html');
});
app.post('/signup', (req, res) => {
const{ username, password, email } = req.body;
// Validate input (e.g., check for required fields, validate email format)
// Mock database: Store user data
users.push({ username, password, email });
// Redirect to a success page or login page
res.redirect('/login');
});
4.Create the Signup Form (signup.html):
Create an HTML form for user registration. This form should include fields for the user's desired
username, password, and email address.
CODE:
<!DOCTYPE html>
<html>
<head>
<title>Signup</title>
</head>
<body>
<h1>Signup</h1>
<form action="/signup" method="post">
<div>
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>
</div>
<div>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required>
</div>
<div>
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
</div>
<div>
<button type="submit">Sign Up</button>
</div>
</form></body></html>
5.Handling User Input Validation:
In a production application, you should include robust input validation and possibly password
hashing before storing user data in a database. You may also want to check if a username or email
address is already taken to prevent duplicates.
6.Start the Server:
Run your Node.js application:
CODE: node ap.js
Now, when users access the ‘/signup’ route and submit the registration form, their data
(username, password, email) is captured and stored in the ‘users’ array (or your actual database).
You can customize the registration process, input validation, and database integration as needed
for your application.
You can run this program, and when you try to access
the'/protected'routewithoutbeingauthenticated,itwillredirectyou to the
'/login' route. After successful login, you canaccesstheprotectedroute.
implement a user registration process to allow users to create accounts with unique usernames
and secure passwords.
Consider using email confirmation for added security.
Store user passwords securely by hashing and salting them. Never store plaintext passwords in
your database.
Exercise 20 : User
Implement userSchema Tweaks
sessions to keep users logged in betweenrequests. Consider
using
You can secure
add newand HTTP-only
fields to your usercookies
schema totocapture
storesessiontokens.
additional information about users. For
Allowuserstoresettheirpasswordsiftheyforgetthem.Thistypicallyinvolvessendin
example, you might add fields for a user's profile picture, phone number, or address.
garesetlinktotheiremailaddress.
if certain fields are no longer needed or relevant, you can remove them from the schema to
simplify it. This is often done to reduce clutter and improve performance.
you find that the data type of a field is not suitable for the information you want to store, you can
change it. For example, you might change a text field to an email field or a date field to a
datetime field.
To ensure data integrity, you can add validation rules to fields. For instance, you can enforce that
email addresses must be in a valid format or that passwords must meet certain complexity
requirements.
You can specify default values for fields. This is useful for fields that often have the same value
for most users, as it saves time during data entry.
if followed_id in users[follower_id]["followers"]:
return jsonify({"message": "User is already following this user."}), 200
users[follower_id]["followers"].append(followed_id)
return jsonify({"message": "User is now following this user."}), 201
HTTP Method: Use the HTTP GET method to retrieve a list of posts. This aligns with the RESTful
convention for reading resources.
Authentication: Determine the authentication requirements for this route. You may allow public
access to view posts or require authentication, depending on your application's needs.
Pagination: Consider implementing pagination to limit the number of posts returned in a single
request. You can use query parameters like /posts?page=1&limit=10 to control the number of posts
per page.
Filtering and Sorting: Allow users to filter and sort posts if necessary. You can use query
parameters like
/posts?tag=technology&sort=date_desc to filter by tags and sort by date in descending order.
Response: Return an appropriate HTTP status code (e.g., 200 OK) along with a JSON response
containing the list of posts. Each post in the list should have a unique identifier and relevant
information.
Here's a Python Flask code snippet illustrating the implementation of the "Posts" index route:
Code:
from flask import Flask, jsonify, request
app = Flask( name )# Sample data for posts posts = [
{"id": 1, "title": "Post 1", "content": "Content 1"},
{"id": 2, "title": "Post 2", "content": "Content 2"}, # Add more posts here
# Endpoint for retrieving a list of posts @app.route("/posts", methods=["GET"]) def get_posts():
page = int(request.args.get("page", 1)) limit = int(request.args.get("limit", 10))
start_index = (page - 1) * limit end_index = start_index + limit
paginated_posts = posts[start_index:end_index]
return jsonify(paginated_posts)if name == " main ":
app.run(debug=True)
This code defines an index route for "Posts" that supports pagination with query parameters.
Adjust it according to your specific requirements and use a database to store and retrieve posts in a
production environment.
To consume and test new features
you'll typically follow these steps:Identify New Features: First, identify the new features or
endpoints you want to consume and test in your API. Ensure you have a clear understanding of the
API documentation or the specifications for these features.
Set Up Your Environment: Make sure you have the necessary environment and tools in place. This
includes having the API URL, any required authentication tokens or credentials, and a testing
environment (e.g., Postman, curl, or a programming language with HTTP libraries).
Testing Tools: Depending on your preference and requirements, you can use various tools to
consume and test APIs:
Postman: A popular GUI tool for testing APIs. It allows you to create and send requests easily,
inspect responses, and automate testing.
cURL: A command-line tool to send HTTP requests. Useful for quick testing and automation.
Programming Language Libraries: Use libraries like requests in Python, axios in JavaScript, or
equivalent libraries in other languages to make HTTP requests and handle responses
programmatically.
Test Scenarios: Define the test scenarios you want to cover. These may include:
Valid requests: Test with correct data and authentication.
Invalid requests: Test with missing or incorrect data to ensure proper error handling. Edge cases:
Test with extreme values or boundary conditions.
Performance and load testing: Assess how the API handles a high volume of requests.
Consume API Endpoints: Use the testing tools to send requests to the new API endpoints. Ensure
you provide valid input data and authentication credentials if required.
Inspect Responses: Carefully inspect the responses for correctness and completeness. Verify that
the API returns the expected data and status codes.
Error Handling: Test how the API handles errors. Verify that it provides informative error messages
and appropriate HTTP status codes.
Automation: Consider automating your tests, especially for regression testing. Tools like Postman
or test frameworks in your preferred programming language can help automate your test cases.
Documentation Review: Continuously refer to the API documentation or specifications to ensure
that you are using the endpoints correctly and testing all intended functionality.
Feedback and Reporting: If you encounter issues or have suggestions for improvement, report
them to the API development team. Clear and detailed bug reports can help in resolving issues
faster.
Security: Pay attention to security considerations, especially if you're testing features that involve
authentication, authorization, or sensitive data.
Scalability: If your API is expected to handle a large number of requests, perform load testing to
assess its scalability and performance.
Version Control: If the API undergoes changes or updates, ensure that you test against the correct
API version.
Documentation Updates: If you discover discrepancies or issues in the API documentation during
testing, inform the API maintainers so they can update it for clarity and accuracy.
Remember that thorough testing is essential to ensure that new features are reliable and meet the
specified requirements. It's also a good practice to automate as much of your testing as possible to
catch regressions quickly as the API evolves.
Return Paginated Results: Return the paginated results to the client along with metadata like the total
number of items and the current page.
Example response:
json
{
"data": [ /* array of paginated items */ ], "page": page,
"limit": limit, "totalItems": totalItems
}
Error Handling: Handle cases where the client provides invalid or out-of-range pagination parameters.
Testing: Thoroughly test your pagination functionality to ensure it works as expected.
By implementing these steps,you can add pagination support to your RESTful API using MongoDB
as the database backend. Clients can request different pages of results, and your API will return the
appropriate subset of data from the MongoDB collection.
app.get('/api/posts', async (req, res) => { const page = parseInt(req.query.page) || 1; const limit =
parseInt(req.query.limit) || 10; const skip = (page - 1) * limit;
try {
const client = await MongoClient.connect('mongodb://localhost:27017'); constdb = client.db('your-
database-name');
const collection = db.collection('your-collection-name');
res.json(posts);
client.close();
} catch (error) { console.error(error);
res.status(500).json({ error: 'Internal Server Error' });
}
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
In this example, the ‘/api/posts’ endpoint accepts ‘page’ and ‘limit’ query parameters to control
pagination. It calculates the ‘skip’ value based on the current page and the number of items per page,
and then uses it in the MongoDB query to retrieve the appropriate page of results .
Determine how you want to track requests and reset limits (e.g., using an in- memory store or a
database).
Middleware: Implement rate limiting as middleware that runs before your API route handlers .
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
In this example, the ‘express-rate-limit’ middleware is used to implement rate limiting for the
‘/api/posts’ endpoint. It allows up to 100 requests per minute per client and responds with a "Too
Many Requests" message when the limit is exceeded.
You can customize the rate limit settings to fit your specific requirements.
Remember to install the ‘express-rate-limit’ package using npm or yarn (‘npm install express-rate-
limit’) before using it in your application.
This is a basic implementation, and you can further enhance it by integrating a more robust rate-
limiting mechanism and possibly storing rate-limiting data in a distributed cache or database for
scalability and persistence.
Here’s a simplified Node.js example of integrating Redis caching into your API :
Javascript:
const express = require('express'); constredis = require('ioredis');
constMongoClient = require('mongodb').MongoClient; const app = express()
// Connect to Redis
constredisClient = new redis();
// Your MongoDB connection setup
constmongoUrl = 'mongodb://localhost:27017'; constdbName = 'your-database-name';
app.get('/api/posts/:postId', async (req, res) => { constpostId = req.params.postId;
constcacheKey = `post:${postId}`;
// Check if the data is in Redis cache
constcachedData = await redisClient.get(cacheKey);
if (cachedData) {
// Data is in the cache, return it res.json(JSON.parse(cachedData));
} else {
// Data is not in the cache, fetch it from MongoDB try {
const client = await MongoClient.connect(mongoUrl); constdb = client.db(dbName);
const collection = db.collection('posts');
const post = await collection.findOne({ _id: postId }); if (post) {
// Store the data in Redis cache
redisClient.setex(cacheKey, 3600, JSON.stringify(post)); // Cache for 1 hour
client.close();
} catch (error) { console.error(error);
res.status(500).json({ error: 'Internal Server Error' });
}
}
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
Redis caching can be customized further based on your API's needs, including cache expiration
policies, cache eviction strategies, and handling cache updates when data changes in MongoDB.
Create unique cache keys for each query or piece of data you want to cache. These keys should be based
on the query parameters or a unique identifier for the data
being cached.
Cache Data Retrieval:
Wrap your data retrieval logic with code that checks the cache for the requested
data before making the actual query to the data source (e.g., a database or API). If the data is found in the
cache, return it; otherwise, perform the query, store the result in
the cache, and then return it.
Set Cache Expiry and Invalidation:
Define an appropriate cache expiration policy based on the nature of your data.
Cached data should have a TTL (time-to-live) after which it becomes stale and needs to be refreshed. You
can also implement cache invalidation strategies to remove or update cached data when it becomes
outdated.
Handle Cache Misses:
When a cache miss occurs (i.e., the data is not found in the cache), make sure to handle it gracefully. Fetch
the data from the original source, populate the cache with the new data, and then return it to the requester.
Cache Eviction Strategies:
Depending on your caching mechanism, you might need to implement eviction strategies (e.g., LRU -
Least Recently Used) to make room for new data when the cache reaches its size limit.
Monitoring and Maintenance:
Implement monitoring and logging to keep track of cache hits, misses, and the overall cache health.
Regularly check and fine-tune your caching strategy based on the performance metrics and changing
application requirements.
Testing and Benchmarking:
Thoroughly test your application with and without caching to measure the
performance improvements. Benchmark your application to ensure that caching is indeed providing the
desired performance boost.
PYTHON CODE:
from flask import Flask, jsonify
app = Flask( name )
# Sample
datavalid_da
ta = {
"name": "John
Doe","age": 30,
"email": "[email protected]"
}
@app.route('/get_valid_data',
methods=['GET'])def get_valid_data():
return jsonify(valid_data)
Save the code in a Python file (e.g., serve_valid_data.py) and run it. You can access the valid data by
making a GET request to http://localhost:5000/get_valid_data in your web browser or using a tool like curl
ifname== "main":list_ec2_instances()
This program will print information about your EC2 instances, including
their IDs,
Week 11:
types,states,privateandpublicIPaddresses.Youcanexpandandcustomizethisc
Exercise 30: Explore the Database Provider
Exercise 31: Production Tweaks to codebase
Exercise 32: Final Testing of public API
Data Operations : They provide APIs and methods for CRUD (Create, Read,
Update, Delete) operations on the database. Developers can use these methods to interact
with the database without writing raw SQL queries.
Exercise 32: Final Testing of public API
Endpoint Testing : Test each endpoint of your API to ensure they return the
Final
expected testingVerify
responses. of a public
that theAPI is a critical
API functions step totoensure
according that the API is working
its documentation.
as expected, issecure, and meets the requirements of its consumers. Proper
testing helps prevent issues andensures a positive experience for developers
who will use your API. Here is a comprehensiveguideto
conductingfinaltestingof apublicAPI:
Security Testing :
Authentication and Authorization : Test authentication mechanisms (e.g., API
keys, OAuth) and ensure that only authorized users can access
4. HTTP Methods :
RESTful APIs use standard HTTP methods to perform CRUD (Create, Read,
Update, Delete) operations on resources. These methods include GET, POST, PUT,
PATCH, and DELETE.
5. Data Modeling :
NoSQL databases like MongoDB, Cassandra, or Couchbase are schema- less or
schema-flexible, allowing you to store and retrieve data without adhering to a fixed
schema.
6. Mapping Resources to Data :
In a RESTful API, resources often map to collections or documents in a NoSQL
database. For example, a collection of "users" in a NoSQL database might
correspond to a "/users" resource in the API.
7. JSON or XML :
RESTful APIs typically use JSON or XML for data exchange. NoSQL databases
often store data in a format that is easily convertible to JSON.
8. Querying :
NoSQL databases provide different query languages and mechanisms for retrieving
data. APIs can expose endpoints that allow clients to send queries or filter data
based on their requirements.
9. Scaling :
NoSQL databases are designed to scale horizontally, which means you can easily
add more servers to handle increased load. RESTful APIs can be deployed on load
balancers to distribute incoming requests across multiple instances.
10. Security :
Security measures like authentication and authorization should be implemented in
both the API and the NoSQL database to protect data.
11. Caching :
You can implement caching mechanisms in both the API layer and the database
layer to improve performance and reduce the load on the system.
In summary, a RESTful API can serve as an interface to interact with a NoSQL database,
allowing developers to create flexible and scalable systems that handle various types of data