Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
node_modules/
node_modules/
.env
13 changes: 13 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const { validateUrlInput } = require('./middlewares/urlMiddleware');



const indexRouter = require('./routes/index');

Expand All @@ -12,13 +15,23 @@ const app = express();
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');


app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
require('dotenv').config()
const mongoose = require('mongoose')
const connectDB = require('./config/dbConfig')


app.use('/', indexRouter);
//app.use('/shorten', indexRouter);


// Connect to MongoDB
connectDB();

// catch 404 and forward to error handler
app.use(function (req, res, next) {
Expand Down
3 changes: 3 additions & 0 deletions bin/www
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@ var app = require('../app');
var debug = require('debug')('url-shortener-app:server');
var http = require('http');


/**
* Get port from environment and store in Express.
*/

var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);



/**
* Create HTTP server.
*/
Expand Down
14 changes: 14 additions & 0 deletions config/dbConfig.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
require('dotenv').config()
const mongoose = require('mongoose')

const connectDB = async () => {
try {
await mongoose.connect(process.env.DATABASE_URI, {
})
console.log('MongoDB connected')
} catch (error) {
console.error(error.message)
process.exit(1)
}
}
module.exports = connectDB;
67 changes: 67 additions & 0 deletions controllers/urlController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
const URL = require('../models/urlSchema');
const { validateUrlInput } = require('../middlewares/urlMiddleware');

exports.shortenUrl = async (req, res) => {
const { originalUrl, alias } = req.validatedData;

try {
let url;
if (alias) {
url = await URL.findOne({ alias });
if (url) {
return res.status(400).json({ message: 'Alias already in use' });
}
}

const shortUrl = `http://localhost:3000/${alias}`;
url = new URL({ originalUrl, shortUrl, alias });
await url.save();

res.status(201).json(url);
} catch (error) {
return res.status(500).render('error', { message: error.message, error: { status: 500 } });
}
};

exports.redirectToOriginalUrl = async (req, res) => {
const shortUrl = req.params.alias;

try {
const url = await URL.findOneAndUpdate(
{ alias: shortUrl },
{ $inc: { clickCount: 1 } },
{ new: true }
);
if (url) {
return res.redirect(url.originalUrl);
} else {
return res.status(404).render('error', { message: 'URL not found', error: { status: 404 } });
}
} catch (error) {
return res.status(500).render('error', { message: error.message, error: { status: 500 } });
}
};

exports.getUrlStats = async (req, res) => {
const shortUrl = req.params.alias;

try {
const url = await URL.findOne({ alias: shortUrl });
if (url) {
res.render('stats', { originalUrl: url.originalUrl, clickCount: url.clickCount });
} else {
return res.status(404).render('error', { message: 'URL not found', error: { status: 404 } });
}
} catch (error) {
return res.status(500).render('error', { message: error.message, error: { status: 500 } });
}
};

exports.getAllUrls = async (req, res) => {
try {
const urls = await URL.find();
res.json(urls);
} catch (error) {
return res.status(500).render('error', { message: error.message, error: { status: 500 } });
}
};
20 changes: 20 additions & 0 deletions middlewares/urlMiddleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const validUrl = require('valid-url');

const validateUrlInput = (req, res, next) => {
const { originalUrl, alias } = req.body;
if (!originalUrl) {
return res.status(400).json({ message: 'Original URL is required' });
}
if(!alias) {
req.body.alias = Math.random().toString(36).substring(7);
}
if (!validUrl.isUri(originalUrl)) {
return res.status(400).json({ message: 'Invalid original URL' });
}
req.validatedData = { originalUrl, alias };
next();
};

module.exports = {
validateUrlInput,
};
30 changes: 30 additions & 0 deletions models/urlSchema.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const mongoose = require('mongoose')

const urlSchema = new mongoose.Schema({
originalUrl: {
type: String,
required: true
},
shortUrl: {
type: String,
required: true,
unique: true
},
alias: String,
createdAt: {
type: Date,
default: Date.now
},
updatedAt: {
type: Date,
default: Date.now
},
clickCount:{
type: Number,
default: 0
}
});

const URL = mongoose.model('URL', urlSchema);

module.exports = URL;
Loading