This project allow user to sort long URL easily using this project
- URL SHORTENER
- VALIDATE URL
- RESPONSIVE
- SIMPLE DESIGN
To run this project, you will need to add the following environment variables to your .env.local file
DATABASE_URL
1.pages/api/schema/urlSchema
const mongoose =require('mongoose');
const urlSchema=new mongoose.Schema({
shortId:{
type:String,required:true,unique:true
},
redirectURL:{type:String,required:true},
Clicks:[{timestamp:{type:Number}}]
},
{timestamps:true}
);
mongoose.models = {};
const URLSCHEMA=mongoose.model('URL',urlSchema );
module.exports=URLSCHEMA
2.pages/api/middleware/DbConnection
const mongoose=require('mongoose');
mongoose.set('bufferCommands', false);
export default async function DbConnection(req,res) {
try{
mongoose.connect(process.env.NEXT_PUBLIC_DBCONNECT)
}
catch(e){
return res.status(500).json({ message:'DATABASE CONNECTION ERROR' })
}
}
3.pages/api/URLPOST
// generating unique id
import { nanoid } from "nanoid";
const validUrl = require("valid-url");
import URLSCHEMA from "./schema/UrlSchema";
import DbConnection from "./middleware/DbConnection";
export default async function handler(req, res) {
if (req.method == "POST") {
// require elements from body
let {url}=req.body
await DbConnection();
// url validation
if (url === undefined) {
return res.status(400).json({ message: "URL is Mandatory Field" });
} else if (url === "") {
return res.status(400).json({ message: "URL Field Not be Blank" });
}
// checking valid URL or NOT
if (validUrl.isWebUri(url)) {
// find record to solve dublicasy in database
let data = await URLSCHEMA.find({ redirectURL: url });
// checking weather redirect URl already Exists or Not
// Already somebody generated Redirect URL
if (data.length != 0) {
return res
.status(200)
.json({ message: "Short URL GENERATED", data: data[0] });
} else {
// shortId generated
let shortId = nanoid(8);
if (shortId.length !== 8) {
return res.status(400).json({ message: "Please Try Again" });
}
const dataSend = new URLSCHEMA({
shortId,
redirectURL: url,
});
let dataRes=await dataSend.save();
return res
.status(200)
.json({ message: "Short URL GENERATED", data:dataRes });
}
}
// not valid URL
else {
return res.status(400).json({ message: "Please Provide Valid URL" });
}
} else {
return res.status(500).json({ message: "Only POST REQUEST IS ALLOWED" });
}
}
4.pages/api/RedirectURL
import URLSCHEMA from "./schema/UrlSchema";
import DbConnection from "./middleware/DbConnection";
export default async function handler(req, res) {
if (req.method == "GET") {
// require elements from body
let shortId = req.query.shortID;
if (shortId === undefined) {
return res.status(400).json({ message: "ShortId must Be there" });
}
await DbConnection();
const dataFetch = await URLSCHEMA.findOneAndUpdate(
{ shortId },
{ $push: { Clicks: { timestamp: Date.now() } } }
);
if (dataFetch === null) {
return res.status(400).json({ message: "Invalid ShortId Provided" });
}
return res.status(200).json({redirectURL:dataFetch.redirectURL})
} else {
return res.status(500).json({ message: "Only GET REQUEST IS ALLOWED" });
}
}
5.FETCH pages/api/URLPOST to sort URL
provide Original URL
const shortUrl=async()=>{
let res=await fetch('URL/api/URLPOST',{
method:"POST",
headers:{"Content-Type": "application/json"},
body:JSON.stringify({url:input})
})
let data=await res.json();
// error
if(res.status==500){
addToast(data.message, {
appearance: 'error',
autoDismiss: true,
})
}
// 400
else if(res.status==400){
addToast(data.message, {
appearance: 'warning',
autoDismiss: true,
})
}
else{
sessionStorage.setItem('shortId',`${URL}${data.data.shortId}`)
sessionStorage.setItem('redirectURL',data.data.redirectURL)
setRedirectUrl(data.data.redirectURL)
sessionStorage.setItem('ClickLength',data.data.Clicks.length)
setClickCount(data.data.Clicks.length)
setSortID(`${URL}${data.data.shortId}`)
setInput(`${URL}${data.data.shortId}`)
addToast(data.message, {
appearance: 'success',
autoDismiss: true,
})
}
}
6.REDIRECT to Original URL from setSortID
pages/api/RedirectURL to sort URL
provide Original URL
[index].js
import { useRouter } from 'next/router'
export default function Index() {
const { addToast } = useToasts()
const router = useRouter();
const shortID=router.query.index;
const redirectUrl=async()=>{
if(shortID!==undefined){
const res=await fetch(`url/api/RedirectToURL?shortID=${shortID}`)
const data=await res.json();
// 500
if(res.status==500){
addToast(data.message, {
appearance: 'error',
autoDismiss: true,
})
}
// 400
else if(res.status==400){
addToast(data.message, {
appearance: 'warning',
autoDismiss: true,
})
}
window.location.href = data.redirectURL
}
}
useEffect(()=>{
if(shortID!==undefined){
redirectUrl();
}
})
return (
<div style={{backgroundColor:'white'}}></div>
)
}
If you have any feedback, please reach out to us at surajthakurrs45@gmail.com
Add badges from somewhere like: shields.io
Client: NEXTJS, TailwindCSS
Server: Node, Express,Nanoid
- Setup nextjs Project
- Installed required project libraries
- Setup mongodb database to store original url and also generate shortid using library nanoid
- create UI to take URl from Clients
- Store details in database and return shortid to Clients