Building and Deploying a Number Classification API with JavaScript | DevOps 1
Introduction
In this blog post, I'll walk you through my journey of building and deploying a Number Classification API using JavaScript. This project was part of the HNG DevOps Stage 1 task, designed to enhance my understanding of APIs, server-side development, and cloud deployment.
The API classifies numbers based on interesting mathematical properties like primality, Armstrong status, digit sum, and parity (odd/even). Additionally, it fetches a fun fact about the number from the Numbers API.
Project Setup
1. Initializing the Project
I started by setting up a Node.js environment:
mkdir number-classification-api
cd number-classification-api
npm init -y
Then, I installed the necessary packages:
npm install express cors axios
Express: For handling API requests.
CORS: To enable cross-origin resource sharing.
Axios: For making HTTP requests to the Numbers API.
2. Developing the API
I created an index.js
file:
const express = require('express');
const cors = require('cors');
const axios = require('axios');
const app = express();
app.use(cors());
app.get('/api/classify-number', async (req, res) => {
const number = req.query.number;
if (isNaN(number)) {
return res.status(400).json({ number, error: true });
}
const num = parseInt(number);
const isPrime = (n) => {
if (n < 2) return false;
for (let i = 2; i <= Math.sqrt(n); i++) {
if (n % i === 0) return false;
}
return true;
};
const isArmstrong = (n) => {
const digits = n.toString().split('').map(Number);
return digits.reduce((acc, digit) => acc + Math.pow(digit, digits.length), 0) === n;
};
const digitSum = num.toString().split('').reduce((acc, digit) => acc + Number(digit), 0);
let properties = [];
if (isArmstrong(num)) properties.push('armstrong');
properties.push(num % 2 === 0 ? 'even' : 'odd');
try {
const funFact = await axios.get(`http://numbersapi.com/${num}/math?json`);
res.json({
number: num,
is_prime: isPrime(num),
is_perfect: false, // Placeholder
properties,
digit_sum: digitSum,
fun_fact: funFact.data.text
});
} catch (error) {
res.status(500).json({ error: 'Error fetching fun fact' });
}
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
3. Testing Locally
I tested the API using Postman and my browser:
node index.js
Then visited: http://localhost:3000/api/classify-number?number=371
Deployment on DigitalOcean
1. Setting Up the Server
I used DigitalOcean to deploy the API:
Droplet Creation: Created an Ubuntu droplet.
SSH Access:
ssh root@<your-server-ip>
Updating the System:
sudo apt update && sudo apt upgrade -y
2. Installing Node.js and Git
sudo apt install nodejs npm git -y
3. Cloning the Repository
cd /var/www
sudo git clone https://github.com/your-username/number-classification-api.git
cd number-classification-api
npm install
4. Running the API
node index.js
To keep it running in the background:
npm install -g pm2
pm2 start index.js
5. Setting Up NGINX (Reverse Proxy)
sudo apt install nginx -y
sudo nano /etc/nginx/sites-available/number-api
NGINX Config:
server {
listen 80;
server_name <your-server-ip>;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
Enable and restart NGINX:
sudo ln -s /etc/nginx/sites-available/number-api /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
Now, the API is accessible at http://<your-server-ip>/api/classify-number?number=371
Challenges Faced
CORS Errors: Initially, I forgot to enable CORS, which caused errors when accessing the API from different origins. Adding
app.use(cors())
fixed this.Server Downtime: The Node server stopped after SSH sessions ended. I resolved this using PM2.
NGINX Configuration: Misconfigured reverse proxy settings caused 502 errors. Double-checking NGINX logs helped me debug (
sudo tail -f /var/log/nginx/error.log
).
Key Learnings
Improved my API development skills with Express.
Understood the importance of input validation and error handling.
Gained practical experience with deploying applications on DigitalOcean and configuring NGINX.
References
Conclusion
This project was an exciting dive into the world of APIs and cloud deployment. I enjoyed the hands-on experience of building something functional and deploying it for real-world access. If you're new to DevOps, I highly recommend trying out similar projects to solidify your learning.
You can check out the live API here and explore the GitHub repository.
Happy coding! ๐