0% found this document useful (0 votes)
2 views10 pages

Lab09 - Express

The document outlines a lab for students to create a backend using Express.js, focusing on building RESTful APIs, handling routes and middleware, and managing data without a database. Students will learn to implement various functionalities like handling route and query parameters, serving static files, creating middleware for logging and authentication, processing form data, and managing JSON data. The lab culminates in building a simple REST API for managing a collection of items, with graded tasks including creating a product catalog API and implementing custom middleware for logging requests.

Uploaded by

amir.raza537918
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views10 pages

Lab09 - Express

The document outlines a lab for students to create a backend using Express.js, focusing on building RESTful APIs, handling routes and middleware, and managing data without a database. Students will learn to implement various functionalities like handling route and query parameters, serving static files, creating middleware for logging and authentication, processing form data, and managing JSON data. The lab culminates in building a simple REST API for managing a collection of items, with graded tasks including creating a product catalog API and implementing custom middleware for logging requests.

Uploaded by

amir.raza537918
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 10

Lab 09 – Creating Routes and Middleware in Express.

JS

Objective:
To enable students to build a structured and functional backend using Express.js that
simulates real-world product listing APIs. This task emphasizes route handling, middleware
usage, query and route parameters, and error management without a database, enhancing
students' confidence in backend development fundamentals.

Activity Outcomes:

By the end of this lab, students will be able to:

 Design and implement RESTful routes using Express.js.


 Handle dynamic query parameters for filtering and searching data.
 Work with route parameters to retrieve specific resources.
 Implement and configure middleware for request logging and debugging.
 Create well-structured API responses and error messages using appropriate status
codes.
 Understand how to simulate data persistence using in-memory structures.
1) Solved Lab Activites
Sr.No Allocated Time Level of Complexity CLO Mapping
1 10 Low CLO-5
2 10 Low CLO-5
3 10 Medium CLO-5
4 10 Medium CLO-5
5 10 Medium CLO-5
6 10 Medium CLO-5

Activity 1: Handling Route Parameters


Create a route that handles parameters in the URL, such as "/users/:id", and extract the
parameter value.
app.get('/users/:id', (req, res) => {
const userId = req.params.id;
res.send(`User ID: ${userId}`);
});

Run the server and open http://localhost:3000/users/123 in your browser. Try changing the
number in the URL.

 /users/:id: The colon (:) indicates a route parameter named "id".


 req.params.id: The req.params object contains the values of the route parameters. In
this case, req.params.id will hold the value of the "id" parameter from the URL.

Activity 2: Handling Query Parameters

Create a route that handles query parameters in the URL, such as "/search?q=example", and
extract the parameter value.

app.get('/search', (req, res) => {


const query = req.query.q;
res.send(`Search query: ${query}`);
});

Run the server and open http://localhost:3000/search?q=test. Try changing the value of "q".

 req.query.q: The req.query object contains the values of the query parameters. In this
case, req.query.q will hold the value of the "q" query parameter from the URL.4

Activity 3: Serving Static Files


The res.send() method can send any string, including HTML markup, which the browser will
then render as a web page, but if you are building some static pages that should be served
from a folder then you can create a directory named "public" and serve static files (e.g., an
HTML file, a CSS file, and an image) from it.
Instructions:
1. If not available, create a folder named "public" in your project directory: mkdir public
2. Create an HTML file named index.html inside the "public" folder:
<!DOCTYPE html>
<html>
<head>
<title>My Static Page</title>
<link rel="stylesheet" href="/styles.css">
</head>
<body>
<h1>Welcome to My Static Page</h1>
<img src="/my-image.jpg" alt="My Image">
</body>
</html>

3. Create a CSS file named styles.css inside the "public" folder:


body {
font-family: sans-serif;
}
h1 {
color: blue;
}

4. Save an image as my-image.jpg inside the "public" folder.


5. Modify server.js:

app.use(express.static('public')); // Serve static files from the 'public' directory

6. Run the server and open http://localhost:3000/myimage.jpg in your browser.

express.static('public'): This middleware tells Express to serve static assets (files that don't
change, like CSS, JavaScript, images) from the "public" directory. Now, files in the public
directory are accessible via URLs like /styles.css and /my-image.jpg.

Activity 4: Create and use Middleware


Create a simple middleware function that logs the request method and URL to the console for
every request.

// Define a middleware function


const myLogger = (req, res, next) => {
console.log(`[${req.method}] ${req.url}`);
next(); // Call the next middleware or route handler
};

// Use the middleware for all routes


app.use(myLogger);
app.get('/', (req, res) => {
res.send('Hello, World!');
});

app.get('/about', (req, res) => {


res.send('About Us');
});

