Skip to content

Commit

Permalink
Merge pull request #260 from 1simransaini/simran_branch
Browse files Browse the repository at this point in the history
Added Url-Shortener project under Node-JS-Projects
  • Loading branch information
Avdhesh-Varshney authored Jun 7, 2024
2 parents 1bc8b7b + 1ad1493 commit 6770bc3
Show file tree
Hide file tree
Showing 13 changed files with 405 additions and 0 deletions.
82 changes: 82 additions & 0 deletions Node-JS-Projects/Advanced/Url-Shortener/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<h1 align='center'><b>💥 URL-Shortner 💥</b></h1>

<!-- -------------------------------------------------------------------------------------------------------------- -->

<h3 align='center'>Tech Stack Used 🎮</h3>
<!-- enlist all the technologies used to create this project from them (Remove comment using 'ctrl+z' or 'command+z') -->

<div align='center'>
<img src="https://img.shields.io/badge/html5-%23E34F26.svg?style=for-the-badge&logo=html5&logoColor=white" alt="HTML5"/>
<img src="https://img.shields.io/badge/css3-%231572B6.svg?style=for-the-badge&logo=css3&logoColor=white" alt="CSS3"/>
<img src="https://img.shields.io/badge/javascript-%23323330.svg?style=for-the-badge&logo=javascript&logoColor=%23F7DF1E" alt="JavaScript"/>
<img src="https://img.shields.io/badge/node.js-6DA55F?style=for-the-badge&logo=node.js&logoColor=white" alt="Node.js"/>
<img src="https://img.shields.io/badge/express.js-%23404d59.svg?style=for-the-badge&logo=express&logoColor=%2361DAFB" alt="Express.js"/>
<img src="https://img.shields.io/badge/MongoDB-%234ea94b.svg?style=for-the-badge&logo=mongodb&logoColor=white" alt="MongoDB"/>
</div>



![Line](https://github.com/Avdhesh-Varshney/WebMasterLog/assets/114330097/4b78510f-a941-45f8-a9d5-80ed0705e847)

<!-- -------------------------------------------------------------------------------------------------------------- -->

## :zap: Description 📃

<div>
<!-- <p>Add Description of the project</p> -->
<p>A simple Node.js URL shortener using ExpressJS and MongoDB. The primary aim of a URL shortener is to convert long URLs into shorter, more manageable links. The shortened URL redirects users to the original, longer URL when accessed.</p>
</div>


<!-- -------------------------------------------------------------------------------------------------------------- -->

## :zap: How to run it? 🕹️

<!-- Add steps how to run this project -->
Follow these steps to set up the project locally:

### Clone the Repository

First, clone the repository to your local machine:

```bash
git clone https://github.com/1simransaini/Url-Shortener.git
```
Navigate to the project directory and install the required dependencies:
```bash
cd Url-Shortener
npm install
```
Create a .env file in the root of the project directory and add the following environment variables:
```bash
PORT=3000
MONGO_URL=yours
```
Run the program as
```bash
node src/server.js
```
<!-- -------------------------------------------------------------------------------------------------------------- -->

## :zap: Screenshots 📸
<!-- add the screenshot of the project (Mandatory) -->
![1](https://github.com/Avdhesh-Varshney/WebMasterLog/assets/91106038/26624ca0-5639-4fe4-9c7f-f0ec4241406a)

![Line](https://github.com/Avdhesh-Varshney/WebMasterLog/assets/114330097/4b78510f-a941-45f8-a9d5-80ed0705e847)

<!-- -------------------------------------------------------------------------------------------------------------- -->

<h4 align='center'>Developed By <b><i>Simran Saini</i></b> 👩</h4>
<p align='center'>
<a href='https://www.linkedin.com/in/1simransaini/'>
<img src='https://img.shields.io/badge/linkedin-%230077B5.svg?style=for-the-badge&logo=linkedin&logoColor=white' />
</a>
<a href='https://github.com/1simransaini'>
<img src='https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge&logo=github&logoColor=white' />
</a>
</p>

<h4 align='center'>Happy Coding 👩</h4>

<h3 align="center">Show some &nbsp;❤️&nbsp; by &nbsp;🌟&nbsp; this repository!</h3>

18 changes: 18 additions & 0 deletions Node-JS-Projects/Advanced/Url-Shortener/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "urlshortner",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "nodemon src/server.js",
"start": "nodemon src/server.js"
},
"author": "Simran Saini",
"license": "ISC",
"dependencies": {
"body-parser": "^1.20.2",
"dotenv": "^16.3.1",
"express": "^4.18.2",
"mongoose": "^7.5.1"
}
}
106 changes: 106 additions & 0 deletions Node-JS-Projects/Advanced/Url-Shortener/public/css/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
body {
font-family: 'Arial', sans-serif;
background-color: #e0e0e0; /* background color */
margin: 0;
padding: 0;
line-height: 1.6;
}

.container {
max-width: 600px;
margin: 50px auto;
background-color: #ffffff; /* background color */
padding: 20px;
border-radius: 5px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
}

header {
text-align: center;
margin-bottom: 20px;
background-color: #007BFF; /* Added background color */
padding: 10px;
border-radius: 5px 5px 0 0;
}

header h1 {
color: #ffffff; /* text color */
margin: 0;
font-size: 2em;
}

header p {
color: #dddddd; /* text color */
font-size: 1em;
}

input[type="url"] {
width: 100%;
padding: 10px;
margin-bottom: 10px;
border: 1px solid #ddd;
border-radius: 5px;
box-sizing: border-box;
transition: border-color 0.3s;
}

input[type="url"]:focus {
border-color: #007BFF;
outline: none;
}

button {
width: 100%;
padding: 10px;
background-color: #28a745; /* background color */
color: #fff;
border: none;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s, transform 0.3s;
}

button:hover {
background-color: #218838; /* hover background color */
transform: scale(1.05);
}

button:active {
background-color: #1e7e34; /* active background color */
}

#result {
margin-top: 20px;
text-align: center;
font-size: 18px;
color: #28a745; /* text color */
}

