Let's dive deep into exploring REST APIs by setting up a Node.js server that uses object literals to simulate a simple JSON database.
We'll also create a client-side program to exercise various aspects of REST, such as CRUD (Create, Read, Update, Delete) operations.
Lab Exercise: Deep Dive into REST APIs
Objective:
- Understand and implement RESTful principles.
- Create a Node.js server with object literals simulating a JSON database.
- Develop a client-side program to perform CRUD operations on the server.
---
Part 1: Setting Up the Node.js Server
1. Initialize the Project**
1. Create a new directory for the project and navigate into it:
```bash
mkdir rest-api-lab
cd rest-api-lab
```
2. Initialize a new Node.js project:
```bash
npm init -y
```
3. Install the required dependencies:
```bash
npm install express
```
2. Create the Server
1. Create a file named `server.js`:
```javascript
```
2. Run the server:
```bash
node server.js
Updated Corrected Code remember to npm i cors
const express = require('express');
const cors = require('cors');
const app = express();
const port = 3000;
app.use(express.json());
app.use(cors());
let items = [
{ id: 1, name: 'Item 1', description: 'Description of Item 1' },
{ id: 2, name: 'Item 2', description: 'Description of Item 2' },
{ id: 3, name: 'Item 3', description: 'Description of Item 3' }
];
app.post('/items', (req, res) => {
const newItem = {
id: items.length + 1,
name: req.body.name,
description: req.body.description
};
items.push(newItem);
res.status(201).json(newItem);
});
app.get('/items', (req, res) => {
res.json(items);
});
app.get('/items/:id', (req, res) => {
const item = items.find(i => i.id === parseInt(req.params.id));
if (!item) return res.status(404).send('Item not found');
res.json(item);
});
app.put('/items/:id', (req, res) => {
const item = items.find(i => i.id === parseInt(req.params.id));
if (!item) return res.status(404).send('Item not found');
item.name = req.body.name;
item.description = req.body.description;
res.json(item);
});
app.delete('/items/:id', (req, res) => {
const itemIndex = items.findIndex(i => i.id === parseInt(req.params.id));
if (itemIndex === -1) return res.status(404).send('Item not found');
items.splice(itemIndex, 1);
res.status(204).send();
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
Explanation
- Explain the use of Express for setting up the server.
- Discuss the use of object literals to simulate a JSON database.
- Walk through each CRUD endpoint and its implementation.
Part 2: Creating the Client-Side Application
1. Create the HTML File
1. Create a file named `index.html`:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>REST API Client</title>
<style>
body {
font-family: Arial, sans-serif;
}
.container {
max-width: 600px;
margin: 0 auto;
}
input, button {
display: block;
width: 100%;
margin-bottom: 10px;
padding: 10px;
}
button {
background-color: #4CAF50;
color: white;
border: none;
cursor: pointer;
}
button:hover {
background-color: #45a049;
}
</style>
</head>
<body>
<div class="container">
<h1>REST API Client</h1>
<h2>Create Item</h2>
<input type="text" id="createName" placeholder="Name">
<input type="text" id="createDescription" placeholder="Description">
<button onclick="createItem()">Create</button>
<h2>Read Items</h2>
<button onclick="getItems()">Get All Items</button>
<ul id="itemsList"></ul>
<h2>Read Single Item</h2>
<input type="number" id="readId" placeholder="Item ID">
<button onclick="getItem()">Get Item</button>
<p id="singleItem"></p>
<h2>Update Item</h2>
<input type="number" id="updateId" placeholder="Item ID">
<input type="text" id="updateName" placeholder="New Name">
<input type="text" id="updateDescription" placeholder="New Description">
<button onclick="updateItem()">Update</button>
<h2>Delete Item</h2>
<input type="number" id="deleteId" placeholder="Item ID">
<button onclick="deleteItem()">Delete</button>
</div>
<script>
function createItem() {
const name = document.getElementById('createName').value;
const description = document.getElementById('createDescription').value;
fetch('/items', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ name, description })
})
.then(response => response.json())
.then(data => {
alert(`Item created: ${data.name}`);
getItems();
})
.catch(error => console.error('Error:', error));
}
function getItems() {
fetch('/items')
.then(response => response.json())
.then(data => {
const itemsList = document.getElementById('itemsList');
itemsList.innerHTML = '';
data.forEach(item => {
const listItem = document.createElement('li');
listItem.textContent = `${item.id}. ${item.name}: ${item.description}`;
itemsList.appendChild(listItem);
});
})
.catch(error => console.error('Error:', error));
}
function getItem() {
const id = document.getElementById('readId').value;
fetch(`/items/${id}`)
.then(response => response.json())
.then(data => {
document.getElementById('singleItem').textContent = `Name: ${data.name}, Description: ${data.description}`;
})
.catch(error => console.error('Error:', error));
}
function updateItem() {
const id = document.getElementById('updateId').value;
const name = document.getElementById('updateName').value;
const description = document.getElementById('updateDescription').value;
fetch(`/items/${id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ name, description })
})
.then(response => response.json())
.then(data => {
alert(`Item updated: ${data.name}`);
getItems();
})
.catch(error => console.error('Error:', error));
}
function deleteItem() {
const id = document.getElementById('deleteId').value;
fetch(`/items/${id}`, {
method: 'DELETE'
})
.then(() => {
alert('Item deleted');
getItems();
})
.catch(error => console.error('Error:', error));
}
</script>
</body>
</html>
```
Explanation
- Walk through the HTML structure, focusing on the forms and buttons for each CRUD operation.
- Explain how the JavaScript functions use the Fetch API to send requests to the server.
- Discuss how responses are handled and the DOM is updated.
---
Part 3: Running and Testing the Project
1. Ensure the server is running:
```bash
node server.js
```
2. Open the `index.html` file in a browser (you can use a local server like `http-server` for this):
npx http-server -c-1 -o
3. Test each functionality (Create, Read, Update, Delete) using the form inputs and buttons.
---
Conclusion:
- Recap the RESTful principles demonstrated:
stateless interactions, use of standard HTTP methods, and structured URLs.
- Highlight how the client-side application interacts with the server.
- Discuss potential improvements, such as form validation and better error handling.
#### **Extensions and Future Enhancements:**
- **Form Validation:** Add client-side validation to ensure all inputs are filled out correctly.
- **Error Handling:** Improve error handling to provide more detailed feedback to users.
- **UI Enhancements:** Enhance the user
interface with better styling and user experience features.
This lab exercise provides a comprehensive hands-on approach to understanding and implementing REST APIs, making it practical and engaging for students.