Run the server and visit any of the defined routes in your browser. Check the console in your
terminal.

 myLogger function: This is a middleware function. It takes req, res, and next as
arguments.
 console.log(...): Logs the request method and URL.
 next(): This is crucial. It tells Express to move on to the next middleware in the chain
or to the route handler. If you don't call next(), the request will be left hanging.
 app.use(myLogger): This tells Express to use the myLogger middleware for all
incoming requests.

Activity 5: Using multiple middleware functions


Create two middleware functions, one for logging request and another for authentication. If
user is not authenticated response object is not sent to next routing method, instead it is
returned to the user.

// Middleware function 1
const loggerMiddleware = (req, res, next) => {
console.log(`[${req.method}] ${req.url}`);
next(); // Pass control to the next middleware/route handler
};

// Middleware function 2
const authMiddleware = (req, res, next) => {
// Simulate authentication
const isAuthenticated = true;
if (isAuthenticated) {
next(); // User is authenticated, proceed to the next handler
} else {
res.status(401).send('Unauthorized'); // User is not authenticated
}
};

// Use the middleware


app.use(loggerMiddleware);
app.use(authMiddleware);

// Route handler for '/'


app.get('/', (req, res) => {
res.send('Hello, World!');
});
Run the server. Open http://localhost:3000/ in your browser and see what is the response.

Activity 6: Handling POST Requests and Form Data


Create a route that handles POST requests and parses form data submitted from an HTML
form.
Create a file named form.html in the "public" directory:
<!DOCTYPE html>
<html>
<head>
<title>Form Example</title>
</head>
<body>
<form method="post" action="/submit-form">
<label for="name">Name:</label>
<input type="text" id="name" name="name"><br><br>
<label for="email">Email:</label>
<input type="email" id="email" name="email"><br><br>
<input type="submit" value="Submit">
</form>
</body>
</html>

Modify app.js:
const bodyParser = require('body-parser'); // Import body-parser

app.use(express.static('public'));
// Use body-parser middleware to parse form data
app.use(bodyParser.urlencoded({ extended: false }));

app.post('/submit-form', (req, res) => {


const name = req.body.name;
const email = req.body.email;
res.send(`Name: ${name}, Email: ${email}`);
});

Run the server.


Open http://localhost:3000/form.html in your browser, fill out the form, and submit it.

 require('body-parser'): Imports the body-parser middleware. This middleware is


needed to parse data from POST requests.
 app.use(bodyParser.urlencoded({ extended: false })): Configures body-parser to parse
URL-encoded form data. The extended: false option uses a simpler parsing algorithm.
o extended: true allows for nested objects (like user[address][city]).
o extended: false only allows for strings and arrays (simpler format).
 req.body: The parsed form data is available in the req.body object. For example,
req.body.name contains the value of the "name" input field.
 app.post('/submit-form', ...): This route handler is for POST requests to "/submit-
form".
Activity 7: Handling JSON Data
Create a route that handles POST requests with JSON data in the request body.

Modify app.js

app.use(bodyParser.json()); // Use body-parser middleware to parse JSON data

app.post('/submit-json', (req, res) => {


const data = req.body;
console.log(data);
res.json({ message: 'JSON data received', data: data });
});

Run the server.


Use a tool like Postman or curl to send a POST request to http://localhost:3000/submit-
json with the following JSON data in the request body:
{
"name": "John Doe",
"age": 30,
"city": "New York"
}

Postman:
o Set the request type to POST.
o Enter the URL: http://localhost:3000/submit-json
o Set the "Body" to "raw" and select "JSON" as the format.
o Enter the JSON data above.
o Click "Send".
Curl:
curl -X POST -H "Content-Type: application/json" -d '{"name": "John Doe", "age": 30,
"city": "New York"}' http://localhost:3000/submit-json

 app.use(bodyParser.json()): Configures body-parser to parse JSON data from the


request body.
 req.body: When the request contains JSON data, req.body will be a JavaScript object
representing that data.
 res.json(...): This method sends a JSON-formatted response.

Activity 8: Setting Cookies


Set a cookie in the user's browser and read it on subsequent requests.
1. Install the cookie-parser middleware: npm install cookie-parser
2. Modify server.js:

app.use(cookieParser()); // Use cookie-parser middleware

app.get('/set-cookie', (req, res) => {


res.cookie('myCookie', 'hello', { maxAge: 900000, httpOnly: true }); // Set a cookie
res.send('Cookie has been set');
});

app.get('/read-cookie', (req, res) => {


const myCookieValue = req.cookies.myCookie; // Read the cookie
if (myCookieValue) {
res.send(`Cookie value: ${myCookieValue}`);
} else {
res.send('Cookie not found');
}
});

3. Run the server.