#result a {
color: #155724; /* link color */
text-decoration: none;
transition: color 0.3s;
}

#result a:hover {
color: #0c3d12; /* hover link color */
}

@media (max-width: 600px) {
.container {
margin: 20px;
padding: 15px;
}

header h1 {
font-size: 1.5em;
}

header p {
font-size: 0.9em;
}

button {
padding: 12px;
}
}
26 changes: 26 additions & 0 deletions Node-JS-Projects/Advanced/Url-Shortener/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>URL SHORTENER</title>
<link rel="stylesheet" href="css/styles.css">
</head>

<body>
<div class="container">
<header>
<h1>URL SHORTENER</h1>
<p>Shorten your lengthy URLs in a snap!!</p>
</header>
<main>
<input type="url" id="originalUrl" placeholder="Enter your long URL here">
<button id="shortenBtn">Shorten</button>
<div id="result"></div>
</main>
<script src="js/main.js"></script>
</div>
</body>

</html>
30 changes: 30 additions & 0 deletions Node-JS-Projects/Advanced/Url-Shortener/public/js/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
document.getElementById('shortenBtn').addEventListener('click', async () => {
const originalUrl = document.getElementById('originalUrl').value;
if (!originalUrl || !isValidUrl(originalUrl)) {
alert('Please enter a valid URL');
return;
}
try {
const response = await fetch('/shorten', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ originalUrl })
});
const data = await response.json();
document.getElementById('result').textContent = `Shortened URL : ${window.location.href}${data.shortUrl}`;
} catch (err) {
console.error('Error shortening the URL : ', err);
alert('Error shortening the URL , PLEASE TRY AGAIN');
}

});
function isValidUrl(string) {
try {
new URL(string);
return true;
} catch (_) {
return false;
}
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// src/controllers/urlController.js
const Url = require('../models/urlModel');
const UrlShortener = require('../utils/urlShortener');

class UrlController {
static async shortenUrl(req, res) {
try {
const { originalUrl } = req.body;
if (!originalUrl || typeof originalUrl !== 'string') {
return res.status(400).json({ message: "A valid URL is required" });
}

// Check if the URL is already shortened
const url = await Url.findOne({ originalUrl });
if (url) {
return res.json(url);
}

// Generate a short URL
const shortUrl = UrlShortener.generateShortUrl();

// Save to the database
const newUrl = new Url({ originalUrl, shortUrl });
await newUrl.save();
res.json(newUrl);
} catch (err) {
res.status(500).json({ message: 'Server error: ' + err.message });
}
}

static async redirectToOriginalUrl(req, res) {
try {
const { shortUrl } = req.params;
if (!shortUrl || typeof shortUrl !== 'string') {
return res.status(400).send('Invalid short URL');
}

const url = await Url.findOne({ shortUrl });
if (!url) {
return res.status(404).send('URL NOT FOUND');
}

// Increase the count
url.clicks += 1;
await url.save();
res.redirect(url.originalUrl);
} catch (err) {
console.error(err);
res.status(500).send('Server Error');
}
}
}

module.exports = UrlController;
16 changes: 16 additions & 0 deletions Node-JS-Projects/Advanced/Url-Shortener/src/db.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const mongoose = require('mongoose');
//requing the .env file
require('dotenv').config();
const connectDB = async () => {
try {
await mongoose.connect(process.env.MONGO_URL, {
useNewUrlParser: true,
useUnifiedTopology: true
});
console.log("Connected to MONGODB ...")
} catch (err) {
console.error('Error connecting to database : ', err);
}
}

module.exports = connectDB;
22 changes: 22 additions & 0 deletions Node-JS-Projects/Advanced/Url-Shortener/src/models/urlModel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const mongoose = require('mongoose');
const urlSchema = new mongoose.Schema({
originalUrl: {
type: String,
required: true
},
shortUrl: {
type: String,
required: true,
unique: true
},
clicks: {
type: Number,
default: 0
},
createdAt: {
type: Date,
default: Date.now
}
});
const Url = mongoose.model('Url', urlSchema);
module.exports = Url;
19 changes: 19 additions & 0 deletions Node-JS-Projects/Advanced/Url-Shortener/src/routes/urlRoutes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// src/routes/urlRoutes.js
const express = require('express');
const rateLimit = require('express-rate-limit');
const urlController = require('../controllers/urlController');

const router = express.Router();

// Define rate limit rule
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
message: "Too many requests from this IP, please try again later."
});

// Apply the rate limiting middleware to relevant routes
router.post('/shorten', limiter, urlController.shortenUrl);
router.get('/:shortUrl', limiter, urlController.redirectToOriginalUrl);

module.exports = router;
Loading

0 comments on commit 6770bc3

Please sign in to comment.