From 8072461ab2380a2aef8cb71ea2928c3b1458c317 Mon Sep 17 00:00:00 2001 From: Manish Date: Tue, 28 Mar 2023 14:38:44 +1100 Subject: [PATCH] Impl: project requirements --- index.js | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 123 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 3048242..6d9059f 100644 --- a/index.js +++ b/index.js @@ -2,9 +2,59 @@ require("dotenv").config(); const express = require("express"); const cors = require("cors"); const app = express(); +const mongoose = require("mongoose"); +const dns = require("dns"); // Basic Configuration const port = process.env.PORT || 3000; +const MONGODB_URI = process.env.MONGODB_URI || ""; + +mongoose.connect(MONGODB_URI, { + // @ts-ignore + useNewUrlParser: true, + useUnifiedTopology: true, +}); + +const urlSchema = new mongoose.Schema({ + original: { + type: String, + unique: true, + }, + short: { type: Number, unique: true }, +}); + +const Url = mongoose.model("Url", urlSchema); + +const counterSchema = new mongoose.Schema({ + name: { type: String, unique: true }, + seq: { type: Number, default: 0 }, +}); + +const Counter = mongoose.model("Counter", counterSchema); + +let shortUrlsCounter = 0; + +Counter.findOne({ name: "shortUrl" }) + .then((counter) => { + if (counter) { + shortUrlsCounter = counter.seq; + console.log(`Old counter: ${counter}`); + } else { + const shortUrlsCounterModel = new Counter({ name: "shortUrl" }); + shortUrlsCounterModel + .save() + .then((counter) => { + if (counter) { + shortUrlsCounter = counter.seq; + console.log(`New counter: ${counter}`); + } else { + console.log(`Error: could not create a new counter`); + } + }) + .catch((err) => console.log(err)); + } + }) + .catch((err) => console.log(err)); app.use(cors()); @@ -14,9 +64,80 @@ app.get("/", function (req, res) { res.sendFile(process.cwd() + "/views/index.html"); }); +app.use(express.urlencoded({ extended: false })); + // Your first API endpoint -app.get("/api/hello", function (req, res) { - res.json({ greeting: "hello API" }); +app.post("/api/shorturl/", (req, res) => { + const original = req.body.url; + try { + const hostname = new URL(original).hostname; + dns.lookup(hostname, (err, addr, family) => { + if (err) { + console.log(`Invalid url:\n${err}`); + res.json({ error: "Invalid URL" }); + } else { + Url.findOne({ original: original }) + .then((url) => { + if (url) + return res.json({ + original_url: original, + short_url: url?.short, + }); + const urlModel = new Url({ + original: original, + short: shortUrlsCounter++, + }); + Counter.findOneAndUpdate( + { name: "shortUrl" }, + { $set: { seq: shortUrlsCounter } }, + { new: true } + ) + .then((counter) => { + if (counter) + console.log(`${counter?.name} updated to ${counter?.seq}`); + else { + console.log(`Could not find "shortUrl" counter in DB`); + return res.sendStatus(500); + } + }) + .catch((err) => { + console.log(`Error updating shortUrl counter in DB:\n${err}`); + return res.sendStatus(500); + }); + urlModel + .save() + .then((url) => { + if (url) + return res.json({ + original_url: original, + short_url: url?.short, + }); + console.log(`Unlikely scenario occurred!:\n${url}`); + res.sendStatus(500); + }) + .catch((err) => { + console.log(`Inserting url to DB failed!:\n${err}`); + res.sendStatus(500); + }); + }) + .catch((err) => { + console.log(`Query failed!:\n${err}`); + res.sendStatus(500); + }); + } + }); + } catch (err) { + res.json({ error: "Invalid URL" }); + } +}); + +app.get("/api/shorturl/:shorturl", (req, res) => { + const shorturl = Number(req.params.shorturl); + Url.findOne({ short: shorturl }) + .then((url) => res.redirect(url.original)) + .catch((err) => + res.json({ error: "No short URL found for the given input" }) + ); }); app.listen(port, function () {