4. Open http://localhost:3000/set-cookie in your browser. This will set the cookie.
5. Then, open http://localhost:3000/read-cookie to see the cookie value.

 require('cookie-parser'): Imports the cookie-parser middleware.


 app.use(cookieParser()): Initializes the cookie-parser middleware.
 res.cookie(name, value, options): This method sets a cookie.
o name: The name of the cookie ('myCookie' in this case).
o value: The value of the cookie ('hello').
o options: An object with cookie options (e.g., maxAge for expiration time in
milliseconds, httpOnly: true to prevent client-side JavaScript from accessing
the cookie).
 req.cookies: This object contains all the cookies sent by the client in the request. For
example, req.cookies.myCookie gets the value of the 'myCookie' cookie.

Activity 9: Build a simple REST API


Create a simple RESTful API using Express.js to manage a collection of items (e.g., books,
students, movies). This lab will help you practice defining routes, handling HTTP methods,
and sending responses.
You will create an API for managing a collection of items. Each item will have an ID, a title,
and any other relevant properties. You need to implement the following endpoints:
 GET /items - Retrieve a list of all items.
 GET /items/:id - Retrieve a specific item by its ID.
 POST /items - Create a new item.
 PUT /items/:id - Update an existing item.
 DELETE /items/:id - Delete an item.

Instructions:
1. Set up the Express.js application
2. Define the routes
3. Handle HTTP methods appropriately
o GET: Retrieve data.
o POST: Create new data.
o PUT: Update existing data.
o DELETE: Delete data.
4. Send responses:
o Use res.json() to send JSON responses with the requested data or appropriate
messages.
o Set appropriate HTTP status codes (e.g., 200 OK, 201 Created, 404 Not
Found, 500 Internal Server Error).
5. Data storage: For simplicity, store the items in an in-memory array. You do not need
to use a database for this lab.

Sample Solution:

// In-memory array to store items


let items = [
{ id: 1, title: 'Item 1' },
{ id: 2, title: 'Item 2' },
];

// Middleware to parse JSON request bodies


app.use(express.json());

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

// GET /items/:id
app.get('/items/:id', (req, res) => {
const id = parseInt(req.params.id);
const item = items.find((i) => i.id === id);

if (item) {
res.json(item);
} else {
res.status(404).json({ message: 'Item not found' });
}
});

// POST /items
app.post('/items', (req, res) => {
const newItem = {
id: items.length + 1,
title: req.body.title,
};
items.push(newItem);
res.status(201).json(newItem);
});

// PUT /items/:id
app.put('/items/:id', (req, res) => {
const id = parseInt(req.params.id);
const itemIndex = items.findIndex((i) => i.id === id);
if (itemIndex > -1) {
items[itemIndex].title = req.body.title;
res.json(items[itemIndex]);
} else {
res.status(404).json({ message: 'Item not found' });
}
});

// DELETE /items/:id
app.delete('/items/:id', (req, res) => {
const id = parseInt(req.params.id);
const itemIndex = items.findIndex((i) => i.id === id);

if (itemIndex > -1) {


items.splice(itemIndex, 1);
res.status(204).send(); // 204 No Content
} else {
res.status(404).json({ message: 'Item not found' });
}
});

app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
});

2) Graded Lab Tasks

Lab Task 1: Middleware Logger with Custom Timestamp

Write a custom middleware function that logs every incoming request with a timestamp,
route, and method. Append these logs to a file using the fs module.

Lab Task 2: Build a Product Catalog API

Develop a product catalog RESTful API using Express.js that supports viewing, filtering, and
retrieving product data. The data will be stored temporarily in memory (no database). This
activity will help students simulate backend functionalities similar to those found in e-
commerce applications.

Functional Requirements:
1. Data Setup:
o Create an array of products with the following fields:
 id (unique number)
 name (string)
 price (number)
 category (string)
 inStock (boolean)
2. GET /products Route:
o Respond with all products in JSON format.
o Support optional query parameters for:
 category (e.g., /products?category=electronics)
 maxPrice (e.g., /products?maxPrice=100)
 inStock=true|false
3. GET /products/:id Route:
o Return the product matching the provided id.
o Respond with a 404 Not Found if the product doesn't exist.
4. POST /products Route (Bonus):
o Accept a JSON body to add a new product.
o Validate that all required fields are present.
o Return a success message and the added product.
5. Middleware:
o Add middleware to log the HTTP method and path of incoming requests.
6. Error Handling:
o Return meaningful error messages and status codes for:
 Invalid routes
 Missing required data
 Invalid data types in input

Further Requirements:
 Ensure clean code structure and proper use of app.use() for middleware.
 Responses must be consistent and in JSON format.
 Input data should be validated for type and completeness before processing.

You might also like