Skip to content

surajsinghgore/urlshortener

Repository files navigation

URL SHORTENER

This project allow user to sort long URL easily using this project

Features

  • URL SHORTENER
  • VALIDATE URL
  • RESPONSIVE
  • SIMPLE DESIGN

Environment Variables

To run this project, you will need to add the following environment variables to your .env.local file

DATABASE_URL

MONGODB schema

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

SETUP MONGODB CONNECTION

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' })
 
 }
}

SERVER APIS

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" });
  }
}

CLIENT SIDE

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>
  )
}

Screenshots

App Screenshot

App Screenshot

Authors

Feedback

If you have any feedback, please reach out to us at [email protected]

Badges

Add badges from somewhere like: shields.io

MIT License GPLv3 License AGPL License

Tech Stack

Client: NEXTJS, TailwindCSS

Server: Node, Express,Nanoid

Roadmap

  • 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

About

URL SHORTENER PROVIDE YOU SERVICE TO SHORT FOR URL

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages